Por favor veja o código abaixo; testa para ver se uma pessoa com Sexo feminino é elegível para a 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));
}
Este teste de unidade foi bem-sucedido. No entanto, falhará se a 'Oferta1' for oferecida às fêmeas no futuro.
É aceitável dizer - se a lógica de negócios em torno da oferta 1 for alterada, o teste de unidade deverá ser alterado. Observe que em alguns casos (para algumas ofertas) a lógica de negócios é alterada no banco de dados da seguinte maneira:
update Offers set Gender='M' where offer=1;
e, em alguns casos, no modelo de domínio como este:
if (Gender=Gender.Male)
{
//do something
}
Observe também que, em alguns casos, a lógica do domínio por trás oferece alterações regularmente e, em alguns casos, não.
c#
unit-testing
domain-driven-design
xunit
w0051977
fonte
fonte
Respostas:
Isso não é frágil no sentido usual. Um teste de unidade é considerado frágil se quebrar devido a alterações na implementação que não afetam o comportamento em teste. Mas se a própria lógica de negócios mudar, um teste dessa lógica deve ser interrompido.
Dito isto, se a lógica de negócios realmente muda com frequência, talvez não seja apropriado codificar as expectativas nos testes de unidade. Em vez disso, você pode testar se as configurações no banco de dados afetam as ofertas conforme o esperado.
O nome do teste
Returns False When Given A Person With A Gender Of Female
não descreve uma regra de negócios. Uma regra de negócios seria algo parecidoOffers Applicable to M should not be applied to persons of gender F
.Portanto, você pode escrever um teste que confirme que, se uma oferta for definida como aplicável apenas a pessoas do tipo M, uma pessoa do tipo F não será indicada como elegível para ela. Este teste garantirá que a lógica funcione mesmo que a configuração das ofertas específicas seja alterada.
fonte
Quando a propriedade é definida no banco de dados de produção (ou em um clone para teste), este não é um teste de unidade . Um teste de unidade verifica uma unidade de trabalho e não requer um estado externo específico para funcionar. Isso pressupõe que
Offer1
está definido no banco de dados como uma oferta apenas para homens. Esse é o estado externo. Portanto, este é mais um teste de integração , especificamente um sistema ou teste de aceitação . Observe que os testes de aceitação geralmente não são com script (não são executados em uma estrutura de teste, mas são executados manualmente por seres humanos).Quando a propriedade é definida no modelo de domínio com uma
if
instrução, o mesmo teste é um teste de unidade. E pode ser quebradiço. Mas o verdadeiro problema é que o código é quebradiço. Como regra geral, seu código será mais resiliente se o comportamento dos negócios for configurável em vez de codificado. Porque uma implantação rápida para corrigir um pequeno erro de codificação deve ser rara. Mas um requisito comercial que muda sem aviso prévio é apenas uma terça-feira (algo que acontece semanalmente).Você pode estar usando uma estrutura de teste de unidade para executar o teste. Mas as estruturas de teste de unidade não se limitam à execução de testes de unidade. Eles também podem executar testes de integração.
Se você estivesse escrevendo um teste de unidade, criaria ambos
person
eoffer1
desde o início, sem depender do estado do banco de dados. Algo comoObserve que isso não muda com base na lógica de negócios. Não é afirmar que
offer1
rejeita mulheres. Está fazendooffer1
o tipo de oferta que rejeita mulheres.Você pode criar e configurar o banco de dados como parte do teste. No C #, usando NUnit, ou no JUnit de Java, você configuraria o banco de dados em um
Setup
método. Presumivelmente, sua estrutura de teste tem uma noção semelhante. Nesse método, você pode inserir registros no banco de dados com SQL.Se for difícil escrever código que substitua um banco de dados de teste pelo banco de dados de produção, isso soa como uma fraqueza de teste no seu aplicativo. Para o teste, seria melhor usar algo como injeção de dependência que permita a substituição. Em seguida, você pode escrever testes independentes das regras de negócios atuais.
Um benefício colateral disso é que muitas vezes é mais fácil para o proprietário da empresa (não necessariamente o proprietário da empresa, mais parecido com a pessoa responsável por este produto na hierarquia corporativa) configurar as regras de negócios diretamente. Como se você possui esse tipo de estrutura técnica, é fácil permitir que o proprietário da empresa use uma interface de usuário (UI) para configurar a oferta. O proprietário da empresa selecionaria a limitação na interface do usuário e emitia a
markLimitedToGender("M")
chamada. Então, quando a oferta persistir no banco de dados, ela será armazenada. Mas você não precisaria armazenar a oferta para usá-la. Portanto, seus testes podem criar e configurar uma oferta que não existe no banco de dados.No sistema, conforme descrito, o proprietário da empresa precisaria fazer uma solicitação ao grupo técnico, que emitisse o SQL apropriado e atualizaria os testes. Ou o grupo técnico precisa editar seu código e testes (ou testes e depois código). Essa parece uma abordagem bastante pesada. Você consegue. Mas o seu software (não apenas o seu teste) seria menos quebradiço se você não precisasse fazer isso.
TL; DR : você pode escrever testes como este, mas é melhor escrever seu software para não precisar fazer isso.
fonte