Estou projetando e desenvolvendo código com o estilo TDD há muito tempo. O que me incomoda no TDD é escrever testes para código que não contém nenhuma lógica comercial ou comportamento interessante. Sei que o TDD é uma atividade de design mais do que testar, mas às vezes sinto que é inútil escrever testes nesses cenários.
Por exemplo, eu tenho um cenário simples como "Quando o usuário clica no botão de verificação, ele deve verificar a validade do arquivo" . Para esse cenário, geralmente começo a escrever testes para a classe apresentador / controlador, como a abaixo.
@Test
public void when_user_clicks_check_it_should_check_selected_file_validity(){
MediaService service =mock(MediaService);
View view =mock(View);
when(view.getSelectedFile).thenReturns("c:\\Dir\\file.avi");
MediaController controller =new MediaController(service,view);
controller.check();
verify(service).check("c:\\Dir\\file.avi");
}
Como você pode ver, não há decisão de design ou código interessante para verificar o comportamento. Estou testando valores da exibição passada para o MediaService. Normalmente escrevo, mas não gosto desse tipo de teste. O que você faz sobre essas situações? Você escreve testes o tempo todo?
ATUALIZAÇÃO:
Alterei o nome e o código do teste após as reclamações. Alguns usuários disseram que você deve escrever testes para casos triviais como esse, para que no futuro alguém possa adicionar um comportamento interessante. Mas e quanto a "Código para hoje, design para amanhã". ? Se alguém, inclusive eu, adicionar um código mais interessante no futuro, o teste poderá ser criado para ele. Por que devo fazer isso agora para os casos triviais?
fonte
Respostas:
Não pretendo 100% de cobertura de código. E normalmente não escrevo testes de métodos que obviamente não conterão nenhuma lógica comercial e / ou mais do que algumas linhas de código. Mas ainda escrevo testes de unidade (usando TDD) de métodos que não parecem tão complexos. Isso ocorre principalmente porque eu gosto de fazer o teste de unidade já, ao voltar a esse código meses ou mesmo anos depois, e quero torná-lo mais complexo. É sempre mais fácil estender os testes existentes, do que ter que construir tudo do zero. Como Noufal disse, é subjetivo. Meu conselho é escrever os testes, se você acha que o método é um pouco complexo ou tem potencial para se tornar mais complexo.
fonte
Esta é a segunda pergunta do TDD hoje que transmite aborrecimento ao número de testes a serem escritos.
"Teste apenas se você quiser que funcione."
Não tenho muita certeza de entender o teste da pergunta.
Você está verificando se Controller.Check () delega para o serviço (dependência) com o argumento como o valor do arquivo selecionado na exibição? Se sim, este é um bom teste. Permite testar o controlador sem a implementação real do serviço. (micro-testes baseados em interação).
Atualização: Agora que estou claro sobre o que você está tentando testar, provavelmente mudaria algum código e renomearia algumas coisas para que se lê "Test Media Controller delega verificação de arquivo selecionada ao serviço de mídia". - que é uma especificação válida para o controlador.
fonte
Eu não escreveria um teste assim (ou pelo menos não o nomearia assim). Em vez disso, eu escreveria um teste para o recurso que requer essa chamada
check()
, para que, se essa verificação ou uma ação equivalente não for feita, o recurso de alto nível não funcione. Por que seu código precisa chamar ocheck()
método?Em geral, tento manter os testes dissociados dos detalhes da implementação, para que pelo menos o nome do teste fale apenas sobre os recursos externos fornecidos pelo objeto. Detalhes de implementação, como objetos e métodos, não são mencionados no nome do teste.
Isso facilita a refatoração (não deve ser necessário alterar os testes quando você altera a implementação) e também facilita descobrir se um teste está desatualizado (o recurso especificado não é mais necessário) . Também facilitará a observação de códigos desnecessários / inoperantes, porque o clichê de baixo nível (como getters e setters) será adicionado / mantido apenas se forem exigidos por recursos de nível superior.
fonte
Isso é subjetivo. Eu nem sempre faço TDD, mas quando faço, tento manter a cobertura do código como minha métrica para saber se meus testes são abrangentes ou não. Às vezes fico preguiçoso e simplesmente pulo partes que, para mim, parecem "óbvias". Às vezes, violo o ciclo Vermelho, Verde, Refatorador e escrevo mais código do que o necessário, mas, com o tempo, entrei em um ritmo do que me sinto confortável.
fonte
Interações entre classes como a anterior e o original mais simples para as quais eu escreveria um teste. As interações podem se tornar mais complexas ao longo do tempo, portanto, é bom ter o terreno no local.
fonte
Você assume que, no futuro, alguém saberá que esse elemento da interface do usuário existe e o que ele chama no back-end.
Meu projeto atual tem mais de 30 desenvolvedores em seis equipes distintas dentro da mesma base de código. Adições triviais da interface do usuário desaparecem no nevoeiro o tempo todo. Ninguém voltará e incluirá um caso de teste para isso mais tarde, porque ninguém se lembrará de que está lá e, quando isso quebra, a demanda se torna "Por que eles não escreveram um teste? Seria tão simples!"
fonte
Como sempre...
Depende
É difícil ver a utilidade desse teste específico em um contexto de TDD, porque não conhecemos a história.
Se a história for como [usuário de mídia], quero [poder verificar a validade da mídia] para que [saiba quando um arquivo não estiver disponível]
o cenário Fornecido [um botão de verificação de mídia] Quando [o usuário clica no botão] Em seguida [a validade do arquivo é verificada]
faz sentido. É trivial, mas faz sentido.
Se a história abrangente for maior que isso, a definição do cenário poderá ser muito estreita.
Lembrar:
TDD! = Teste de Unidade
TDD testa recursos . Se for um recurso, ele merece um teste para verificá-lo.
fonte