29 boas práticas para escrita de código de testes

Neste artigo você vai ver:

A atividade de teste de software é inegavelmente crucial para o processo de desenvolvimento. Embora a escrita de código de testes (test code) não garanta a ausência de bugs em produtos, a falta de testes tornam o processo de desenvolvimento mais frágil, uma vez que se torna mais difícil repetir o comportamento de um erro inesperado e garantir que o problema não volte a acontecer. 

Dessa forma, pessoas desenvolvedoras de software contam com um rico arsenal de prática, técnicas e ferramentas para apoiar o processo de escrita de testes de software. 

Aqui mesmo, no blog da Zup, já discutimos diversas abordagens de testes, das mais tradicionais como teste manual, até estratégias mais sofisticadas como testes fuzzing, passando por testes de contratos, pelo papel do testador, dentre vários outros. 

Refletindo sobre a escrita de código de testes

No entanto, embora existam diversas técnicas e processos, é importante refletir e debater sobre quais seriam as melhores práticas para escrita de código de testes ou test code

Por exemplo, até que ponto devemos nos preocupar com essa etapa que avalia o comportamento excepcional da nossa aplicação? Ou, por exemplo, qual seria o tamanho ideal (em termos de linha de código) para um código de testes? Ou ainda, se faz sentido testar os métodos mais simples da minha aplicação, como gets e sets, ou mesmo um equals ou hashcode?

Possivelmente, dúvidas como essas e similares, já devem ter passado pela cabeça de devs que curtem escrever código de testes. Nesse momento, o mais comum é confiar na opinião da pessoa desenvolvedora mais experiente do time ou talvez consultar algum texto de blog ou livro. 

Entretanto, embora a opinião das pessoas mais experientes, que inclusive se tornam referências nas comunidades técnicas sejam relevantes, no final do dia, não deixa de ser a opinião de uma única pessoa, que tem suas próprias crenças e vieses. 

Aumentando a percepção sobre a qualidade de um código de testes

Como forma de tentar minimizar esses vieses e obter uma percepção mais ampla sobre as boas práticas para escrita de código de testes, um grupo de pesquisa fez um estudo composto de duas etapas

Primeira etapa

Em um primeiro momento, profissionais de pesquisa selecionaram 21 pessoas desenvolvedoras experientes, que trabalham em empresas de tecnologias renomadas, bem como em projetos de software livre da Apache. Essas pessoas foram entrevistadas com o objetivo de entender determinadas questões, como: 

  • Como você definiria um bom código de teste?
  • Quais critérios você utilizaria para caracterizar a qualidade de um código de teste?
  • Quais fatores você considera quando vai escrever um código de teste?

Nessa etapa, foram analisadas todas as entrevistas e levantadas 29 características que poderiam ajudar a constituir um bom código de teste. Essas características foram agrupadas em seis dimensões: conteúdo do código de teste, tamanho e complexidade, cobertura, manutenção, capacidade de detectar bugs e outras.

Segunda etapa

Após apurarem essa lista, o time de pesquisa foi além e fez um segundo estudo. Nessa etapa, 261 pessoas desenvolvedoras de empresas de tecnologia receberam o convite para responder um questionário de validação. 

Nesse questionário, era preciso priorizar as 29 características descobertas anteriormente. O objetivo desta segunda etapa era entender quais poderiam ser as características mais importantes que as pessoas desenvolvedoras poderiam se apoiar para criar seus códigos de testes. 

A tabela a seguir apresenta a lista de características dos códigos de teste. Na última coluna desta mesma tabela, está a média das avaliações das pessoas que responderam o questionário de validação. 

A escala da validação ia de um (pouco relevante) até cinco (muito relevante). Logo, os itens com valor mais próximo de cinco indicam as características mais relevantes, de acordo com as pessoas que responderam a pesquisa.

CaracterísticaVotos
Conteúdo
Um bom caso de teste deve ser específico ou atômico, ou seja, deve testar um único aspecto de um requisito3.93
Casos de teste em uma suíte de testes devem ser autocontidos, ou seja, devem ser independentes uns dos outros3.95
Bons casos de teste devem verificar o fluxo normal e excepcional4.47
Os casos de teste devem executar a análise de valor de limite, ou seja, tomar como valores de entrada os extremos de um domínio de entrada4.24
Os casos de teste devem servir como uma boa documentação de referência3.93
Tamanho e complexidade
A maioria dos casos de teste deve ser pequena em tamanho (em termos de linhas de código)3.85
Casos de teste grandes geralmente são difíceis de entender e manter3.73
Casos de teste grandes podem ser necessários para detectar bugs difíceis3.59
Um bom conjunto contém muitos casos de teste pequenos (com menos LOC) e poucos casos de teste grandes3.97
O aumento da complexidade em um caso de teste pode levar a erros no próprio código de teste4.04
Cobertura
A cobertura de código é necessária, mas não suficiente3.97
A cobertura de código deve ser usada para entender o que está faltando nos testes e criá-los com base nisso3.97
Maior cobertura não significa que um conjunto de testes pode detectar mais bugs4.02
Cada caso de teste deve exercitar uma quantidade de código pequena3.92
Um caso de teste projetado para maximizar a cobertura geralmente é longo, incompreensível e frágil (ou seja, quebra facilmente)3.50
Projetar casos de teste para cobrir requisitos diferentes geralmente é mais importante do que projetar casos de teste para cobrir mais códigos4.00
Manutenibilidade
Um bom caso de teste deve ser bem modularizado4.62
Um bom caso de teste deve ser legível e compreensível4.58
Os casos de teste devem ser mais simples do que o código que está sendo testado4.20
O código de teste deve ser projetado tendo em mente a capacidade de manutenção, pois a evolução do código geralmente requer alterações no código de teste4.16
Os links de rastreabilidade devem ser mantidos entre o código de teste, os requisitos e o código-fonte3.97
Detecção de bugs
Um bom caso de teste deve tentar interromper a funcionalidade para encontrar possíveis bugs4.11
Teste até as coisas mais simples que não podem dar errado3.89
Durante a manutenção, quando um bug é corrigido, é bom adicionar um caso de teste que o cubra4.40
As asserções de teste podem ajudar a detectar erros sutis que, de outra forma, poderiam passar despercebidos4.51
Adicionar erros comuns e possíveis causas como comentários no código de teste é útil para depurar falhas3.98
Outros
Um bom caso de teste deve ser projetado de forma que seus resultados sejam determinísticos4.07
Os casos de teste em um conjunto de testes não devem ter efeitos colaterais, portanto executar um teste antes ou depois de outro não deve alterar os resultados4.28
Os casos de teste devem usar tags ou categorias, como testes lentos, testes rápidos, etc., para poder executar um conjunto específico de testes facilmente por vez3.93

As principais características da escrita de código de testes

De acordo com a pesquisa, as três características mais relevantes dentre as mais votadas são as seguintes: 

Um bom caso de teste deve ser legível e fácil de se compreender (4.58)

Mais de 96% de profissionais acreditam que códigos de testes devem ser fáceis de ler e entender. Essa foi a característica mais votada do estudo, o que é interessante, pois não está associada diretamente com a capacidade do teste de revelar bugs e, sim, com a capacidade do código ser mantido e evoluído. 

Uma das pessoas que participou do estudo complementou dizendo que “Como qualquer código, se você precisar mantê-lo, é melhor entendê-lo.” No entanto, outra pessoa comentou que embora essa seja uma característica importante, não é necessariamente fácil de se alcançar: “É um desafio manter o teste de unidade com boa aparência.

Em um outro estudo, foi observado que códigos de testes que são difíceis de serem entendidos são também mais difíceis de serem corrigidos em caso de falha.

Assertions ajudam a detectar erros sutis que, de outra forma, poderiam passar despercebidos (4.51)

Assertions são construções de código de teste que ajudam, através de comparações de valores, avaliar se uma determinada propriedade tem o comportamento que se espera observar. 

A maioria das pessoas acredita que o uso de assertions é essencial na escrita de bons casos de teste. Como uma pessoa exemplificou: “você precisa ter asserções em um teste, caso contrário, você está apenas exercitando o sistema”. 

Essa observação está também alinhada com outros estudos que indicam que o uso de assertions está fortemente correlacionado com a efetividade da suíte de testes.

Bons casos de teste devem verificar o fluxo normal e excepcional (4.47)

A terceira característica mais votada foi a necessidade de escrever testes que exercitem o comportamento normal e também o excepcional das nossas aplicações. 

Inclusive, uma pessoa que respondeu a pesquisa comentou que “Você se concentra no caso feliz para verificar se a funcionalidade de negócios está OK… e então (escreve o código de teste) para garantir que todos os casos extremos foram tratados adequadamente.”

Outras características interessantes

As três primeiras características acima são mais gerais e, talvez por isso, foram mais bem votadas. Porém, também houve algumas características mais técnicas que tiveram um bom nível de votação, como: 

  • A cobertura de código é necessária, mas não suficiente (no sentido de garantir que um código está livre de bugs);
  • Os casos de teste devem executar a análise de valor de limite;
  • Os casos de teste de uma suíte de testes devem ser independentes uns dos outros.

Por conta do nosso espaço aqui, vamos deixar a discussão sobre as demais características para você discutir nos comentários. No entanto, para uma análise mais profunda das práticas, sugerimos a leitura completa do artigo ?. 

Na Zup, inclusive, temos o clube do artigo, que é um momento em que zuppers se reúnem para ler e debater artigos científicos. Este artigo sobre qualidade dos testes foi tópico do nosso segundo encontro, que rendeu bastante discussão!

Falando em boas práticas, confira um episódio do Zup Tech Hour sobre programação com um time de especialistas:

Conclusão

A escrita de código de testes ou test code não é uma tarefa fácil, porém de suma importância. Neste texto, visitamos um artigo científico que derivou uma lista de características para bons códigos de testes. 

Depois de entender um pouco mais sobre como avaliar a qualidade dos testes, será que podemos olhar para os testes que escrevemos e apontar onde podemos melhorar? Será que conseguimos empregar alguma dessas características no próximo teste que escreveremos?

Conte pra gente se você pensa em adotar algumas dessas características! Nossos comentários estão disponíveis para a discussão.

Imagem capa, referente ao conteúdo sobre "escrita de código de testes", em que contém uma mulher branca, sentada de frente dois computadores e um notebook que possuem diversos códigos.
Foto de Gustavo Pinto
Pesquisador
Uso metodologia científica pra testar as crenças dos times de desenvolvimento. Será que Kotlin é mesmo melhor que Java? Será que multirepos é melhor que monorepos? Será mesmo?

Este site utiliza cookies para proporcionar uma experiência de navegação melhor. Consulte nossa Política de Privacidade.