Tengo una clase que estoy probando. La clase tiene una función:apply(List<IRule> rules, List<ITarget> targets);
En una prueba, quiero asegurarme de que cada objetivo se haya pasado a una regla, a la:
rule1.AssertWasCalled(fnord => fnord.Test(target1));
rule1.AssertWasCalled(fnord => fnord.Test(target2));
rule1.AssertWasCalled(fnord => fnord.Test(target3));
Me parece que limitarme a una sola declaración de afirmación sería bastante difícil . ¿Estoy en lo cierto en esta suposición, o hay alguna otra forma en que pueda afirmar que cada objetivo, de hecho, ha sido probado?
unit-testing
code-quality
Wayne Werner
fuente
fuente
Respuestas:
Las tres afirmaciones son, en esencia, una prueba. Está probando el comportamiento de un método en una colección para asegurarse de que cada elemento haya sido un parámetro para una llamada específica (es decir, que cada elemento se haya procesado correctamente).
Configurar los datos tres veces y en tres métodos diferentes es un desperdicio y menos legible que la alternativa de tener varias afirmaciones.
La "regla" de afirmación única se trata más de hacer afirmaciones de diferentes tipos en los mismos métodos (esencialmente probar cosas diferentes), lo que realmente no se aplica en este caso, donde está probando un solo comportamiento.
fuente
Creo que esta afirmación por regla de prueba existe para mantener sus pruebas enfocadas en un tema. Si prueba 20 cosas en una prueba, es realmente difícil saber cuál es su cobertura. Sabes que está causando un problema cuando no puedes nombrar el método de prueba sin la palabra y en ella. Por ejemplo, si su método de prueba se denominaría con mayor precisión como
testFooIsTrueAndDbExistsAndBarIsNullAndAnExceptionDoesntOccur()
, probablemente esté probando demasiado en una prueba.En su caso, creo que probablemente esté bien afirmar tres veces. Si desea que su código sea más legible, puede extraer esas tres afirmaciones en un método llamado
assertWasCalledOnTargets(...)
.fuente
Para su ejemplo particular, puede salirse con la afirmación de "uno" si hace algo como:
Es lo que hago para evitar sentirme culpable por tener múltiples afirmaciones en una prueba.
fuente
He luchado con este también.
El purista (en mí) insiste en una afirmación por prueba, así sabré * exactamente * dónde explotaron las cosas.
Y luego me encuentro cortando / pegando mucho del mismo código de configuración de prueba redundante. Después de la tercera o cuarta capa de esto, comienzas a decir "¡Oy! ¡Suficiente!"
Mi compromiso ha sido encontrar los aspectos que "nunca" se rompen. Y pondré esas piezas juntas y luego agregaré un nuevo elemento que podría romperse. Para ser claros, superponer varias áreas volátiles en una prueba sería una violación de este compromiso.
fuente
Assume
. Acabo de enterarme de eso hoy.Si el código de configuración para
target1
es diferente del código de configuración paratarget2
, este tipo de corte de esquina tiende a conducir a un código de inicialización de prueba demasiado largo. Esto a su vez es un desastre o termina siendo refactorizado y reutilizado. Si sus pruebas son lo suficientemente complejas como para justificar su refactorización, su prueba probablemente esté probando más de una cosa.Si el código de configuración para cada objetivo es esencialmente el mismo, probablemente sea excesivo dividir su prueba en múltiples pruebas individuales.
Si
target1
ytarget2
son diferentes implementaciones de la misma interfaz, en su lugar debe ser la adición de una unidad de prueba a la interfaz (y permitiendo que su marco de pruebas para generar una prueba para cada aplicación de esa interfaz).fuente