Quantos testes por método?
Bem, o máximo teórico e altamente impraticável é a complexidade do N-Path (suponha que todos os testes abranjam maneiras diferentes através do código;)). O mínimo é UM !. Por método público , isto é, ele não testa detalhes da implementação, apenas comportamentos externos de uma classe (retornam valores e chamam outros objetos).
Você cita:
* E o pensamento de testar cada um de seus métodos com seu próprio método de teste (em um relacionamento de 1 a 1) será risível. *
e depois pergunte:
Portanto, se a criação de um teste para cada método é 'risível', como / quando você escolhe para que escreve os testes?
Mas acho que você não entendeu o autor aqui:
A idéia de ter one test method
por one method in the class to test
é o que o autor chama de "risível".
(Pelo menos para mim) Não se trata de 'menos', é de 'mais'
Então deixe-me reformular como eu o entendi:
E o pensamento de testar cada um de seus métodos com SOMENTE UM MÉTODO (seu próprio método de teste em um relacionamento de 1 a 1) será risível.
Para citar sua cotação novamente:
Quando você percebe que se trata de especificar comportamento e não de escrever testes, seu ponto de vista muda.
Quando você pratica TDD , não pensa :
Eu tenho um método calculateX($a, $b);
e ele precisa de um teste testCalculcateX
que teste TUDO sobre o método.
O que o TDD diz é para pensar sobre como o seu código DEVE FAZER :
Preciso calcular o maior dos dois valores ( primeiro caso de teste! ), Mas se $ a for menor que zero, ele deverá gerar um erro ( segundo caso de teste! ) E se $ b for menor que zero, deverá ... ( terceiro caso de teste! ) e assim por diante.
Você deseja testar comportamentos, não apenas métodos únicos sem contexto.
Dessa forma, você obtém um conjunto de testes que é documentação para o seu código e REALMENTE explica o que é esperado que ele faça, talvez até o porquê :)
Como você decide para qual parte do seu código você cria testes de unidade?
Bem, tudo o que acaba no repositório ou em qualquer lugar perto da produção precisa de um teste. Eu não acho que o autor de suas citações discordaria disso, como tentei declarar acima.
Se você não tiver um teste, fica muito mais difícil (mais caro) alterar o código, especialmente se você não estiver fazendo a alteração.
O TDD é uma maneira de garantir que você tenha testes para TUDO, mas contanto que você os escreva, tudo bem. Normalmente, escrevê-las no mesmo dia ajuda, já que você não fará isso mais tarde, vai? :)
Resposta aos comentários:
uma quantidade decente de métodos não pode ser testada em um contexto específico porque eles dependem ou dependem de outros métodos
Bem, existem três coisas que esses métodos podem chamar:
Métodos públicos de outras classes
Podemos zombar de outras classes e definir o estado lá. Estamos no controle do contexto, então isso não é um problema.
* Métodos protegidos ou privados no mesmo *
Qualquer coisa que não faça parte da API pública de uma classe não é testada diretamente, geralmente.
Você deseja testar o comportamento e não a implementação e, se uma classe faz tudo, funciona em um grande método público ou em muitos métodos protegidos menores chamados de implementação . Você deseja alterar esses métodos protegidos sem tocar nos seus testes. Porque seus testes serão interrompidos se o seu código mudar de comportamento! É para isso que servem seus testes, para dizer quando você quebra alguma coisa :)
Métodos públicos na mesma classe
Isso não acontece com muita frequência, acontece? E se gostar do exemplo a seguir, existem algumas maneiras de lidar com isso:
$stuff = new Stuff();
$stuff->setBla(12);
$stuff->setFoo(14);
$stuff->execute();
Que os setters existem e não fazem parte da assinatura do método execute é outro tópico;)
O que podemos testar aqui é se as execuções explodem quando definimos os valores errados. Isso setBla
gera uma exceção quando você passa uma string e pode ser testado separadamente, mas se quisermos testar se esses dois valores permitidos (12 e 14) não funcionam JUNTOS (por qualquer motivo) do que esse é um caso de teste.
Se você deseja uma suíte de testes "boa", pode, em php, talvez (!) Adicionar uma @covers Stuff::execute
anotação para garantir que você gere apenas cobertura de código para esse método e que outras coisas que estão apenas configuradas precisam ser testadas separadamente (novamente, se você quer isto).
Portanto, o ponto é: talvez você precise criar parte do mundo circundante primeiro, mas deve ser capaz de escrever casos de teste significativos que geralmente abrangem apenas uma ou talvez duas funções reais (setters não contam aqui). O restante pode ser zombado do éter ou ser testado primeiro e depois confiar (ver @depends
)
* Nota: A questão foi migrada do SO e, inicialmente, era sobre PHP / PHPUnit, é por isso que o código de exemplo e as referências são do mundo php, acho que isso também é aplicável a outras linguagens, pois o phpunit não difere muito dos outros xUnit estruturas de teste.