Tests en Java guiados por datos con EasyTest

0
6897

En este tutorial veremos como utilizar la librería EasyTest para realizar pruebas guiadas por datos de nuestras clases Java corriendo sobre JUnit.

0. Índice de contenidos

1. Introducción

Creo que a todos, cuando queremos probar nuestras aplicaciones Java, lo primero que se nos viene a la mente es JUnit, el poderoso framework que nos permite evaluar el correcto funcionamiento de los métodos que implementan nuestras clases. Sin embargo, a veces olvidamos que sobre JUnit se han desarrollado una serie de frameworks que extienden y complementan las librerías principales de esta herramienta de testeo. EasyTest es uno de estos estos frameworks, cuyo objetivo es proporcionar un mecanismo adecuado para realizar tests guiados por datos. De esta forma, haciendo uso de ficheros Excel, CSV, XML u otro tipo de ficheros formateados en el que se definen los casos de prueba y a través de una serie de anotaciones ejecutar los tests.

Si bien es cierto que JUnit ya ofrece una serie de mecanismos para realizar algo parecido a tests guiados por datos, no son del todo limpios e implican que el usuario escriba mucha cantidad de código innecesario. Esto es lo que intenta solucionar EasyTest, proporcionando un framework enfocado a realizar este tipo de pruebas.

Las características principales de EasyTest son:

  • Escribir tests guiados por pruebas donde los datos se pueden especificar externamente haciendo uso de ficheros con formato.
  • Pasar datos de entrada como parámetros de los métodos de test utilizando la anotación @Param.
  • Devolver datos de los casos de prueba y capturar la salida en un fichero.
  • Los parámetros de entrada pasados al método de prueba pueden ser Java types o tipos definidos por el usuario.
  • Los datos se pueden cargar tanto a nivel de clase como a nivel de método utilizando la anotación @DataLoader.
  • Se pueden utilizar múltiples tipos (CSV, Excel, XML, formato a medida) en los ficheros usados para cargar los datos en una misma clase de prueba.
  • El usuario puede inyectar beans de prueba en las clase de test utilizando la anotación @Provided.
  • El usuario puede interceptar las llamadas que se realizan a la clase que se está probando y hacer cosas como por ejemplo monitorizar el rendimiento de los métodos de la clase.
  • El IDE utilizado se encarga de enviar información sobre qué método se ha ejecutado bajo que parámetros de entrada y sus valores. De esta manera, se puede identificar fácilmente el motivo de fallo de un test.
  • EasyTest soporta el framework Spring Test, así, es posible ejecutar los test utilizando el SpringTestRunner de EasyTest.
  • Los ficheros con los datos de prueba se pueden proporcionar como un recurso del classpath (classpath: prefijo), como un recurso del sistema de ficheros o como un recurso Url.

Sin más preámbulos vamos a mostrar una pequeña descripción con ejemplos de uso de esta intuitiva librería.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15’ (2 GHz Intel Core i7, 8 GB 1333 MHz DDR3)
  • Sistema Operativo: Mac OS X Yosemite 10.10.4
  • Entorno de desarrollo: Eclipse Java EE IDE, Mars Release (4.5.0)
  • EasyTest 1.3.2
  • Apache Maven 3.3.3

3. Ejemplo de uso

En primer lugar veremos un ejemplo muy sencillo en el que probamos una clase calculadora que contiene un método encargado de sumar dos enteros.

Una vez creado el proyecto Maven, añadimos la dependencia de EasyTest en nuestro pom:

pom.xml
<dependency>
	<groupId>org.easetech</groupId>
	<artifactId>easytest-core</artifactId>
	<version>1.3.2</version>
</dependency>

La clase calculadora será algo tal que así:

Calculator.java
package com.autentia.tutorial.easytest;

public class Calculator {

    public int addTwoIntegers(int op1, int op2) {
        return op1 + op2;
    }

}
	

Como vemos se implementa un métoodo muy trivial que suma dos operandos pasados por parámetros.

Nuestra clase de test usando EasyTest será la siguiente:

CalculatorTest.java
package com.autentia.tutorial.easytest;

import org.easetech.easytest.annotation.DataLoader;
import org.easetech.easytest.annotation.Param;
import org.easetech.easytest.runner.DataDrivenTestRunner;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(DataDrivenTestRunner.class)
@DataLoader(filePaths = { "dataForCalculator.xls" })
public class CalculatorTest {

    private Calculator calculatorSUT;

    @Before
    public void setUp() {
        calculatorSUT = new Calculator();
    }

    @Test
    public void givenTwoNumbersShouldReturnTheSum(@Param(name = "op1") int op1, @Param(name = "op2") int op2,
            @Param(name = "result") int result) {

        int sum = calculatorSUT.addTwoIntegers(op1, op2);

        Assert.assertEquals(result, sum);
    }

}

Aquí si que podemos explicar algunas cosillas. En primer lugar, indicamos a JUnit mediante la anotación @RunWith que use el runner de EasyTest para test guiados por datos.

En segundo lugar, indicamos el fichero que contiene los casos de prueba, en este caso hemos usado un fichero excel, pero como se ha mencionado anteriormente, se puede hacer uso de otro tipo de ficheros con formato. El fichero, al que hemos llamado dataForCalculator.xls, se encuentra dentro de src/test/resources y su contenido es el siguiente:

dataForCalculator.xls
givenTwoNumbersShouldReturnTheSum	op1	op2	result
									  1	  2	     3
									  6	  8	    14
                                     10	 20	    30

En la primera fila, primera columna, se indica el nombre del método de test que usará estos datos. En las siguientes tres columnas, se indica el nombre que tendrán los parámetros de entrada del método de test, en este caso, op1, op2 y result. Como podemos ver en el código de nuestro método de test, haciendo uso de la anotación @Param con su atributo name, vemos que el valor de dicho atributo se corresponde con los nombres de las columnas en el excel. Finalmente, debajo de estas tres columnas, en las filas sucesivas, se indican los valores con los que será probado el método.

De esta forma, se realizarán tres pruebas del método addTowIntegers con los valores indicados en el excel. Siendo op1 y op2 los operandos y result el valor esperado.

Si ejecutamos el test, obtendremos una salida similar a la de cualquier método de test de JUnit, en el que si se produce algún fallo nos informará del motivo.

testResult

4. Otras características interesantes

El ejemplo anterior es simplemente una primera toma de contacto con EasyTest, pero existen una serie de detalles interesantes como por ejemplo, poder externalizar la lógica de la configuración inicial del test. Para ello se hace uso de las anotaciones @TestConfigProvider y @Inject. Lo veremos más claro aplicándolo en nuestro ejemplo:

CalculatorTest.java
package com.autentia.tutorial.easytest;

import javax.inject.Inject;

import org.easetech.easytest.annotation.DataLoader;
import org.easetech.easytest.annotation.Param;
import org.easetech.easytest.annotation.TestConfigProvider;
import org.easetech.easytest.runner.DataDrivenTestRunner;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(DataDrivenTestRunner.class)
@DataLoader(filePaths = { "dataForTest.xls" })
@TestConfigProvider({ TestCalculatorConfigProvider.class })
public class CalculatorTest {

    @Inject
    private Calculator calculatorSUT;

    @Test
    public void givenTwoNumbersShouldReturnTheSum(@Param(name = "op1") int op1, @Param(name = "op2") int op2,
            @Param(name = "result") int result) {

        int sum = calculatorSUT.addTwoIntegers(op1, op2);

        Assert.assertEquals(result, sum);
    }

}
	

Como vemos, omitimos el método before en el que inicializamos la clase y añadimos la anotación @Inject, de manera que nos inyecte directamente el objeto a probar que ha sido inicializado en la clase inidicada en la anotación @TestConfigProvider. Para nuestro ejemplo, la clase TestCalculatorConfigProvider simplemente nos devuelve una instancia de la clase Calculator:

TestCalculatorConfigProvider.java
package com.autentia.tutorial.easytest;

import org.easetech.easytest.annotation.TestBean;

public class TestCalculatorConfigProvider {

    @TestBean
    public Calculator calulator() {
        return new Calculator();
    }
}
	

En casos en los que la inicialización necesaria para realizar nuestros tests sea más compleja puede ser interesante utilizar esta estrategia ya que nos simplifica el código y una misma configuración puede ser utilizada para distintas clases de test

Otra anotación interesante es @Parallel(threads= número de threads) que nos permite ejecutar tests en paralelo, mejorando la eficiencia en la ejecución de las pruebas.

5. Conclusiones

El uso de EasyTest puede ser muy interesante ya que nos permite realizar múltiples pruebas con diferentes datos de entrada. Así podremos probar más exhaustivamente el comportamiento de los métodos de nuestras clases Java, sin necesidad de crear un método de test para cada conjunto de valores utilizado en las pruebas. Esto nos proporciona una mayor claridad y limpieza en nuestro código de test y además, gracias al uso de ficheros externos, podemos ampliar o modificar los valores que queremos probar sin necesidad de tocar nuestro código.

Finalmente, el uso de las diferentes anotaciones proporcionadas por este framework, nos permite ejecutar nuestros test con mejoras en el rendimiento. En el repositorio github de EasyMock podemos encontrar una amplia documentación, así como código de ejemplo en el que se utilizar diferentes tipos de fichero de entrada, que vale la pena mirar para decidir cuál es la mejor forma de probar nuestras clases utilizando las diferentes prestaciones que nos ofrece EasyMock.

6. Referencias

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad