Estoy tratando de realizar la configuración y el desmontaje para un conjunto de pruebas de integración, usando jUnit 4.4 para ejecutar las pruebas. El desmontaje debe ejecutarse de manera confiable. Tengo otros problemas con TestNG, por lo que estoy buscando volver a jUnit. ¿Qué ganchos están disponibles para su ejecución antes de que se ejecuten las pruebas y después de que se hayan completado todas las pruebas?
Nota: estamos usando maven 2 para nuestra compilación. Intenté usar las fases pre-
& de maven post-integration-test
, pero, si falla una prueba, maven se detiene y no se ejecuta post-integration-test
, lo cual no ayuda.
java
testing
junit
integration-testing
sblundy
fuente
fuente
post-integration-test
si falla una prueba. Consulte también esta página wiki .Respuestas:
Sí, es posible ejecutar de manera confiable métodos de instalación y desmontaje antes y después de cualquier prueba en un conjunto de pruebas. Déjame demostrar en código:
package com.test; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({Test1.class, Test2.class}) public class TestSuite { @BeforeClass public static void setUp() { System.out.println("setting up"); } @AfterClass public static void tearDown() { System.out.println("tearing down"); } }
Entonces tu
Test1
clase se vería así:package com.test; import org.junit.Test; public class Test1 { @Test public void test1() { System.out.println("test1"); } }
... y puedes imaginar que se
Test2
ve similar. Si corrieraTestSuite
, obtendría:Por lo tanto, puede ver que la configuración / desmontaje solo se ejecuta antes y después de todas las pruebas, respectivamente.
El truco: esto solo funciona si está ejecutando el conjunto de pruebas y no está ejecutando Test1 y Test2 como pruebas JUnit individuales. Mencionaste que estás usando maven, y al complemento seguro de maven le gusta ejecutar pruebas de forma individual y no como parte de una suite. En este caso, recomendaría crear una superclase que amplíe cada clase de prueba. La superclase contiene los métodos @BeforeClass y @AfterClass anotados. Aunque no es tan limpio como el método anterior, creo que funcionará para usted.
En cuanto al problema con las pruebas fallidas, puede configurar maven.test.error.ignore para que la compilación continúe en las pruebas fallidas. Esto no se recomienda como una práctica continua, pero debería ayudarlo a funcionar hasta que todas sus pruebas pasen. Para obtener más detalles, consulte la documentación segura de maven .
fuente
Un colega mío sugirió lo siguiente: puede usar un RunListener personalizado e implementar el método testRunFinished (): http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html#testRunFinished(org. junit.runner.Result)
Para registrar RunListener, simplemente configure el complemento surefire de la siguiente manera: http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html sección "Uso de oyentes y reporteros personalizados"
Esta configuración también debe ser elegida por el complemento a prueba de fallas. Esta solución es excelente porque no tiene que especificar Suites, clases de prueba de búsqueda o nada de esto; le permite a Maven hacer su magia, esperando que terminen todas las pruebas.
fuente
Puede usar la anotación @ClassRule en JUnit 4.9+ como describí en una respuesta a otra pregunta .
fuente
Usando anotaciones, puede hacer algo como esto:
import org.junit.*; import static org.junit.Assert.*; import java.util.*; class SomethingUnitTest { @BeforeClass public static void runBeforeClass() { } @AfterClass public static void runAfterClass() { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testSomethingOrOther() { } }
fuente
Aquí nosotros
fuente
En cuanto a "Nota: estamos usando maven 2 para nuestra compilación. Intenté usar las fases de prueba previa y posterior a la integración, pero, si una prueba falla, maven se detiene y no ejecuta la prueba posterior a la integración , lo cual no ayuda ".
en su lugar, puede probar el complemento a prueba de fallos, creo que tiene la capacidad de garantizar que se realice la limpieza independientemente de la configuración o el estado de la etapa intermedia
fuente
Siempre que todas sus pruebas puedan extender una clase "técnica" y estén en el mismo paquete, puede hacer un pequeño truco:
public class AbstractTest { private static int nbTests = listClassesIn(<package>).size(); private static int curTest = 0; @BeforeClass public static void incCurTest() { curTest++; } @AfterClass public static void closeTestSuite() { if (curTest == nbTests) { /*cleaning*/ } } } public class Test1 extends AbstractTest { @Test public void check() {} } public class Test2 extends AbstractTest { @Test public void check() {} }
Tenga en cuenta que esta solución tiene muchos inconvenientes:
Para obtener información: listClassesIn () => ¿Cómo se encuentran todas las subclases de una clase determinada en Java?
fuente
Hasta donde yo sé, no hay ningún mecanismo para hacer esto en JUnit, sin embargo, puede intentar subclasificar Suite y anular el método run () con una versión que proporcione ganchos.
fuente
Dado que maven-surefire-plugin no ejecuta la clase Suite primero, pero trata la suite y las clases de prueba de la misma manera, podemos configurar el complemento como se muestra a continuación para habilitar solo las clases de la suite y deshabilitar todas las pruebas. Suite ejecutará todas las pruebas.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <includes> <include>**/*Suite.java</include> </includes> <excludes> <exclude>**/*Test.java</exclude> <exclude>**/*Tests.java</exclude> </excludes> </configuration> </plugin>
fuente
La única forma en que creo que obtendría la funcionalidad que desea sería hacer algo como
import junit.framework.Test; import junit.framework.TestResult; import junit.framework.TestSuite; public class AllTests { public static Test suite() { TestSuite suite = new TestSuite("TestEverything"); //$JUnit-BEGIN$ suite.addTestSuite(TestOne.class); suite.addTestSuite(TestTwo.class); suite.addTestSuite(TestThree.class); //$JUnit-END$ } public static void main(String[] args) { AllTests test = new AllTests(); Test testCase = test.suite(); TestResult result = new TestResult(); setUp(); testCase.run(result); tearDown(); } public void setUp() {} public void tearDown() {} }
Utilizo algo como esto en eclipse, así que no estoy seguro de qué tan portátil es fuera de ese entorno
fuente
Si no desea crear una suite y tiene que enumerar todas sus clases de prueba, puede usar la reflexión para encontrar la cantidad de clases de prueba dinámicamente y hacer una cuenta regresiva en una clase base @AfterClass para hacer el tearDown solo una vez:
public class BaseTestClass { private static int testClassToRun = 0; // Counting the classes to run so that we can do the tear down only once static { try { Field field = ClassLoader.class.getDeclaredField("classes"); field.setAccessible(true); @SuppressWarnings({ "unchecked", "rawtypes" }) Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader()); for (Class<?> clazz : classes) { if (clazz.getName().endsWith("Test")) { testClassToRun++; } } } catch (Exception ignore) { } } // Setup that needs to be done only once static { // one time set up } @AfterClass public static void baseTearDown() throws Exception { if (--testClassToRun == 0) { // one time clean up } } }
Si prefiere usar @BeforeClass en lugar de los bloques estáticos, también puede usar una marca booleana para realizar el recuento de reflejos y la configuración de prueba solo una vez en la primera llamada. Espero que esto ayude a alguien, me tomó una tarde encontrar una manera mejor que enumerar todas las clases en una suite.
Ahora todo lo que necesita hacer es extender esta clase para todas sus clases de prueba. Ya teníamos una clase base para proporcionar algunas cosas comunes para todas nuestras pruebas, por lo que esta fue la mejor solución para nosotros.
La inspiración proviene de esta respuesta SO https://stackoverflow.com/a/37488620/5930242
Si no desea extender esta clase a todas partes, esta última respuesta SO podría hacer lo que desee.
fuente