Deixe-me começar conectando as fontes - Teste de Unidade Pragmático em Java com JUnit (há uma versão com C # -Nunit também .. mas eu tenho esta .. é agnóstica na maior parte. Recomendado.)
Bons testes devem ser A TRIP (a sigla não é pegajosa o suficiente - eu tenho uma impressão da folha de cheats no livro que eu tive que puxar para ter certeza de que entendi direito ..)
- Automático : a chamada de testes, bem como a verificação de resultados para APROVAÇÃO / FALHA, deve ser automática
- Completo : Cobertura; Embora os bugs tendam a se agrupar em torno de certas regiões no código, certifique-se de testar todos os caminhos e cenários principais. Use ferramentas se precisar conhecer regiões não testadas
- Repetível : os testes devem produzir os mesmos resultados todas as vezes ... todas as vezes. Os testes não devem depender de parâmetros incontroláveis.
- Independente : Muito importante.
- Os testes devem testar apenas uma coisa de cada vez. Múltiplas asserções estão bem, desde que todas estejam testando um recurso / comportamento. Quando um teste falha, ele deve apontar a localização do problema.
- Os testes não devem depender uns dos outros - isolados. Sem suposições sobre a ordem de execução do teste. Certifique-se de 'lousa limpa' antes de cada teste usando configuração / desmontagem de forma adequada
Profissional : a longo prazo, você terá tanto código de teste quanto produção (se não mais), portanto, siga o mesmo padrão de bom design para seu código de teste. Métodos bem fatorados - classes com nomes reveladores de intenções, sem duplicação, testes com bons nomes, etc.
Bons testes também são executados rapidamente . qualquer teste que leve mais de meio segundo para ser executado .. precisa ser trabalhado. Quanto mais tempo o conjunto de testes leva para ser executado ... menos freqüentemente ele será executado. Quanto mais mudanças o desenvolvedor tentará fazer entre as execuções .. se alguma coisa quebrar .. levará mais tempo para descobrir qual mudança foi a culpada.
Atualização 2010-08:
- Legível : pode ser considerado parte do Professional - no entanto, não pode ser enfatizado o suficiente. Um teste ácido seria encontrar alguém que não faz parte de sua equipe e pedir-lhe para descobrir o comportamento sob teste em alguns minutos. Os testes precisam ser mantidos da mesma forma que o código de produção - portanto, facilite a leitura, mesmo que exija mais esforço. Os testes devem ser simétricos (seguir um padrão) e concisos (testar um comportamento de cada vez). Use uma convenção de nomenclatura consistente (por exemplo, o estilo TestDox). Evite bagunçar o teste com "detalhes incidentais" .. torne-se minimalista.
Além dessas, a maioria das outras são diretrizes que reduzem o trabalho de baixo benefício: por exemplo, 'Não teste código que você não possui' (por exemplo, DLLs de terceiros). Não saia para testar getters e setters. Fique de olho na relação custo-benefício ou probabilidade de defeito.
fonte
A maioria das respostas aqui parece abordar as práticas recomendadas de teste de unidade em geral (quando, onde, por que e o quê), em vez de realmente escrever os próprios testes (como). Como a pergunta parecia bem específica na parte "como", pensei em postar isso, tirado de uma apresentação "bolsa marrom" que fiz na minha empresa.
Testes das 5 Leis da Escrita de Womp:
1. Use nomes de métodos de teste longos e descritivos.
2. Escreva seus testes em um estilo Arrange / Act / Assert .
3. Sempre forneça uma mensagem de falha com seus Asserts.
4. Comente o motivo do teste - qual é a premissa do negócio?
5. Cada teste deve sempre reverter o estado de qualquer recurso que toque
fonte
Mantenha esses objetivos em mente (adaptado do livro xUnit Test Patterns de Meszaros)
Algumas coisas para tornar isso mais fácil:
Não se esqueça que você pode fazer testes de integração com o seu framework xUnit também, mas mantenha os testes de integração e testes de unidade separados
fonte
Os testes devem ser isolados. Um teste não deve depender de outro. Além disso, um teste não deve depender de sistemas externos. Em outras palavras, teste seu código, não o código do qual seu código depende. Você pode testar essas interações como parte de seus testes de integração ou funcionais.
fonte
Algumas propriedades de ótimos testes de unidade:
Quando um teste falha, deve ser imediatamente óbvio onde está o problema. Se você tiver que usar o depurador para rastrear o problema, então seus testes não são granulares o suficiente. Ter exatamente uma afirmação por teste ajuda aqui.
Ao refatorar, nenhum teste deve falhar.
Os testes devem ser executados tão rápido que você nunca hesite em executá-los.
Todos os testes devem passar sempre; sem resultados não determinísticos.
Os testes de unidade devem ser bem fatorados, assim como seu código de produção.
@Alotor: Se você está sugerindo que uma biblioteca deve ter apenas testes de unidade em sua API externa, eu discordo. Quero testes de unidade para cada classe, incluindo classes que não exponho a chamadores externos. (No entanto, se sentir necessidade de escrever testes para métodos privados, preciso refatorar. )
EDIT: Houve um comentário sobre a duplicação causada por "uma afirmação por teste". Especificamente, se você tiver algum código para configurar um cenário e quiser fazer várias afirmações sobre ele, mas tiver apenas uma afirmação por teste, poderá duplicar a configuração em vários testes.
Eu não adoto essa abordagem. Em vez disso, uso acessórios de teste por cenário . Aqui está um exemplo aproximado:
fonte
O que você quer é delinear os comportamentos da classe em teste.
A intenção básica é aumentar sua confiança no comportamento da classe.
Isso é especialmente útil ao analisar a refatoração de seu código. Martin Fowler tem um interessante artigo sobre testes em seu site.
HTH.
Felicidades,
Roubar
fonte
O teste deve falhar originalmente. Então você deve escrever o código que os faz passar, caso contrário, você corre o risco de escrever um teste que está bugado e sempre passa.
fonte
Eu gosto do acrônimo Right BICEP do livro Pragmatic Unit Testing mencionado acima :
Pessoalmente, acho que você pode ir muito longe verificando se obteve os resultados corretos (1 + 1 deve retornar 2 em uma função de adição), experimentando todas as condições de contorno que você pode pensar (como usar dois números cuja soma é maior do que o valor máximo inteiro na função add) e forçando condições de erro, como falhas de rede.
fonte
Bons testes precisam ser sustentáveis.
Ainda não descobri como fazer isso em ambientes complexos.
Todos os livros didáticos começam a se desgrudar à medida que sua base de código começa a atingir centenas de 1000 ou milhões de linhas de código.
Uma boa arquitetura pode controlar parte da explosão de interação, mas, inevitavelmente, conforme os sistemas se tornam mais complexos, o sistema de teste automatizado cresce com isso.
É aqui que você começa a lidar com compensações:
Você também precisa decidir:
onde você armazena casos de teste em sua base de código?
Eu poderia continuar para sempre, mas o que quero dizer é que:
Os testes precisam ser mantidos.
fonte
Abordei esses princípios há algum tempo neste artigo da MSDN Magazine, que acho importante para qualquer desenvolvedor ler.
A maneira como defino testes de unidade "bons" é se eles possuem as três propriedades a seguir:
fonte
fonte
Jay Fields tem muitos bons conselhos sobre como escrever testes de unidade e há um post onde ele resume os conselhos mais importantes . Lá você vai ler que deve pensar criticamente sobre o seu contexto e julgar se o conselho vale para você. Você obtém uma tonelada de respostas incríveis aqui, mas cabe a você decidir qual é a melhor para o seu contexto. Experimente-os e apenas refatorando se isso cheirar mal para você.
Atenciosamente
fonte
Nunca assuma que um método trivial de 2 linhas funcionará. Escrever um teste de unidade rápido é a única maneira de evitar que o teste nulo ausente, o sinal de menos mal colocado e / ou o erro de escopo sutil o mordam, inevitavelmente quando você tem ainda menos tempo para lidar com isso do que agora.
fonte
Eu apoio a resposta "A TRIP", exceto que testes DEVEM depender uns dos outros !!!
Por quê?
DRY - Dont Repeat Yourself - aplica-se a testes também! As dependências de teste podem ajudar a 1) economizar tempo de configuração, 2) economizar recursos de fixação e 3) apontar falhas. Claro, apenas considerando que sua estrutura de teste oferece suporte a dependências de primeira classe. Caso contrário, admito, eles são ruins.
Acompanhamento http://www.iam.unibe.ch/~scg/Research/JExample/
fonte
Freqüentemente, os testes de unidade são baseados em objetos ou dados fictícios. Gosto de escrever três tipos de testes de unidade:
O objetivo é evitar repetir tudo para poder testar todas as funções.
fonte
Pense sobre os 2 tipos de teste e trate-os de forma diferente - teste funcional e teste de desempenho.
Use diferentes entradas e métricas para cada um. Você pode precisar usar um software diferente para cada tipo de teste.
fonte
Eu uso uma convenção de nomenclatura de teste consistente descrita pelos padrões de nomenclatura de teste de unidade de Roy Osherove Cada método em uma determinada classe de caso de teste tem o seguinte estilo de nomenclatura MethodUnderTest_Scenario_ExpectedResult.
A primeira seção de nome de teste é o nome do método no sistema em teste.
A seguir está o cenário específico que está sendo testado.
Finalmente estão os resultados desse cenário.
Cada seção usa Upper Camel Case e é delimitada por uma pontuação inferior.
Achei isso útil quando executo o teste, os testes são agrupados pelo nome do método em teste. E ter uma convenção permite que outros desenvolvedores entendam a intenção do teste.
Também acrescento parâmetros ao nome do Método se o método em teste estiver sobrecarregado.
fonte