Eu tenho uma classe que estou testando. A classe tem uma função:apply(List<IRule> rules, List<ITarget> targets);
Em um teste, quero garantir que cada destino tenha sido passado para uma regra, a la:
rule1.AssertWasCalled(fnord => fnord.Test(target1));
rule1.AssertWasCalled(fnord => fnord.Test(target2));
rule1.AssertWasCalled(fnord => fnord.Test(target3));
Parece-me que me limitar a uma única declaração de asserção seria bastante complicado . Estou correto nesta suposição, ou existe alguma outra maneira de afirmar que cada alvo foi, de fato, testado?
unit-testing
code-quality
Wayne Werner
fonte
fonte
Respostas:
As três afirmações são essencialmente um teste. Você está testando o comportamento de um método em uma coleção, para garantir que cada item tenha sido um parâmetro para uma chamada específica (ou seja, que cada item tenha sido processado corretamente).
Configurar os dados três vezes e em três métodos diferentes é um desperdício e menos legível do que a alternativa de ter várias afirmações.
A única regra de afirmação é mais sobre fazer afirmações de tipos diferentes nos mesmos métodos (essencialmente testando coisas diferentes), o que realmente não se aplica nesse caso, em que você está testando um único comportamento.
fonte
É minha convicção que esta regra de afirmativa por teste existe para manter seus testes focados em um problema. Se você testar 20 coisas em um teste, é realmente difícil dizer qual é a sua cobertura. Você sabe que está causando um problema quando não pode nomear o método de teste sem a palavra e nele. Por exemplo, se seu método de teste for nomeado com mais precisão como
testFooIsTrueAndDbExistsAndBarIsNullAndAnExceptionDoesntOccur()
, provavelmente você está testando demais em um teste.No seu caso, acho que não há problema em afirmar três vezes. Se você quiser fazer seu código mais legível, você pode extrair esses três afirma em um método chamado
assertWasCalledOnTargets(...)
.fonte
Para o seu exemplo em particular, você pode se safar da declaração de declaração "one" se fizer algo como:
É o que faço para evitar me sentir culpado por ter várias afirmações em um teste.
fonte
Também lutei com este.
O purista (em mim) insiste em uma afirmação por teste, para que eu saiba * exatamente * onde as coisas explodiram.
E então me encontro cortando / colando muito do mesmo código de configuração de teste redundante. Após a terceira ou quarta camada disso, você começa a dizer "Oi! Basta!"
Meu compromisso foi encontrar os aspectos que "nunca" quebram. E eu vou juntar essas peças e depois adicionar um novo elemento que pode quebrar. Só para esclarecer, colocar em camadas várias áreas voláteis em um teste seria uma violação desse compromisso.
fonte
Assume
. Acabei de aprender sobre isso hoje.Se o código de configuração
target1
for diferente do código de configuraçãotarget2
, esse tipo de corte de esquina tende a eventualmente levar a um código de inicialização de teste excessivamente longo. Por sua vez, isso é uma bagunça ou acaba sendo refatorado e reutilizado. Se seus testes forem complexos o suficiente para justificá-los, provavelmente você está testando mais de uma coisa.Se o código de configuração para cada destino for essencialmente o mesmo, dividir seu teste em vários testes individuais provavelmente será um exagero.
Se
target1
etarget2
são implementações diferentes da mesma interface, você deve adicionar um teste de unidade à interface (e permitir que sua estrutura de teste gere um teste para todas as implementações dessa interface).fonte