2009-01-30 6 views
15

He estado creando pruebas de Unidad como locas y descubro que a menudo tengo que configurar algo en una prueba que acabo de destruir en una prueba anterior. ¿Es razonable alguna vez crear algo (por ejemplo, un registro de la base de datos) en una prueba (por ejemplo, una prueba de inserción) y luego usarlo para una prueba posterior (por ejemplo, una prueba de eliminación)? ¿O deberían todas y cada una de las pruebas mantenerse completamente por sí mismas?¿Es malo contar con el orden de las pruebas de su unidad NUnit?

¿Se puede determinar el orden de las pruebas en NUnit o siempre se hacen alfabéticamente?

Nota: Estoy preguntando específicamente sobre el orden de las pruebas dentro del archivo de prueba uno. No en archivos de prueba o de cualquier manera más global.

Actualización: Gracias a todos los que respondieron - había una gran cantidad de buenas respuestas y el sentido del grupo es bastante unánime. Elegí la respuesta de John Nolan ya que me brindó la explicación más completa y muchos enlaces. Como habrás adivinado, he tenido la tentación de romper esta regla a pesar de pensar que podría ser un poco "maloliente", como dijo John. Gracias también a Fortyrunner por agregar la etiqueta unit-testing.

+1

Buen trabajo al informar y explicar su pensamiento actualizado. Muy agradable. –

+0

Gracias, Jon. Me imagino que esta es una comunidad y las comunidades requieren un cierto grado de cuidado si van a crecer y florecer. –

Respuesta

10

Confiar en el orden de sus pruebas indica que está persistiendo el estado en todas las pruebas. Esto es smelly

Una manera más limpia de probar es donde usted solo depende de la funcionalidad única de la que desea verificar el comportamiento. Comúnmente usted mock los otros objetos que necesita para probar su método para funcionar.

Una buena manera de pensar acerca de las pruebas unitarias es el patrón Arrange, Act, Assert.

A continuación se muestra un fragmento de la excelente libre eBook de Karl Seguin. Anoté Arrange, Act y Assert.

[TestFixture] public class CarTest 
{ 
    [Test] public void SaveCarCallsUpdateWhenAlreadyExistingCar() 
    { 
     //Arrange 
     MockRepository mocks = new MockRepository(); 
     IDataAccess dataAccess = mocks.CreateMock<IDataAccess>(); 
     ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess); 
     //Act 
     Car car = new Car(); 
     Expect.Call(dataAccess.Save(car)).Return(389); 
     mocks.ReplayAll(); 
     car.Save(); 
     mocks.VerifyAll(); 
     // Assert 
     Assert.AreEqual(389, car.Id); 
     ObjectFactory.ResetDefaults(); 
    } 
} 
+0

¿La instrucción ObjectFactory.ResetDefaults() en realidad es parte de la 'Aserción'? He pensado un poco sobre esto, y creo que debería llamarse Organizar, Actuar, Afirmar, Limpiar o Organizar, Actuar, Afirmar, Restablecer? Algo de ese tipo, o tal vez: organizar, actuar, afirmar, desarticular? –

+0

Aunque casi siempre estoy de acuerdo con usted, hay casos en que una prueba simplemente debe depender de otra y/o el uso de objetos falsos puede frustrar el punto del proceso de prueba. Un ejemplo sería un equipo que requiere que las funciones se dividan en partes más discretas de lo razonable, o cuando se prueba entre versiones de bases de datos de bases de datos. En estos casos, me gusta utilizar variables estáticas que se pueden configurar inicialmente, luego están disponibles para todas las funciones posteriores. – Brain2000

+0

@ Brain2000 Sugeriría que estas no son pruebas de "unidad" en el sentido tradicional. No estoy muy seguro de lo que quiere decir con "funciones divididas en partes más discretas de lo que es razonable", pero en el último caso parece que está haciendo más acerca de las pruebas de interacción/integración. No hay nada de malo en esto, pero realizan diferentes trabajos. –

3

Realmente no confiaría en el pedido de pruebas. En lugar de eso, insertaba el código de configuración común en un método diferente y lo llamaba tanto de la prueba simple como de la más complicada. Alternativamente, simplemente llame a la prueba de inserción al inicio de la prueba de eliminación.

6

Vería cada prueba como completamente independiente de cualquier otra prueba. Incluso si pudiera ordenar el orden de las pruebas, sería una pesadilla de mantenimiento cuando las pruebas cambien.

11

Mire en test fixture setups que le permiten especificar funciones que se ejecutarán antes de cualquiera de las pruebas en el dispositivo. Esto le permite realizar una configuración común una vez y siempre se ejecutará, ya sea que ejecute una prueba o todas las pruebas en la suite.

2

Desafortunadamente, el orden de ejecución de la prueba unitaria no es predecible o al menos podría cambiarse en el futuro. P.ej. El marco de prueba de la unidad se modificará para que cada prueba se ejecute en una secuencia separada. Entonces, desde mi punto de vista, el uso de la orden de prueba no es razonable. Por otro lado, puede crear un conjunto de pequeñas pruebas independientes para probar partes pequeñas de su código y luego crear una o varias pruebas grandes que ejecutarán sus pequeñas pruebas en un orden específico.

8

Las pruebas unitarias están pensadas para ser independientes, no se deben ejecutar como un script secuencial. Si realmente los necesita se ejecutan secuencialmente, recójalos en una sola función de prueba.

Si las pruebas de su unidad sufren de expensive set-up, es posible que esté realizando pruebas de integración cuando crea que está realizando pruebas unitarias. Si está accediendo a una base de datos SQL dentro de la mayoría de las pruebas de su unidad, en realidad está realizando pruebas de integración con su capa de acceso a datos.

3

Recomiendo encarecidamente que todas las pruebas unitarias sean independientes.

Su lógica de negocio/estructura de base de datos, etc. puede cambiar con el tiempo, por lo que eventualmente tendrá que reemplazar o reescribir (o incluso descartar) las pruebas de unidades existentes, y si tiene varias otras pruebas dependiendo de la que Sustituir, esto podría causar problemas innecesarios porque también tendría que pasar por todas las otras pruebas y comprobar si siguen funcionando como se esperaba.

Además, una prueba de unidad defectuosa no debería poder arrastrar muchas otras (que podrían funcionar perfectamente por sí mismas) hacia abajo.

2

Si usted tiene pruebas de estado (un problema común con el trabajo de base de datos - que es lo que hago cuando no estoy en SO), entonces me parece que evitar la orden dentro de un archivo de prueba no es absolutamente necesario . Sin embargo, debe reconocer que si tiene 2 pruebas, con la prueba 2 dependiendo de la prueba 1 que pase, entonces obtendrá una falla doble "catastrófica" si la prueba 1 falla, porque la prueba 2 no tiene la configuración esperada (y, es más, desea preocuparse si la prueba 2 pasa después de que falló la prueba 1 si cree que la prueba 2 depende de la aprobación de la prueba 1).

Es por eso que desea que las pruebas sean independientes siempre que sea posible, tanto dentro del archivo como entre archivos.

Sería muy imprudente depender del orden entre (conjuntos de) pruebas en diferentes archivos.

Cuestiones relacionadas