Creación de Proyectos Java para Pruebas y Depuración con Selenium y Appium

El desarrollo de software moderno, especialmente en el ámbito de las aplicaciones móviles y web, exige rigurosos procesos de prueba y depuración para garantizar la calidad, fiabilidad y seguridad del producto final. Java, como lenguaje de programación robusto y versátil, ofrece un ecosistema potente para abordar estas necesidades. Este artículo detalla el proceso de creación de un proyecto Java enfocado en la automatización de pruebas, utilizando herramientas como Selenium y Appium para interactuar con aplicaciones móviles, y Cucumber para definir escenarios de prueba de manera legible. Además, se explorarán las técnicas y herramientas esenciales para la depuración de código Java, un aspecto fundamental para identificar y corregir errores de manera eficiente.

Diagrama de flujo de desarrollo de software con pruebas automatizadas

Configuración del Proyecto y Librerías

La base de cualquier proyecto de automatización de pruebas reside en una configuración adecuada y la selección de las librerías necesarias. Para este proyecto, que se centra en la prueba de una aplicación móvil, la combinación de Selenium y Appium es crucial. Selenium es una suite de herramientas para automatizar la interacción con navegadores web, mientras que Appium extiende esta capacidad a las aplicaciones móviles nativas, híbridas e híbridas.

Cada feature en el contexto de Cucumber, una herramienta de automatización de pruebas basada en comportamiento (BDD), está compuesto por un Background (opcional, para pasos previos comunes) y uno o más scenarios. En nuestro caso, definiremos un feature titulado "Make login in the mobile application" con la descripción "As a user I want to make login in the mobile appication". Este feature contendrá un escenario que simula el acceso a la pantalla inicial de una aplicación móvil, introduce credenciales de usuario y contraseña, y verifica que el inicio de sesión sea exitoso.

Análisis de Ficheros y Estructura de Pruebas con Cucumber

Cucumber utiliza palabras clave específicas para definir la estructura de las pruebas, lo que permite que los escenarios sean comprensibles tanto para los desarrolladores como para los stakeholders no técnicos.

Keyword: FEATURE

El keyword FEATURE se utiliza para definir el título y una breve descripción del conjunto de pruebas. Como se mencionó, nuestro feature se titula "Make login in the mobile application" y su propósito es "As a user I want to make login in the mobile appication".

Keyword: BACKGROUND

El BACKGROUND es opcional y se emplea cuando se requieren pasos previos antes de ejecutar los escenarios dentro de un feature. En este proyecto, antes de ejecutar el escenario de login, necesitamos tener un usuario disponible y acceso a la aplicación. Una alternativa a BACKGROUND es utilizar los keywords Given y And dentro de un escenario específico. Sin embargo, si estos pasos previos se repiten en múltiples escenarios, es más coherente y DRY (Don't Repeat Yourself) utilizar BACKGROUND.

Keyword: SCENARIO

El SCENARIO define una prueba individual dentro de un feature. Podemos tener uno o más escenarios para probar diferentes aspectos de una misma funcionalidad. En este proyecto, probaremos que el login se efectúa de forma correcta. Si deseáramos probar también un escenario de login incorrecto, crearíamos un nuevo SCENARIO dentro del mismo feature. Cada escenario se define con pasos que comienzan con When (cuando se realiza una acción) y Then (entonces se verifica un resultado). Por ejemplo, un paso When podría ser "introducir usuario y contraseña", y un paso Then sería "el login es correcto".

Ejemplo de estructura de un archivo .feature de Cucumber

Variantes de Archivos de Feature

Se pueden definir features sin BACKGROUND o añadir múltiples SCENARIOs para cubrir diferentes casos de prueba. Por ejemplo, un feature sin BACKGROUND podría tener todos los pasos de configuración dentro de cada SCENARIO. La adición de un nuevo SCENARIO permitiría probar, por ejemplo, un intento de login fallido.

Generación de Código Fuente en Java y Ejecución

Una vez que el proyecto está configurado con las librerías necesarias y los escenarios de prueba definidos en archivos .feature, el siguiente paso es la codificación en Java y la ejecución de las pruebas.

Fichero: params.properties

Para gestionar la configuración de manera flexible y evitar codificar valores directamente en el código fuente, se utiliza un archivo params.properties. Este archivo contendrá parámetros esenciales como la ruta de la aplicación móvil a probar, las credenciales de usuario (usuario y contraseña), el identificador del dispositivo para la prueba y la dirección del servidor Appium local.

Adicionalmente, se creará una clase personalizada para facilitar la lectura de este archivo de propiedades.

Fichero: RunCukeTest.java

Este fichero actúa como el punto de entrada para la ejecución de las pruebas de Cucumber. Utilizando JUnit, RunCukeTest.java indicará a Cucumber que ejecute los tests, especificará la ruta donde se encuentran los archivos .feature y configurará los plugins para la generación de reportes de resultados.

Fichero: User.java

Se creará una clase User (bean) para representar la entidad de usuario. Esta clase contendrá campos para el nombre de usuario y la contraseña, junto con su constructor y métodos accesores (getters y setters).

Fichero: BaseAppium.java

Esta clase será responsable de inicializar la sesión de Appium. Codificará la lógica para establecer las capacidades (capabilities) necesarias tanto a nivel del servicio de Appium como del driver, arrancar la sesión del servidor Appium y, finalmente, crear el objeto driver que se utilizará para interactuar con la aplicación móvil.

Diagrama de arquitectura de Appium

Fichero: Login.java

En esta clase se implementará la lógica específica para la funcionalidad de login. Obtendrá los elementos de la interfaz de usuario de la pantalla de login a través del driver de Appium, aplicará los valores correspondientes (usuario y contraseña) y codificará la acción de verificar si el login fue exitoso. También incluirá la implementación de la acción de logout. Esta clase extenderá de BaseAppium.java para heredar el acceso al driver.

Fichero: LoginSteps.java

Este es el fichero donde se implementarán los pasos definidos en los archivos .feature. Cada paso (step) del archivo .feature tendrá una anotación @Given, @When, o @Then seguida de una expresión regular que coincida con el texto del paso. El código dentro de estos métodos interactuará con la clase Login.java y el driver para ejecutar las acciones y validaciones correspondientes.

Depuración y Pruebas Unitarias en Java

Java no solo es potente para el desarrollo, sino también para la depuración y las pruebas. Probar un sistema operativo con Java implica verificar su funcionalidad, fiabilidad y seguridad. Java se puede usar para probar un sistema operativo de tres maneras: escribiendo casos de prueba en Java, usando marcos de prueba de Java o utilizando herramientas de prueba de Java.

Herramientas de Depuración en Java

Para la depuración de código Java, existen varias herramientas esenciales:

  • Eclipse IDE: Un entorno de desarrollo integrado (IDE) que soporta el desarrollo y la depuración de Java, permitiendo ejecutar y depurar código directamente en el sistema operativo o en un simulador/emulador.
  • JDB (Java Debugger): Una herramienta de línea de comandos que forma parte del Java Development Kit (JDK) y permite la depuración interactiva del código Java.
  • JDWP (Java Debug Wire Protocol): Un protocolo que define la comunicación entre un depurador de Java y una Java Virtual Machine (JVM).
  • JDI (Java Debug Interface): Una interfaz que define cómo un depurador de Java accede y manipula la JVM.

La elección de la herramienta adecuada dependerá del tipo de sistema operativo, su versión y la plataforma. Es crucial mantener un estilo de codificación coherente y convenciones de nomenclatura claras para el código Java, los casos de prueba y los informes.

Uso del Depurador con Eclipse

Técnicas de Depuración

Durante la depuración, se pueden utilizar:

  • Puntos de interrupción (Breakpoints): Permiten detener la ejecución del programa en una línea de código específica.
  • Puntos de inspección (Watchpoints): Permiten monitorear el valor de una variable.
  • Registro (Logging): La inclusión de sentencias de impresión o uso de librerías de logging para rastrear el flujo del programa y los valores de las variables.

Pruebas Unitarias con JUnit

Las pruebas unitarias en Java son fundamentales para la eficiencia y la simplicidad en el desarrollo de software a gran escala. Permiten reducir horas de depuración y agilizar la colaboración. La idea principal es escribir pruebas atómicas para características individuales y luego integrar más funcionalidades probadas.

¿Cómo escribir una prueba JUnit en Java?

Se utiliza un marco de prueba popular como JUnit. La práctica convencional es escribir clases de prueba separadas para cada clase de código fuente.

  1. Estructura de la Clase de Prueba:

    import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.*;class MathTest {
    @Testvoid add_twoNumbers_returnsCorrectSum() { // Arrange (preparación) int expected = 4; // Act (acción) int actual = Math.add(2, 2); // Assert (verificación) assertEquals("2+2 should equal 4", expected, actual);}@Testvoid divide_byZero_throwsArithmeticException() { // Arrange int number = 5; // Act & Assert assertThrows(ArithmeticException.class, () -> { Math.divide(number, 0); });}
    }
  2. Anotaciones: @Test marca un método como un caso de prueba.

  3. Assertions: Métodos como assertEquals(), assertTrue(), assertThrows() se utilizan para verificar si el comportamiento actual coincide con el esperado.

  4. Convenciones de Nomenclatura: Los nombres de los métodos de prueba deben ser descriptivos, indicando la función probada, los parámetros y el resultado esperado.

Preguntas Comunes de Entrevista JUnit

  • Fallo automático de una prueba: Se puede usar fail("descripción del error");.
  • Métodos setUp() y tearDown(): Se utilizan anotaciones como @BeforeAll, @BeforeEach, @AfterAll, @AfterEach para ejecutar código antes o después de las pruebas.

Errores de Sintaxis vs. Errores Lógicos

Los errores de sintaxis son generalmente fáciles de identificar y corregir gracias a las herramientas del IDE (como las marcas rojas que indican un punto y coma faltante). Los errores lógicos, por otro lado, requieren un análisis más profundo del flujo del programa.

Guía Paso a Paso para la Depuración

  1. Crear Paquetes y Clases: Organizar el código en paquetes y clases lógicas.
  2. Método main(): Utilizarlo como punto de entrada para ejecutar el programa.
  3. Declaraciones de Salida Simples: Añadir System.out.println() para verificar la ejecución básica.
  4. Estructura de Archivos: Asegurarse de que los archivos .java y los archivos compilados estén en los directorios correctos.
  5. Identificar Errores de Sintaxis: Prestar atención a los mensajes de error del IDE y a las marcas visuales.
  6. Usar el Depurador: Establecer puntos de interrupción y ejecutar el programa en modo de depuración.
  7. Monitorear Valores de Variables: Observar el estado de las variables en el depurador para identificar discrepancias lógicas.
  8. Continuar la Ejecución: Una vez analizado el estado, continuar la ejecución para ver el efecto de las correcciones.
  9. Comprender Otros Tipos de Errores: Ser consciente de los diferentes tipos de errores y cómo abordarlos sistemáticamente.

Encontrar y corregir errores es una habilidad fundamental para cualquier programador. El uso del depurador del IDE, la revisión de la estructura del código y la comprensión de los errores de sintaxis son pasos cruciales para desarrollar software de alta calidad.

tags: #crear #un #proyecto #en #java #llamado