Prueba JUnit con número dynamic de pruebas

En nuestro proyecto tengo varias pruebas JUnit que, por ejemplo, toman cada archivo de un directorio y ejecutan una prueba en él. Si implemento un método testEveryFileInDirectory en TestCase esto se muestra como una sola prueba que puede fallar o tener éxito. Pero estoy interesado en los resultados en cada archivo individual. ¿Cómo puedo escribir un TestCase / TestSuite para que cada archivo aparezca como una prueba separada, por ejemplo, en el TestRunner gráfico de Eclipse? (Codificar un método de prueba explícito para cada archivo no es una opción).

Compare también la pregunta Prueba parametrizada con un nombre en Eclipse Testrunner .

Eche un vistazo a las Pruebas Paramétricas en JUnit 4.

En realidad, hice esto hace unos días. Trataré de explicar …

Primero construya su clase de prueba normalmente, ya que solo está probando con un archivo de entrada. Decora tu clase con:

 @RunWith(Parameterized.class) 

Cree un constructor que tome la entrada que cambiará en cada llamada de prueba (en este caso, puede ser el archivo)

Luego, crea un método estático que devuelva una Collection de matrices. Cada matriz de la colección contendrá los argumentos de entrada para el constructor de su clase, por ejemplo, el archivo. Decora este método con:

 @Parameters 

Aquí hay una clase de muestra.

 @RunWith(Parameterized.class) public class ParameterizedTest { private File file; public ParameterizedTest(File file) { this.file = file; } @Test public void test1() throws Exception { } @Test public void test2() throws Exception { } @Parameters public static Collection data() { // load the files as you want Object[] fileArg1 = new Object[] { new File("path1") }; Object[] fileArg2 = new Object[] { new File("path2") }; Collection data = new ArrayList(); data.add(fileArg1); data.add(fileArg2); return data; } } 

También mira este ejemplo

JUnit 3

 public class XTest extends TestCase { public File file; public XTest(File file) { super(file.toString()); this.file = file; } public void testX() { fail("Failed: " + file); } } public class XTestSuite extends TestSuite { public static Test suite() { TestSuite suite = new TestSuite("XTestSuite"); File[] files = new File(".").listFiles(); for (File file : files) { suite.addTest(new XTest(file)); } return suite; } } 

JUnit 4

 import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class TestY { @Parameters public static Collection getFiles() { Collection params = new ArrayList(); for (File f : new File(".").listFiles()) { Object[] arr = new Object[] { f }; params.add(arr); } return params; } private File file; public TestY(File file) { this.file = file; } @Test public void testY() { fail(file.toString()); } } 

JUnit 5

JUnit 5 lo admite a través de la noción de un DynamicTest , que se generará en @TestFactory , mediante el método estático dynamicTest .

 import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.stream.Stream; @TestFactory public Stream testFiles() { return Arrays.asList(new File(".").list()) .stream() .map((file) -> dynamicTest( "Test for file: " + file, () -> { /* Your test comes here */ })); } 

Las pruebas que se ejecutan en su IDE (IntelliJ aquí) se mostrarán así:

Salida en IntelliJ

Debería ser posible en JUnit 3 heredando TestSuite y anulando el método tests() para listar los archivos y para cada retorno una instancia de una subclase de TestCase que toma el nombre de archivo como parámetro de constructor y tiene un método de prueba que prueba el archivo proporcionado en el constructor

En JUnit 4 podría ser incluso más fácil.

Podría considerar usar la biblioteca JUnitParams , por lo que tendría algunas opciones más (más limpias):

 @org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class) public class ParameterizedTest { @org.junit.Test @junitparams.Parameters(method = "data") public void test1(File file) throws Exception { } @org.junit.Test @junitparams.Parameters(method = "data") public void test2(File file) throws Exception { } public static File[] data() { return new File[] { new File("path1"), new File("path2") }; } } 

 @org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class) public class ParameterizedTest { @org.junit.Test @junitparams.Parameters(value = { "path1", "path2" }) public void test1(String path) throws Exception { File file = new File(path); } @org.junit.Test @junitparams.Parameters(value = { "path1", "path2" }) public void test2(String path) throws Exception { File file = new File(path); } } 

Puedes ver más ejemplos de uso aquí .

Además de JUnitParams, ¿por qué escribir pruebas parametrizadas con él es más fácil y más legible ?

El proyecto JUnitParams agrega un nuevo corredor a JUnit y proporciona pruebas parametrizadas mucho más fáciles y legibles para JUnit> = 4.6.

Principales diferencias con el corredor estándar JUnit Parametrised:

  • más explícito: los parámetros están en los parámetros del método de prueba, no en los campos de clase
  • menos código: no necesita un constructor para configurar los parámetros
  • puede mezclar parametrizado con métodos no parametrizados en una clase
  • los parámetros se pueden pasar como una cadena de CSV o desde una clase de proveedor de parámetros
  • la clase de proveedor de parámetros puede tener tantos parámetros que proporcionen métodos como desee, de modo que pueda agrupar los diferentes casos
  • puede tener un método de prueba que proporcione parámetros (ya no hay clases externas ni estáticas)
  • puede ver los valores reales de los parámetros en su IDE (en Parametrised de JUnit solo se trata de números consecutivos de parámetros)

Si TestNG es una opción, puede usar Parámetros con DataProviders .

La prueba de cada archivo individual tendrá su resultado en el informe basado en texto o en la interfaz de usuario del plugin TestNG de Eclipse. El número total de pruebas ejecutadas contará cada uno de sus archivos individualmente.

Este comportamiento difiere de las Teorías JUnit, en el que todos los resultados se agrupan en una entrada de “teoría” y solo cuentan como 1 prueba. Si desea informes de resultados por separado en JUnit, puede probar Pruebas parametrizadas .

Prueba e insumos

 public class FileTest { @DataProvider(name="files") public File[][] getFiles(){ return new File[][] { { new File("file1") }, { new File("file2") } }; // or scan a directory } @Test(dataProvider="files") public void testFile(File file){ //run tests on file } } 

Ejemplo de salida

 PASSED: testFile(file1) PASSED: testFile(file2) =============================================== Default test Tests run: 2, Failures: 0, Skips: 0 =============================================== 

Tuve un problema similar y terminé escribiendo un simple JUnit 4 runner que permite generar pruebas dinámicamente.

https://github.com/kimble/junit-test-factory