2008-11-19 6 views
5

Me preguntaba si el objeto a probar debería ser un campo y configurarlo así durante un método SetUp (es decir, JUnit, nUnit, MS Test, ...).¿Inicializar objeto para probar en SetUp o durante el método de prueba?

Considere los siguientes ejemplos (esto es C♯ con MSTEST, pero la idea debe ser similar para cualquier otro idioma y el marco de pruebas):

public class SomeStuff 
{ 
    public string Value { get; private set; } 

    public SomeStuff(string value) 
    { 
     this.Value = value; 
    } 
} 


[TestClass] 
public class SomeStuffTestWithSetUp 
{ 
    private string value; 
    private SomeStuff someStuff; 

    [TestInitialize] 
    public void MyTestInitialize() 
    { 
     this.value = Guid.NewGuid().ToString(); 
     this.someStuff = new SomeStuff(this.value); 
    } 

    [TestCleanup] 
    public void MyTestCleanup() 
    { 
     this.someStuff = null; 
     this.value = string.Empty; 
    } 

    [TestMethod] 
    public void TestGetValue() 
    { 
     Assert.AreEqual(this.value, this.someStuff.Value); 
    } 
} 

[TestClass] 
public class SomeStuffTestWithoutSetup 
{ 
    [TestMethod] 
    public void TestGetValue() 
    { 
     string value = Guid.NewGuid().ToString(); 
     SomeStuff someStuff = new SomeStuff(value); 
     Assert.AreEqual(value, someStuff.Value); 
    } 
} 

Por supuesto, con sólo un método de ensayo, el primer ejemplo es demasiado largo, pero con más métodos de prueba, esto podría ser bastante seguro de algún código redundante.

¿Cuáles son los pros y los contras de cada enfoque? ¿Hay alguna "mejores prácticas"?

Respuesta

8

Es una pendiente resbaladiza una vez que comience la inicialización de los campos & general, la configuración del contexto de su prueba dentro el método de prueba en sí. Esto conduce a métodos de prueba grandes y accesorios realmente inmanejables que no se explican muy bien.

En su lugar, debe mirar la organización de prueba de nombre de estilo BDD &. Haga un accesorio por contexto, en lugar de un accesorio por sistema bajo prueba. Entonces su [configuración] realmente configura el contexto, y sus pruebas pueden ser simples afirmaciones de una sola línea.

Es mucho más fácil de leer cuando se ve una salida de prueba que hace esto:

OrderFulfillmentServiceTests.cs

  • with_an_order_from_a_new_customer

    • debe comprobar su crédito del servicio de crédito
    • debe dar ningún descuento
  • con verificación de crédito válida

    • debe disminuir el inventario
    • debe enviar las mercancías
  • con un cliente en Texas o California

    • debe añadir el impuesto sobre las ventas apropiada
  • con una orden de un cliente de oro

    • NO se debe comprobar el crédito
    • envío
    • se debe conseguir acelerada añadió gratis

Nuestras pruebas son ahora muy buena documentación para nuestro sistema. Cada "with_an ..." es un accesorio de prueba, y los elementos a continuación son pruebas. Dentro de eso, configura el contexto (el estado del mundo como lo describe el nombre de la clase) y luego la prueba hace la afirmación simple que verifica lo que dice el nombre del método.

+0

Sí, cambiar a ese estilo de prueba realmente ha ayudado con cómo van las cosas. Básicamente, las pruebas unitarias siguen la misma regla que el código: es decir, responsabilidad única. Una prueba para un escenerio. –

1

El segundo enfoque es mucho más legible y mucho más fácil de rastrear visualmente.

Sin embargo, el primer enfoque significa menos repetición.

Lo que he encontrado es que tiendo a usar el SetUp para crear objetos (especialmente para cosas con varias dependencias), y luego establezco los valores utilizados en la prueba en sí. Por experiencia, esto proporciona la cantidad correcta de reutilización de código frente a legibilidad/trazabilidad.

0

Personalmente, utilizo métodos de instalación y desmontaje por dos razones distintas, aunque supongo que otras tendrán diferentes motivos.

  1. Use los métodos de Configuración y Desmontaje cuando existe una lógica de iniciación común que todas las pruebas utilizan y una sola instancia de los objetos creados en la Configuración están diseñados para ser reutilizados.
  2. Use los métodos de Configuración y Desmontaje cuando el tiempo que lleva crear y destruir cualquier objeto creado toma tiempo suficiente para ralentizar el proceso de prueba de la unidad cuando se repite en cada Método de Prueba.

para darle una idea de con qué frecuencia me encuentro al otro lado de estos escenarios, en un proyecto que estoy trabajando ahora, sólo dos de mis clases de prueba (de un total de alrededor de ochenta) tengo una necesidad explícita de montaje y desmontaje métodos, las dos veces fue para satisfacer mi segunda razón debido al máximo de 10 segundos que he habilitado para cada ejecución de prueba.

También prefiero la legibilidad de tener el objeto (s) creado y destruido dentro del TestMethod, aunque no es un punto de ruptura o de venta para mí.

+0

Do not SetUp y TearDown se llaman antes de cada TestMethod de todos modos? –

+0

Mi mal. No sé dónde me desinformé en eso. ¡Gracias por la aclaración! –

1

Hablando con Kent Beck sobre el diseño de jUnit, sé que las Clases de prueba fueron una forma de compartir la configuración entre Pruebas, por lo que la intención fue la inicialización común. Sin embargo, junto con eso, eso significa dividir las pruebas que requieren una configuración diferente en clases de prueba separadas que tienen nombres reveladores.

0

El enfoque que tomo está en el medio - utilizo TearDown y SetUp para crear un directorio de prueba "sandbox" (y eliminarlo cuando termine), así como para inicializar algunas variables miembro de prueba con algunos valores predeterminados que ser utilizado para probar las clases. Luego configuré algunos "métodos auxiliares": uno se llama generalmente InstantiateClass(). Utilizo eso para llamar con los parámetros predeterminados (si hay alguno) que puedo anular según sea necesario en cada prueba explícita.

[Test] 
public void TestSomething() 
{ 
    _myVar = "value"; 
    InstantiateClass(); 
    RunTheClass(); 
    Assert.IsTrue(this, that); 
} 
0

En la práctica, encuentro establecieron métodos hacen que sea difícil de razonar acerca de una prueba que está fallando y que tenga que desplazarse a algún lugar cerca de la parte superior del archivo (que puede ser muy grande) para averiguar lo que el colaborador se ha roto (no es fácil con la burla) y no hay referencias clicables para navegar en su IDE. En resumen, pierdes localidad espacial.

Los métodos de ayuda estática revelan a los colaboradores de forma más explícita, y evita los campos que amplían innecesariamente el alcance de las variables.

Cuestiones relacionadas