Introducción a TestNG

1. Información general

En este artículo, presentaremos el marco de prueba TestNG.

Nos centraremos en: configuración del marco, redacción de casos y configuraciones de prueba simples, ejecución de pruebas, generación de informes de pruebas y ejecución de pruebas simultáneas.

2. Configuración

Comencemos agregando la dependencia de Maven en nuestro archivo pom.xml :

 org.testng testng 7.1.0 test 

La última versión se puede encontrar en el repositorio de Maven.

Al usar Eclipse, el complemento TestNG se puede descargar e instalar desde Eclipse Marketplace.

3. Escribir un caso de prueba

Para escribir una prueba usando TestNG, solo necesitamos anotar el método de prueba con org.testng.annotations. Anotación de prueba :

@Test public void givenNumber_whenEven_thenTrue() { assertTrue(number % 2 == 0); }

4. Probar configuraciones

Mientras escribimos casos de prueba, a menudo necesitamos ejecutar algunas instrucciones de configuración o inicialización antes de ejecutar las pruebas, y también una limpieza después de completar las pruebas. TestNG proporciona una serie de funciones de inicialización y limpieza a nivel de método, clase, grupo y suite:

@BeforeClass public void setup() { number = 12; } @AfterClass public void tearDown() { number = 0; }

El método setup () anotado con las anotaciones @BeforeClass será invocado antes de la ejecución de cualquier método de esa clase de prueba, y tearDown () después de ejecutar todos los métodos de la clase de prueba.

De manera similar, podemos usar las anotaciones @BeforeMethod, @AfterMethod, @ Before / AfterGroup, @ Before / AfterTest y @ Before / AfterSuite para cualquier configuración a nivel de método, grupo, prueba y suite.

5. Ejecución de la prueba

Podemos ejecutar los casos de prueba con el comando "test" de Maven, este ejecutará todos los casos de prueba anotados con @Test y los colocará en un conjunto de pruebas predeterminado. También podemos ejecutar casos de prueba desde los archivos XML de la suite de pruebas TestNG, utilizando el complemento maven-surefire-plugin:

 org.apache.maven.plugins maven-surefire-plugin 2.19.1    src\test\resources\test_suite.xml    

Tenga en cuenta que si tenemos varios archivos XML, que cubren todos los casos de prueba, podemos agregarlos todos en la etiqueta suiteXmlFiles :

  src/test/resources/parametrized_test.xml   src/test/resources/registration_test.xml  

Para ejecutar la prueba de forma independiente, necesitamos tener la biblioteca TestNG en la ruta de clase y la clase de prueba compilada junto con el archivo de configuración XML:

java org.testng.TestNG test_suite.xml

6. Pruebas de agrupación

Las pruebas se pueden ejecutar en grupos, por ejemplo, de 50 casos de prueba, 15 se pueden agrupar y ejecutar dejando otros como están.

En TestNG, las pruebas de agrupación en suites se realizan utilizando un archivo XML:

Tenga en cuenta que ambas clases de prueba, RegistrationTest, SignInTest ahora pertenecen a la misma suite y una vez que se ejecuta la suite, se ejecutarán los casos de prueba de esta clase.

Además de las suites de prueba, también podemos crear grupos de prueba en TestNG, donde en lugar de clases de prueba, los métodos se agrupan. Para hacer eso, agregue el parámetro de grupos en la anotación @Test :

@Test(groups = "regression") public void givenNegativeNumber_sumLessthanZero_thenCorrect() { int sum = numbers.stream().reduce(0, Integer::sum); assertTrue(sum < 0); }

Usemos un XML para ejecutar los grupos:

Esto ejecutará el método de prueba etiquetado con regresión de grupo , en la clase SummationServiceTest .

7. Pruebas parametrizadas

Las pruebas unitarias parametrizadas se utilizan para probar el mismo código en varias condiciones. Con la ayuda de pruebas unitarias parametrizadas, podemos configurar un método de prueba que obtenga datos de alguna fuente de datos. La idea principal es hacer que el método de prueba unitaria sea reutilizable y probar con un conjunto diferente de entradas.

En TestNG, podemos parametrizar las pruebas usando la anotación @ Parameter o @DataProvider . Mientras usa el archivo XML, anote el método de prueba con @ Parameter:

@Test @Parameters({"value", "isEven"}) public void givenNumberFromXML_ifEvenCheckOK_thenCorrect(int value, boolean isEven) { assertEquals(isEven, value % 2 == 0); }
Y proporcione los datos mediante un archivo XML:

El uso de datos de un archivo XML es útil, pero a menudo necesitamos datos más complejos. La anotación @DataProvider se usa para manejar estos escenarios, que se pueden usar para mapear tipos de parámetros complejos para métodos de prueba. @DataProvider para tipos de datos primitivos:

@DataProvider(name = "numbers") public static Object[][] evenNumbers() { return new Object[][]{{1, false}, {2, true}, {4, true}}; } @Test(dataProvider = "numbers") public void givenNumberFromDataProvider_ifEvenCheckOK_thenCorrect(Integer number, boolean expected) { assertEquals(expected, number % 2 == 0); }

@DataProvider para objetos:

@Test(dataProvider = "numbersObject") public void givenNumberObjectFromDataProvider_ifEvenCheckOK_thenCorrect(EvenNumber number) { assertEquals(number.isEven(), number.getValue() % 2 == 0); } @DataProvider(name = "numbersObject") public Object[][] parameterProvider() { return new Object[][]{{new EvenNumber(1, false)}, {new EvenNumber(2, true)}, {new EvenNumber(4, true)}}; }

Con esto, cualquier objeto que deba probarse puede crearse y usarse en la prueba. Esto es principalmente útil para casos de prueba de integración.

8. Ignorar casos de prueba

A veces queremos no ejecutar un caso de prueba determinado, temporalmente durante el proceso de desarrollo. Esto se puede hacer agregando enabled = false, en la anotación @ Test :

@Test(enabled=false) public void givenNumbers_sumEquals_thenCorrect() { int sum = numbers.stream.reduce(0, Integer::sum); assertEquals(6, sum); }

9. Pruebas dependientes

Consideremos un escenario, en el que si el caso de prueba inicial falla, todos los casos de prueba posteriores deben ejecutarse y, más bien, marcarse como omitidos. TestNG proporciona esta función con el parámetro dependOnMethods de la anotación @Test :

@Test public void givenEmail_ifValid_thenTrue() { boolean valid = email.contains("@"); assertEquals(valid, true); } @Test(dependsOnMethods = {"givenEmail_ifValid_thenTrue"}) public void givenValidEmail_whenLoggedIn_thenTrue() { LOGGER.info("Email {} valid >> logging in", email); }

Notice that, the login test case depends on the email validation test case. Thus, if email validation fails the login test will be skipped.

10. Concurrent Test Execution

TestNG allows tests to run in parallel or in multi-threaded mode, thus providing a way to test these multi-threaded pieces of code.

You can configure, for methods, classes, and suites to run in their own threads reducing the total execution time.

10.1. Classes and Methods in Parallel

To run test classes in parallel, mention the parallel attribute in the suite tag in XML configuration file, with value classes:

Note that, if we have multiple test tags in the XML file, these tests can also be run in parallel, by mentioning parallel =” tests”. Also to execute individual methods in parallel, mention parallel =” methods”.

10.2. Multi-Threaded Execution of Test Method

Let's say we need to test the behavior of a code when running in multiple threads. TestNG allows to run a test method in multiple threads:

public class MultiThreadedTests { @Test(threadPoolSize = 5, invocationCount = 10, timeOut = 1000) public void givenMethod_whenRunInThreads_thenCorrect() { int count = Thread.activeCount(); assertTrue(count > 1); } }

The threadPoolSize indicates that the method will run in n number of threads as mentioned. The invocationCount and timeOut indicate that the test will be executed multiple times and fail the test if it takes more time.

11. Functional Testing

TestNG viene con características que también pueden usarse para pruebas funcionales. Junto con Selenium, se puede utilizar para probar las funcionalidades de una aplicación web o para probar servicios web con HttpClient.

Más detalles sobre las pruebas funcionales con Selenium y TestNG están disponibles aquí. También algunas cosas más sobre pruebas de integración en este artículo.

12. Conclusión

En este artículo, echamos un vistazo rápido a cómo configurar TestNG y ejecutar un caso de prueba simple, generar informes, ejecución concurrente de casos de prueba y también un poco sobre programación funcional. Para más funciones como pruebas dependientes, ignorando casos de prueba, grupos de prueba y suites, puede consultar nuestro artículo JUnit vs TestNG aquí.

La implementación de todos los fragmentos de código se puede encontrar en Github.