¿Debería poder ejecutarse cada prueba unitaria independientemente de otras pruebas?

24

Digamos que tiene pruebas para dos métodos de una clase. El primer método recopila datos de otro nivel y los coloca en algún tipo de almacenamiento independiente del tiempo de ejecución (como una tabla SQL), por lo que todos los datos manejados por esta prueba están codificados en la prueba. El segundo método es responsable de tomar datos de donde lo dejó el primer método y transformarlos de alguna manera (cálculo, mover ciertas partes a otro lugar, etc.).

Ahora, este segundo método podría tener entradas codificadas como la primera, o podría suponerse que las dos pruebas se ejecutarían secuencialmente y podrían retomar donde la primera prueba dejó, tomando los datos que realmente se almacenaron en la primera prueba.

Si optara por la segunda opción, realmente tendría una buena idea de que los dos métodos funcionan bien juntos, sin embargo, si la primera prueba falla, todas las pruebas posteriores fallan, eliminando el beneficio de la prueba de ayudar a aislar los errores más rápidamente.

Si optaras por la primera opción, cada método se aislaría y probaría de forma independiente, pero nunca sabrías realmente que realmente pueden funcionar juntos correctamente.

¿Cuál es la mejor opción aquí? ¿Existe algún tipo de alternativa como tener una sola prueba para cada método aislado con codificación rígida y luego pruebas más grandes que contengan ambos métodos en uno?

Morgan Herlocker
fuente
2
De hecho, desearía poder aleatorizar fácilmente el orden de las pruebas unitarias cada vez que se ejecutan. En este momento se ejecutan en un orden desconocido, aunque relativamente fijo.
Trabajo

Respuestas:

11

Si optaras por la primera opción, cada método se aislaría y probaría de forma independiente, pero nunca sabrías realmente que realmente pueden funcionar juntos correctamente.

Si sus métodos son verdaderamente independientes, esto no debería importar. Su segundo método debería:

a) Funciona correctamente cuando se le presentan datos válidos.

b) Fallar de manera sensata y consistente cuando se presentan datos no válidos.

Igualmente su primer método debería hacer lo mismo. Por lo tanto, siempre que maneje los casos de error, funcionarán juntos correctamente.

Si desea probar que los métodos funcionan correctamente juntos, entonces eso es prueba de integración, no prueba unitaria.

ChrisF
fuente
27

Si las pruebas no pueden ejecutarse independientemente, entonces no son pruebas unitarias.

Una prueba unitaria no debe depender de ningún estado externo, como el contenido de una tabla de base de datos. Debe probar únicamente una unidad de código de forma aislada.

Las pruebas que alteran o requieren un cierto estado son válidas, pueden formar parte de las pruebas de integración, por ejemplo, y en tales casos es importante asegurarse de que se realice la configuración adecuada, pero estas no serían pruebas unitarias. En este caso, todavía no recomendaría que una prueba requiera que se ejecute otra. Si se encuentra en este caso, probablemente debería factorizar el código que se requiere en un método de configuración separado. Es posible que tenga una prueba que simplemente llame al código de configuración y verifique que no se produzca una excepción, por ejemplo, y luego otra prueba que utilice activamente los datos configurados en el método de configuración.

Steve
fuente
@Steve, entonces, en este ejemplo, ¿diría: una prueba para el método 1, una prueba para el método 2 y una prueba que ejecuta 1 y 2 en la misma prueba?
Morgan Herlocker
2
Sí. las dos primeras serían pruebas unitarias, la tercera suena como una prueba de integración.
Steve
si tiene un módulo de cliente y un módulo de pedidos y un pedido no se pueden crear sin relación con el cliente. ¿Cómo lo probará independientemente del módulo del cliente? Cree un registro del cliente en la base de datos con sql (inserte en el cliente) o use Customer.createCustomer (). Y en mi humilde opinión, usar el segundo es mejor, ya que no es necesario implementar ninguna lógica en la prueba, pero solo funciona si su prueba para crear clientes pasa.
Dainius
@Dainius. En un escenario de prueba unitaria, normalmente usaría objetos simulados, por lo que pasaría un cliente simulado a su módulo de pedido. Tienes razón en que no querrás usar sql en este caso.
Steve
parece que en cualquier escenario donde el método B depende del método A, casi siempre habrá un método C que llama a A y luego llama a B. Dado que este es el caso, puede probar A, B y C de forma independiente.
Morgan Herlocker
9

Estoy seguro de que parece correcto ahora tener una prueba unitaria B que depende del estado que dejó la prueba unitaria B. Pero considere un año a partir de ahora cuando tenga mil pruebas unitarias. ¿Realmente desea esperar diez minutos para que se complete todo el conjunto de pruebas cada vez que necesite realizar un cambio?

Depende de su estilo de desarrollo, por supuesto, pero si desea tener alguna esperanza de un desarrollo decente basado en pruebas, en el que pueda ejecutar una prueba individual muchas veces cuando desarrolle una característica, le sugiero que brinde a cada prueba la capacidad de ser independiente.

Steve Rukuts
fuente
1
+1 Raskolnikov, no consideré el hecho de que esto sería un gran ahorro de tiempo más adelante cuando "haya realizado todas las pruebas" más adelante.
Morgan Herlocker
3

Parece que estás hablando de la configuración de prueba, que se puede realizar de varias maneras. Desea una copia limpia de los datos de la prueba (llamada accesorio) para cada prueba, por lo que cada uno de ellos no debe depender el uno del otro.

Existen varios marcos que permiten este tipo de pruebas, y herramientas como DBUnit que le permiten construir y destruir estructuras de datos rápidamente al inicio y al final de las pruebas y los conjuntos de pruebas.

TrueDub
fuente