2010-01-14 11 views
10

¿Cuál cree que es la forma más limpia de hacer varias afirmaciones sobre un resultado? En el pasado les puse todas la misma prueba, pero esto está empezando a sentirse un poco sucio, solo he estado jugando con otra idea usando setup.Mejores prácticas para múltiples afirmaciones sobre el mismo resultado en C#

[TestFixture] 
public class GridControllerTests 
{ 
    protected readonly string RequestedViewId = "A1"; 

    protected GridViewModel Result { get; set;} 

    [TestFixtureSetUp] 
    public void Get_UsingStaticSettings_Assign() 
    { 
     var dataRepository = new XmlRepository("test.xml"); 

     var settingsRepository = new StaticViewSettingsRepository(); 

     var controller = new GridController(dataRepository, settingsRepository); 

     this.Result = controller.Get(RequestedViewId); 

    } 

    [Test] 
    public void Get_UsingStaticSettings_NotNull() 
    { 
     Assert.That(this.Result,Is.Not.Null); 
    } 

    [Test] 
    public void Get_UsingStaticSettings_HasData() 
    { 
     Assert.That(this.Result.Data,Is.Not.Null); 
     Assert.That(this.Result.Data.Count,Is.GreaterThan(0)); 
    } 

    [Test] 
    public void Get_UsingStaticSettings_IdMatches() 
    { 
     Assert.That(this.Result.State.ViewId,Is.EqualTo(RequestedViewId)); 
    } 

    [Test] 
    public void Get_UsingStaticSettings_FirstTimePageIsOne() 
    { 
     Assert.That(this.Result.State.CurrentPage, Is.EqualTo(1)); 
    } 
} 

Respuesta

3

Lo que se necesita para mantener a es el patrón de Arrange, Act, Assert (y luego finalizar la prueba). En su caso, todos los arreglos están en el TestFixtureSetUp, al igual que la acción que se está probando. Me gustaría volver a organizar esto un poco, puede ser difícil de manejar cuando tienes más pruebas. Como señala Dockers, las configuraciones pesadas de prueba deben evitarse, pueden convertirse en problemas, son "de una sola medida" en todas las pruebas de la clase y, por lo tanto, pueden llegar a ser más pesadas de lo que la mayoría de las pruebas necesitan.

Si tiene la tentación de continuar con otra acción de seguimiento y luego afirma más, haga esto en una prueba por separado.

No tengo ningún problema para poner varios asertos en la misma prueba, siempre que contribuyan a probar lo mismo (es decir, que formen parte de la misma "aserción lógica"). En este caso, cualquier número de afirmaciones sobre el contenido de este.Result.Data estaría bien para mí, todos inspeccionarían el mismo valor de resultado. Su Get_UsingStaticSettings_HasData hace esto muy claramente. Lo mejor es usar un mensaje de falla único en cada afirmación para que sea más fácil saber qué afirmación falló.

De forma alternativa, podría resumir las afirmaciones relacionadas en un único método. esto es útil por las razones DRY habituales si lo usa más de una vez, pero de lo contrario no veo que sea una gran diferencia.

En resumen
* Realice una acción por prueba
* Después de la acción, ya que muchos afirman utilizar relacionada como sea necesario para poner a prueba una cosa
* Terminar la prueba allí.

15

Tener múltiples aserciones en la misma prueba puede llevar a Assertion Roulette, por lo que esto es algo de lo que siempre debe tener cuidado.

Sin embargo, Assertion Roulette es principalmente un problema cuando las aserciones son no relacionadas. Si están conceptualmente estrechamente relacionados, muchas aserciones a menudo se pueden ver como Aserciones lógicas.

En muchos casos puede obtener lo mejor de ambos mundos al encapsular explícitamente tal Aserción lógica en un tipo o método personalizado.

+0

"Aserciones lógicas" es una buena palabra para ello. Es interesante que el ejemplo de Assertion Roulette es esencialmente un ejemplo de "cómo equivocarse al no hacer Arrange-Act-Assert". ¿Los conceptos son diferentes? – Anthony

+0

@Anthony: los conceptos difieren, aunque están estrechamente relacionados. Es mucho menos probable que sienta el dolor de Assertion Roulette si sigue AAA (o Four Phase Test como lo llama xUnit Test Patterns), pero aún sería diferente si tuviera Assertions completamente sin relación en el mismo bloque de Assertion. –

+3

La idea de Assertion Roulette se puede minimizar en NUnit especificando un comentario en la declaración de Assertion. En lugar de hacer "Assert.That (condition)" use "Assert.That (condition, failureMessage)" donde "failureMessage" es información sobre lo que el Assert estaba verificando. Esto le permitirá saber exactamente qué Assert en una prueba de unidad falló. – Pedro

2

Puede utilizar Oapt - Un complemento NUnit para ejecutar un afirman por prueba:

[TestFixture] 
public class GridControllerTests 
{ 
    [TestCase, ForEachAssert] 
    public void Get_UsingStaticSettings_Assign() 
    { 
     var dataRepository = new XmlRepository("test.xml"); 
     var settingsRepository = new StaticViewSettingsRepository(); 
     var controller = new GridController(dataRepository, settingsRepository); 

     var result = controller.Get("A1"); 

     AssertOne.From(
     () => Assert.That(this.Result,Is.Not.Null), 
     () => Assert.That(this.Result.Data,Is.Not.Null), 
     () => Assert.That(this.Result.Data.Count,Is.GreaterThan(0)), 
     () => Assert.That(this.Result.State.ViewId,Is.EqualTo(RequestedViewId)), 
     () => Assert.That(this.Result.State.CurrentPage, Is.EqualTo(1))); 
    } 
} 

Esto creará 5 casos de prueba diferentes, uno para cada aserción.

0

Tiendo a poner las aserciones solo si son valiosas por sí mismas. Si quiero una afirmación por sí solo, hago una afirmación de encargo:

AssertThatMyObjectMatches(field1, field2, field3, field4, myObject); 

A veces, sin embargo, me gustaría tener más de un ejemplo de una prueba. Hago esto cuando la mitad del comportamiento no tiene valor sin la otra mitad.

Assert.True(list.IsEmpty()); 

list.Add(new Thing()); 
Assert.False(list.IsEmpty()); 

Otros, incluida la comunidad de Ruby, tienen una opinión diferente al respecto.Ha impulsado principalmente por el blog de Dave Astels', aquí:

http://www.artima.com/weblogs/viewpost.jsp?thread=35578

encuentro el método de 'Una afirmación por prueba' muy útil para cosas como la validación, donde cada pequeño aspecto es valioso. De lo contrario, no me preocupo tanto por eso.

Lo que sea que funcione para usted y su equipo es probablemente la manera correcta. Tiendo a hacer lo que parezca simple y fácil de cambiar es lo correcto más adelante, cuando tengo una mejor idea de lo que es correcto. También puse muchos comentarios a nivel de unidad Given/When/Then en ejemplos más complejos, y dividí la clase si se vuelve demasiado compleja de entender.

La razón por la que escribimos pruebas de esta manera no es para poder ver las cosas que se rompen. Es para ayudar a las personas a entender el código y cambiarlo sin romper las cosas en primer lugar.

Cuestiones relacionadas