Primeiro, desculpas pelo título, não consegui pensar na maneira mais fácil de explicar!
Eu tenho um método para o qual quero escrever testes de unidade. Vou mantê-lo bastante genérico, pois não quero discutir a implementação do método, apenas o teste. O método é:
public void HandleItem(item a)
{
CreateNewItem();
UpdateStatusOnPreviousItem();
SetNextRunDate();
}
Portanto, essa classe possui um método público que chama alguns métodos privados para executar a lógica.
Então, ao escrever o teste de unidade, quero verificar se as três coisas foram feitas. Como todos são chamados na mesma execução, pensei que poderia fazê-lo como um teste:
public void GivenItem_WhenRun_Thenxxxxx
{
HandleItem(item);
// Assert item has been created
// Assert status has been set on the previous item
// Assert run date has been set
}
Mas achei que também poderia escrever como três testes separados:
public void GivenItem_WhenRun_ThenItemIsCreated()
{
HandleItem(item);
}
public void GivenItem_WhenRun_ThenStatusIsUpdatedOnPreviousItem()
{
HandleItem(item);
}
public void GivenItem_WhenRun_ThenRunDateIsSet()
{
HandleItem(item);
}
Então, para mim, isso parece mais agradável, pois essencialmente lista os requisitos, mas todos os três estão relacionados e exigem exatamente o mesmo trabalho realizado no método testado, por isso estou executando o mesmo código três vezes.
Existe uma abordagem recomendada para levar com isso?
obrigado
fonte
Resposta curta: é muito mais importante que seus testes abranjam todas as funcionalidades do que como eles fazem.
Resposta mais longa: se você ainda deseja escolher entre essas soluções amplamente equivalentes, pode usar critérios auxiliares para o que é melhor. Por exemplo,
fonte
Use uma chamada de método com várias afirmações. Aqui está o porquê:
Ao testar o HandleItem (a), você está testando se o método colocou o item no estado correto. Em vez de "uma afirmação por teste", pense em "um conceito lógico por teste".
Pergunta: Se um CreateNewItem falhar, mas os outros dois métodos forem bem-sucedidos, isso significa que o HandleItem foi concluído com êxito? Acho que não.
Com várias declarações (com mensagens apropriadas), você saberá exatamente o que falhou. Você normalmente testa um método várias vezes para várias entradas ou estados de entrada, para evitar várias afirmações.
Na IMO, essas perguntas geralmente são um sinal de outra coisa. É um sinal de que HandleItem não é realmente algo que você possa "testar a unidade", pois parece delegar apenas a outros métodos. Quando você está simplesmente validando que o HandleItem chama outros métodos corretamente, ele se torna mais um candidato a teste de integração (nesse caso, você ainda teria três declarações).
Você pode considerar tornar públicos os outros 3 métodos e testá-los independentemente. Ou até mesmo extraí-los para outra classe.
fonte
Use a segunda abordagem. Com sua primeira abordagem, se o teste falhar, você não saberá o porquê imediatamente, porque pode ser uma das três funções que falharam. Com a segunda abordagem, você saberá imediatamente onde o problema ocorreu. Você pode colocar código duplicado dentro da sua função de configuração de teste.
fonte
IMHO, você deve testar as três partes desse método separadamente, para saber mais especificamente onde as coisas estão dando errado quando elas acontecem, evitando passar duas vezes pela mesma parte do seu código.
fonte
Eu não acho que exista um argumento forte para escrever métodos de teste separados para o seu caso de uso. Se você deseja obter os resultados de todas as três condições variáveis, pode testar todas as três e imprimir suas falhas concatenando-as em
string
e afirmando se a sequência de caracteres ainda está vazia depois de concluir o teste. Mantendo todos no mesmo método, suas mensagens de condições e falhas documentam a pós-condição esperada do método em um único local, em vez de dividi-lo em três métodos que podem ser separados posteriormente.Isso significa que seu teste único terá mais código, mas se você tiver tantas pós-condições que são um problema, provavelmente desejará refatorar seus métodos de teste para testar métodos individuais de
HandleItem
qualquer maneira.fonte