unitarias unitaria tipos test software pruebas prueba framework ejemplo con java unit-testing junit junit4

unitaria - test en java



¿Cómo ejecutar métodos de prueba en orden específico en JUnit4? (16)

Creo que es una función bastante importante para JUnit, si el autor de JUnit no quiere la función de orden, ¿por qué?

No estoy seguro de que haya una forma limpia de hacer esto con JUnit, que yo sepa, JUnit asume que todas las pruebas se pueden realizar en un orden arbitrario. De las preguntas frecuentes:

¿Cómo uso un dispositivo de prueba?

(...) El orden de invocaciones del método de prueba no está garantizado , por lo que testOneItemCollection () puede ejecutarse antes de testEmptyCollection (). (...)

¿Por que es esto entonces? Bueno, creo que hacer que las pruebas dependan del orden es una práctica que los autores no quieren promover. Las pruebas deben ser independientes, no deben estar acopladas y violar esto hará que las cosas sean más difíciles de mantener, romperá la capacidad de ejecutar pruebas individualmente (obviamente), etc.

Dicho esto, si realmente desea ir en esta dirección, considere usar TestNG ya que admite métodos de prueba en cualquier orden arbitrario de forma nativa (y cosas como especificar que los métodos dependen de grupos de métodos). Cedric Beust explica cómo hacer esto en orden de ejecución de pruebas en pruebas .

Quiero ejecutar métodos de prueba que están anotados por @Test en un orden específico.

Por ejemplo:

public class MyTest { @Test public void test1(){} @Test public void test2(){} }

Quiero asegurarme de ejecutar test1() antes de test2() cada vez que ejecuto MyTest , pero no puedo encontrar una anotación como @Test(order=xx) .

Creo que es una función bastante importante para JUnit, si el autor de JUnit no quiere la función de orden , ¿por qué?


Actualmente, JUnit permite que los métodos de prueba ejecuten la ordenación usando anotaciones de clase:

@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.JVM) @FixMethodOrder(MethodSorters.DEFAULT)

Para establecer el orden de los métodos puedes nombrarlos como:

a_testWorkUnit_WithCertainState_ShouldDoAlgo b_testWorkUnit_WithCertainState_ShouldDoAlgo c_testWorkUnit_WithCertainState_ShouldDoAlgo

Puedes encontrar ejemplos aquí .


Aquí hay una extensión de JUnit que puede producir el comportamiento deseado: https://github.com/aafuks/aaf-junit

Sé que esto va en contra de los autores de la filosofía JUnit, pero cuando se usa JUnit en entornos que no son pruebas unitarias estrictas (como se practica en Java), esto puede ser muy útil.



Es uno de los principales problemas que enfrenté cuando trabajé en Junit y se me ocurrió una solución que funciona bien para mí:

import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; public class OrderedRunner extends BlockJUnit4ClassRunner { public OrderedRunner(Class<?> clazz) throws InitializationError { super(clazz); } @Override protected List<FrameworkMethod> computeTestMethods() { List<FrameworkMethod> list = super.computeTestMethods(); List<FrameworkMethod> copy = new ArrayList<FrameworkMethod>(list); Collections.sort(copy, new Comparator<FrameworkMethod>() { @Override public int compare(FrameworkMethod f1, FrameworkMethod f2) { Order o1 = f1.getAnnotation(Order.class); Order o2 = f2.getAnnotation(Order.class); if (o1 == null || o2 == null) { return -1; } return o1.order() - o2.order(); } }); return copy; } }

también crea una interfaz como la siguiente:

@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD}) public @interface Order { public int order(); }

Ahora suponga que tiene clase A donde ha escrito varios casos de prueba como los siguientes:

(@runWith=OrderRunner.class) Class A{ @Test @Order(order = 1) void method(){ //do something } }

Entonces la ejecución comenzará desde el método llamado "método ()". ¡Gracias!


He leído algunas respuestas y estoy de acuerdo en que no es la mejor práctica, pero la forma más sencilla de ordenar las pruebas, y la forma en que JUnit ejecuta las pruebas de forma predeterminada, es por nombre alfabético ascendente.

Así que simplemente nombre sus pruebas en el orden alfabético que desee. También tenga en cuenta que el nombre de la prueba debe comenzar con la palabra prueba. Solo ten cuidado con los números

test12 se ejecutará antes de test2

asi que:

testA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond


La migración a TestNG parece la mejor manera, pero no veo una solución clara para jUnit. Aquí está la solución / formato más legible que encontré para jUnit:

@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class SampleTest { @Test void stage1_prepareAndTest(){}; @Test void stage2_checkSomething(){}; @Test void stage2_checkSomethingElse(){}; @Test void stage3_thisDependsOnStage2(){}; @Test void callTimeDoesntMatter(){} }

Esto garantiza que los métodos de stage2 se llamen después de los de stage1 y antes de los de stage3.


Lo que desea es perfectamente razonable cuando los casos de prueba se ejecutan como una suite.

Lamentablemente no hay tiempo para dar una solución completa en este momento, pero eche un vistazo a la clase:

org.junit.runners.Suite

Lo que le permite llamar a los casos de prueba (de cualquier clase de prueba) en un orden específico.

Se pueden usar para crear pruebas funcionales, de integración o de sistema.

Esto deja sus pruebas de unidad tal como están sin un orden específico (como se recomienda), ya sea que las ejecute así o no, y luego reutilice las pruebas como parte de un panorama más amplio.

Reutilizamos / heredamos el mismo código para las pruebas de unidad, integración y sistema, a veces controladas por datos, a veces comprometidas y, a veces, ejecutadas como una suite.


Mira un informe JUnit. JUnit ya está organizado por paquete. Cada paquete tiene (o puede tener) clases de TestSuite, cada una de las cuales a su vez ejecuta múltiples TestCases. Cada TestCase puede tener múltiples métodos de prueba de la forma public void test*() , cada uno de los cuales se convertirá en una instancia de la clase TestCase a la que pertenecen. Cada método de prueba (instancia de TestCase) tiene un nombre y un criterio de aprobación / falla.

Lo que mi administración requiere es el concepto de elementos de TestStep individuales, cada uno de los cuales informa sus propios criterios de aprobación / falla. La falla de cualquier paso de prueba no debe impedir la ejecución de pasos de prueba posteriores.

En el pasado, los desarrolladores de pruebas en mi posición organizaron las clases de TestCase en paquetes que correspondían a las partes del producto bajo prueba, crearon una clase de TestCase para cada prueba e hicieron de cada método de prueba un "paso" separado en la prueba. Completa con sus propios criterios de aprobación / falla en la salida de JUnit. Cada TestCase es una "prueba" independiente, pero los métodos individuales, o los "pasos" de prueba dentro de TestCase, deben ocurrir en un orden específico.

Los métodos de TestCase fueron los pasos de TestCase, y los diseñadores de prueba obtuvieron un criterio de aprobación / falla por separado para cada paso de prueba. Ahora los pasos de la prueba se mezclan y las pruebas (por supuesto) fallan.

Por ejemplo:

Class testStateChanges extends TestCase public void testCreateObjectPlacesTheObjectInStateA() public void testTransitionToStateBAndValidateStateB() public void testTransitionToStateCAndValidateStateC() public void testTryToDeleteObjectinStateCAndValidateObjectStillExists() public void testTransitionToStateAAndValidateStateA() public void testDeleteObjectInStateAAndObjectDoesNotExist() public void cleanupIfAnythingWentWrong()

Cada método de prueba afirma e informa sus propios criterios de aprobación / falla por separado. Al colapsar esto en "un método de prueba grande" por el simple hecho de ordenar, se pierde la granularidad de los criterios de aprobación / falla de cada "paso" en el informe de resumen de JUnit. ... y eso molesta a mis managers. Actualmente están demandando otra alternativa.

¿Alguien puede explicar cómo un JUnit con un método de prueba aleatorizado podría soportar criterios separados de aprobación / falla de cada paso de prueba secuencial, como se ejemplificó anteriormente y es requerido por mi gerencia?

Independientemente de la documentación, veo esto como una regresión seria en el marco de JUnit que está haciendo la vida difícil para muchos desarrolladores de pruebas.


No estoy seguro de estar de acuerdo, si quiero probar ''Carga de archivos'' y luego probar ''Datos insertados por carga de archivos'', ¿por qué no querría que estos sean independientes unos de otros? Creo que es perfectamente razonable poder ejecutarlos por separado en lugar de tener ambos en un caso de prueba Goliath.


Por favor revise este: https://github.com/TransparentMarket/junit . Ejecuta la prueba en el orden en que están especificados (definidos dentro del archivo de clase compilado). También cuenta con una suite AllTests para ejecutar primero las pruebas definidas por el subpaquete. Al usar la implementación de AllTests, se puede extender la solución al filtrar también las propiedades (solíamos usar las anotaciones de @Fast pero aún no estaban publicadas).


Puedes usar uno de estos códigos:

@FixMethodOrder(MethodSorters.JVM)OR `@FixMethodOrder(MethodSorters.DEFAULT)` OR `@FixMethodOrder(MethodSorters.NAME_ASCENDING)` before your test class like this: @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class BookTest { ...}


Si el orden es importante, usted debe hacer el pedido usted mismo.

@Test public void test1() { ... } @Test public void test2() { test1(); ... }

En particular, debe enumerar algunas o todas las posibles permutaciones de orden para probar, si es necesario.

Por ejemplo,

void test1(); void test2(); void test3(); @Test public void testOrder1() { test1(); test3(); } @Test(expected = Exception.class) public void testOrder2() { test2(); test3(); test1(); } @Test(expected = NullPointerException.class) public void testOrder3() { test3(); test1(); test2(); }

O bien, una prueba completa de todas las permutaciones:

@Test public void testAllOrders() { for (Object[] sample: permute(1, 2, 3)) { for (Object index: sample) { switch (((Integer) index).intValue()) { case 1: test1(); break; case 2: test2(); break; case 3: test3(); break; } } } }

Aquí, permute() es una función simple que itera todas las permuaciones posibles en una colección de arreglos.


Si se deshace de su instancia existente de Junit y descarga JUnit 4.11 o superior en la ruta de compilación, el siguiente código ejecutará los métodos de prueba en el orden de sus nombres, ordenados en orden ascendente:

@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class SampleTest { @Test public void testAcreate() { System.out.println("first"); } @Test public void testBupdate() { System.out.println("second"); } @Test public void testCdelete() { System.out.println("third"); } }


Terminé aquí pensando que mis pruebas no se ejecutaron en orden, pero la verdad es que el desorden estaba en mis trabajos asíncronos. Cuando trabaje con concurrencia, también debe realizar verificaciones de concurrencia entre sus pruebas. En mi caso, los trabajos y las pruebas comparten un semáforo, por lo que las siguientes pruebas se cuelgan hasta que el trabajo en ejecución libera el bloqueo.

Sé que esto no está totalmente relacionado con esta pregunta, pero tal vez podría ayudar a identificar el problema correcto


Vea mi solución aquí: "Junit y Java 7".

En este artículo describo cómo ejecutar las pruebas junit en orden, "como en su código fuente". Las pruebas se ejecutarán en orden a medida que sus métodos de prueba aparezcan en el archivo de clase.

http://intellijava.blogspot.com/2012/05/junit-and-java-7.html

Pero como dijo Pascal Thivent, esta no es una buena práctica.