Durante o treinamento de TDD baseado no caso do software médico, estamos implementando a seguinte história: "Quando o usuário pressiona o botão Salvar, o sistema deve adicionar um paciente, adicionar um dispositivo e adicionar registros de dados do dispositivo".
A implementação final será mais ou menos assim:
if (_importDialog.Show() == ImportDialogResult.SaveButtonIsPressed)
{
AddPatient();
AddDevice();
AddDeviceDataRecords();
}
Temos duas maneiras de implementá-lo:
- Três testes nos quais cada um verifica um método (AddPatient, AddDevice, AddDeviceDataRecords) foram chamados
- Um teste que verifica todos os três métodos foi chamado
No primeiro caso, se algo de errado acontecer com a condição da cláusula if, todos os três testes falharão. Mas, no segundo caso, se o teste falhar, não temos certeza do que está exatamente errado. De que maneira você prefere?
fonte
A granularidade no seu exemplo parece ser a diferença entre testes de unidade e aceitação.
Um unittest testa uma única unidade de funcionalidade, com o menor número possível de dependências. No seu caso, poderia haver 4 unittests
Os unittests são para os desenvolvedores , para que eles obtenham confiança, que seu código esteja tecnicamente correto
Os testes de aceitação devem testar a funcionalidade combinada, da perspectiva do usuário. Eles devem ser modelados ao longo das histórias de usuários e ter o mais alto nível possível. Portanto, você não precisa verificar se as funções são chamadas, mas se um benefício visível para o usuário é alcançado:
quando o usuário digita os dados, clica em ok e ...
testes de aceitação são para os clientes ou para construir uma melhor comunicação com eles.
Para responder à sua pergunta "o que você prefere": qual é um problema maior para você agora, bugs e regressão (=> mais unittests) ou entender e formalizar o cenário geral (=> mais testes de aceitação)
fonte
Isso é falso.
Você deve fazer isso para garantir que funcione.
Você também deve fazer isso para garantir que a API funcione.
A classe - como uma unidade - deve ser completamente testada. Cada método.
Você pode começar com um teste que cubra todos os três métodos, mas não diz muito.
Corrigir. É por isso que você testa todos os métodos.
Você deve testar a interface pública. Como essa classe faz três coisas mais uma (mesmo que estejam agrupadas em um método por causa da história do usuário), você deve testar todas as quatro coisas. Três pacotes de baixo nível e um.
fonte
Escrevemos nossos testes de unidade para frases significativas de funcionalidade que muitas vezes são mapeadas para um método (se você escreveu bem o seu código), mas às vezes ficam maiores, abrangendo muitos métodos.
Por exemplo, imagine que adicionar um paciente ao seu sistema precise que algumas sub-rotinas (funções filho) sejam chamadas:
Também podemos escrever teste de unidade para cada uma dessas funções.
fonte
Uma regra simples que eu tenho seguido é nomear o teste para que ele descreva com precisão o que o teste faz. Se o nome do teste ficar muito complexo, é um sinal de que o teste talvez esteja fazendo muito. Por exemplo, nomear um teste para fazer o que você propõe na opção 2 pode se parecer com PatientIsAddedDeviceIsAddedAndDeviceDataRecordsWhenSaved, que é muito mais complexo do que três testes separados PatientIsAddedWhenSaved, DeviceIsAddedWhenSaved, DataRecordsWhenSaved. Também acho que as lições que podem ser aprendidas com o BDD são bastante interessantes, onde cada teste é realmente representativo de um único requisito que pode ser descrito em uma linguagem natural.
fonte