Por favor vea el código a continuación; prueba para ver si una persona con Sexo de mujer es elegible para la oferta1:
[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
var personId = Guid.NewGuid();
var gender = "F";
var person = new Person(personId, gender);
var id = Guid.NewGuid();
var offer1 = new Offer1(id,"Offer1");
Assert.False(offer1.IsEligible(person));
}
Esta prueba unitaria tiene éxito. Sin embargo, fallará si se ofrece 'Offer1' a las mujeres en el futuro.
¿Es aceptable decir que si la lógica empresarial que rodea la oferta 1 cambia, entonces la prueba unitaria debe cambiar? Tenga en cuenta que en algunos casos (para algunas ofertas) la lógica de negocios se cambia en la base de datos de esta manera:
update Offers set Gender='M' where offer=1;
y en algunos casos en el modelo de dominio como este:
if (Gender=Gender.Male)
{
//do something
}
Tenga en cuenta también que, en algunos casos, la lógica de dominio detrás ofrece cambios regularmente y en otros casos no.
c#
unit-testing
domain-driven-design
xunit
w0051977
fuente
fuente
Respuestas:
Esto no es frágil en el sentido habitual. Una prueba unitaria se considera quebradiza si se rompe debido a cambios en la implementación que no afectan el comportamiento bajo prueba. Pero si la lógica de negocios en sí misma cambia, se supone que se rompe una prueba de esta lógica .
Dicho esto, si la lógica comercial cambia con frecuencia, quizás no sea apropiado codificar las expectativas en las pruebas unitarias. En su lugar, podría probar si las configuraciones en la base de datos afectan las ofertas como se esperaba.
El nombre de la prueba
Returns False When Given A Person With A Gender Of Female
no describe una regla comercial. Una regla de negocios sería algo asíOffers Applicable to M should not be applied to persons of gender F
.Por lo tanto, podría escribir una prueba que confirme que si una oferta se define como solo aplicable a personas de tipo M, entonces una persona de tipo F no será indicada como elegible para ella. Esta prueba garantizará que la lógica funcione incluso si cambia la configuración de las ofertas específicas.
fuente
Cuando la propiedad se define en la base de datos de producción (o un clon para pruebas), esto no es una prueba unitaria . Una prueba unitaria verifica una unidad de trabajo y no requiere un estado externo particular para funcionar. Esto supone que
Offer1
se define en la base de datos como una oferta solo para hombres. Eso es un estado externo. Esto es más una prueba de integración , específicamente un sistema o una prueba de aceptación . Tenga en cuenta que las pruebas de aceptación a menudo no están programadas (no se ejecutan en un marco de prueba sino que se realizan manualmente por seres humanos).Cuando la propiedad se define en el modelo de dominio con una
if
declaración, la misma prueba es una prueba unitaria. Y puede ser frágil. Pero el verdadero problema es que el código es frágil. Como regla general, su código será más resistente si el comportamiento empresarial es configurable en lugar de codificado. Debido a que una implementación apresurada para corregir un pequeño error de codificación debería ser rara. Pero un requisito comercial que cambia sin previo aviso es solo un martes (algo que sucede semanalmente).Puede estar utilizando un marco de prueba de unidad para ejecutar la prueba. Pero los marcos de pruebas unitarias no se limitan a ejecutar pruebas unitarias. También pueden ejecutar pruebas de integración.
Si estuviera escribiendo una prueba unitaria, crearía ambas
person
yoffer1
desde cero sin depender del estado de la base de datos. Algo comoTenga en cuenta que esto no cambia en función de la lógica empresarial. No es afirmativo lo que
offer1
rechaza a las mujeres. Está haciendooffer1
el tipo de oferta que rechaza a las mujeres.Puede crear y configurar la base de datos como parte de la prueba. En C #, usando NUnit, o en JUnit de Java, configuraría la base de datos en un
Setup
método. Presumiblemente su marco de prueba tiene una noción similar. En ese método, puede insertar registros en la base de datos con SQL.Si le resulta difícil escribir código que sustituya una base de datos de prueba por la base de datos de producción, eso suena como una debilidad de prueba en su aplicación. Para las pruebas, sería mejor usar algo como inyección de dependencia que permita la sustitución. Luego, podría escribir pruebas que sean independientes de las reglas comerciales actuales.
Un beneficio adicional de esto es que a menudo es más fácil para el dueño del negocio (no necesariamente el dueño corporativo, más como la persona responsable de este producto en la jerarquía corporativa) configurar las reglas comerciales directamente. Porque si tiene este tipo de marco técnico, es fácil permitir que el propietario de la empresa use una interfaz de usuario (UI) para configurar la oferta. El propietario de la empresa seleccionaría la limitación en la interfaz de usuario y emitiría la
markLimitedToGender("M")
llamada. Luego, cuando la oferta persiste en la base de datos, la almacena. Pero no necesitaría almacenar la oferta para usarla. Por lo tanto, sus pruebas podrían crear y configurar una oferta que no existe en la base de datos.En su sistema como se describe, el dueño del negocio tendría que presentar una solicitud al grupo técnico, que emitiría el SQL apropiado y actualizaría las pruebas. O el grupo técnico tiene que editar su código y pruebas (o pruebas y luego código). Ese parece un enfoque bastante pesado. Puedes hacerlo. Pero su software (no solo sus pruebas) sería menos frágil si no tuviera que hacerlo.
TL; DR : puede escribir pruebas como esta, pero es mejor que escriba su software para no tener que hacerlo.
fuente