2012-03-02 21 views
16

Tengo un caso de prueba donde agrego una entidad, la actualizo y elimino la misma. Por lo tanto, el orden de ejecución es importante aquí. Yo quiero que sea:Especificar el orden de ejecución en el caso de prueba JUnit

  1. Crear
  2. actualización
  3. Eliminar

Extrañamente, por sólo un caso de prueba (de 15), JUnit lo ejecuta en el siguiente orden:

  1. Eliminar
  2. actualización
  3. Crear.

¿Cómo le digo a JUnit que las ejecute en un orden específico? En otros casos, JUnit funciona totalmente bien (ejecutándose en serie). ¿Y por qué JUnit se comporta de forma extraña en este caso?

Relevante siguiente fragmento de código:

private static Date date; 
    private static int entity; 
    static Parking p; 
    public ParkingTests(String name) { 
     super(name); 
    } 
    public void testAdd() throws Exception { 
      //Add code here 
    } 
    public void testUpdate() throws Exception { 
      //update code here 
    } 
    public void testDelete() throws Exception { 
      //delete code here 
    } 
    } 

Se pone más raro. Ejecuto muchos casos de prueba como parte de un conjunto. Si solo ejecuto el caso de estacionamiento, la orden se mantiene. Si lo ejecuto junto con otros, a veces se mantiene, ¡a veces no!

+1

¿Puedes mostrar el código fuente de esta clase? –

+1

Un caso de prueba sería uno de los métodos en una clase de prueba. Hacer que sus pruebas dependan de un cierto orden de ejecución no es una buena práctica, como se detalla aquí: http://stackoverflow.com/q/3693626/422353 – madth3

+0

Sí, lo leí y me di cuenta de que las pruebas unitarias, en el mundo ideal, no debe ejecutarse en un orden específico. Lamentablemente, así es como funcionan las cosas aquí. Una cabina no se puede eliminar antes de crearse y penalizarse. Entonces el orden se vuelve importante. – crazyaboutliv

Respuesta

17

Su tipo de situación es incómoda, ya que se siente mal para mantener el trabajo duplicar el fin de aislar las pruebas (véase más abajo) - pero tenga en cuenta que la mayor parte de la duplicación se puede sacar en setUp y tearDown (@Before, @After), por lo que no necesita mucho código adicional. Siempre que las pruebas no se ejecuten tan lentamente que deje de ejecutarlas a menudo, es mejor perder un poco de CPU en nombre de las pruebas limpias.

public void testAdd() throws Exception { 
     // wipe database 
     // add something 
     // assert that it was added 
} 
public void testUpdate() throws Exception { 
     // wipe database 
     // add something 
     // update it 
     // assert that it was updated 
} 
public void testDelete() throws Exception { 
     // wipe database 
     // add something 
     // delete it 
     // assert that it was deleted 
} 

La alternativa es seguir todo en una sola prueba con múltiples afirma, pero esto es más difícil de entender y mantener, y da un poco menos información cuando una prueba falla:

public void testCRUD() throws Exception { 
     // wipe database 
     // add something 
     // assert that it was added 
     // update it 
     // assert that it was updated 
     // delete it 
     // assert that it was deleted 
} 

Prueba con bases de datos o colecciones o almacenamiento de cualquier tipo es complicado porque una prueba siempre puede afectar otras pruebas dejando basura en la base de datos/colección. Incluso si sus pruebas no dependen explícitamente entre sí, aún pueden interferir entre sí, especialmente si una de ellas falla.

Siempre que sea posible, use una instancia nueva para cada prueba, o limpie los datos, idealmente de la manera más sencilla posible, p. Ej. para una base de datos, borrar una tabla completa es más probable que tenga éxito que una eliminación muy específica que accidentalmente se puede equivocar.

Actualización: Por lo general, es mejor borrar los datos al comienzo de la prueba, por lo que una ejecución de prueba fallida no afecta la siguiente ejecución.

+0

Puedo utilizar su segunda sugerencia y escribirlos todos en una sola prueba, pero, como ha dicho, difícil de mantener. Además, la mayoría de mis pruebas están escritas de esta manera (1, 2 y 3) y solo esta está dando problemas. (Y sí, uso un DB limpio cada vez. No existe tal problema) – crazyaboutliv

+0

@crazyaboutliv: Diría que no confíe en que las pruebas se ejecuten de la manera en que lo está haciendo. Como dice el documento junit, el orden de ejecución del método de prueba no está garantizado. Además, he visto casos en que pasan pruebas junit cuando se ejecutan desde IDE pero fallan cuando se ejecutan como parte de la compilación. Y nadie querría entrar en situaciones como esta. –

+0

@DNA Su respuesta es buena para una sola tabla donde la inserción de valores antes de CRUD podría agregarse a setUp(), pero ¿qué ocurre si tengo más de 1 tabla para probar? No puedo tener tareas comunes para todas las tablas que podrían entrar en setUp() y tearDown(). – Prudhvi

19

Generalmente, las pruebas junit (métodos de prueba) no deben depender entre sí. siguiente es tomado de junit FAQ

Cada prueba se ejecuta en su propio accesorio de prueba para aislar las pruebas de los cambios realizados por otras pruebas. Es decir, las pruebas no comparten el estado de los objetos en el dispositivo de prueba. Debido a que las pruebas están aisladas, pueden ejecutarse en cualquier orden ... ... El pedido de invocaciones de métodos de prueba no está garantizado con .

Así que si quieres hacer algunas cosas de iniciación común entonces usted podría hacer que en el método anotado con @Before y la limpieza en el método anotado con @After. O bien, si esa inicialización no es necesaria para todos los métodos de prueba en su clase de prueba, entonces puede poner eso en métodos privados y llamarlos apropiadamente de sus pruebas.

En una nota lateral, si todavía desea hacer el pedido de pruebas, entonces puede echar un vistazo a TestNG.

0

Lo que puede hacer:

  • de limpieza de la base de datos antes de cada prueba
  • de inicio mediante pruebas de la primera operación lógica en primer lugar. Cuando tenga suficiente confianza, suponga que es correcta y pase a la siguiente, etc.
  • Primero escriba las pruebas de recuadro blanco, pero comience con las pruebas de recuadro negro. Por ejemplo, si tienes activadores o similares en tu base de datos, comienza con eso.
2

Si desea ejecutar las pruebas JUnit en orden "tal como se presentan en el código fuente", ver mi nota sobre esto aquí:

How to run junit tests in order as they present in your source code

Pero en realidad no es un buen idea, las pruebas deben ser independientes.

+0

O simplemente puede definir un Test Suite .. que es mucho más simple y fácil. –

+0

@ThomasW no es más fácil cuando ya tiene 5000+ pruebas ... – kornero

5

En general, JUnit no garantiza el pedido de casos de prueba. No se garantiza que sea alfabético ni el orden en el archivo. Si el orden de las pruebas fue importante, entonces uno depende de la salida del anterior. ¿Qué pasa si el primero falló? ¿Deberíamos incluso molestarnos con las pruebas posteriores (y dependientes)? Probablemente no.

Así que si tuviéramos esto:

@Test 
public void first(){...} 

@Test 
public void second() {...} 

@Test 
public void third() {...} 

No sabemos qué orden van a ejecutar en el Dado que esperamos que vayan en orden, y que probablemente no debería molestar a correr segunda o tercera si el archivo. una (s) anterior falló, podemos hacer esto en su lugar:

@Test 
public void firstThree(){ 
    first(); 
    second(); 
    third(); 
} 

public void first(){...} 
public void second() {...} 
public void third() {...} 

en cuenta que sólo tenemos una @test este tiempo, y garantiza el pedido.

11

Si está seguro de que desea tener un orden de ejecución para sus pruebas, JUnit 4.11 ahora lo admite mediante una anotación. Ver this thread para más discusión - básicamente, se usaría

@FixMethodOrder 

para garantizar cierto orden prueba de esa manera. Sin embargo, está desalentado.

6

Si está usando Java 7, entonces debe saber que Junit obtiene la lista de todas las pruebas utilizando "Método [] getDeclaredMethods()" de java.lang.Class. Puede leer del javadoc de este método o de junit docs que: "Los elementos en la matriz devuelta no están ordenados y no están en ningún orden particular.", pero en la lista anterior de métodos de implementación de jvm se ordenó tal como estaban en código fuente.

Esto fue tomado de este blog y proporciona un trabajo.

+0

Nota: el blog al que hace referencia fue escrito por alguien que [ya proporcionó una respuesta antes que usted] (http://stackoverflow.com/a/ 13265376/365237) – eis

+0

Así es, gracias por señalar eso. Si no recuerdo mal, ya leí el blog y lo resolví en algunas pruebas unitarias en las que estaba trabajando. Cuando vi esta pregunta, pensé que los demás también querrían saberlo. Creo que debería haber leído todas las respuestas con más cuidado. Quise decir sin ofender. Si @kornero quiere, eliminaré la publicación. –

Cuestiones relacionadas