Testes de software — Boas Práticas
Falaremos aqui especificamente de testes de unitários, eles normalmente são mais comuns e devem ser feitos em maiores quantidades.
Benefícios da criação de testes
Começaremos falando dos benefícios para criar testes unitários, afinal de contas, o usuário final não precisa do código gerado pelos testes.
- Garantir maior segurança em manutenções e evoluções.
- Garantir um código mais conciso.
- Serve como uma documentação para os desenvolvedores.
Esses são três objetivos que justificam a necessidade de criação de testes.
“Código legado é aquele sem testes.”
― Michael Feathers
Boas práticas na criação de testes
Para entendermos como os testes devem ser comportar, vamos entender dois acrônimos, o FIRST e o CORRECT.
Os praticantes do TDD, seguem o princípio de começar com os testes, fazer com que ele falhe, depois escrever o código para fazer o teste passar e seguir esse fluxo até finalizar a demanda.
Entretanto, mesmo não seguindo o TDD, é preciso escrever os testes respeitando o FIRST:
Fast: Quanto mais rápido melhor, então o ideal é não depender de integrações externas, como acesso a arquivos, internet, banco de dados…
Independent: Um teste não pode depender de outro, deve poder ser executado independente da ordem da execução.
Repeatable: Independente da quantidade de vezes que ele for executado, a saída dele deve ser a mesma.
Self-validating: Cada teste precisa ter pelo menos uma assertiva para validar a execução.
Thorough/Timely: Os testes precisam realizar uma cobertura de forma inteligente, buscando identificar todos os possíveis cenários, para garantir que o software funcionará em todos eles.
E eles também precisam ser feitos no momento correto, a criação dos testes ajudam a deixar o código mais limpo, então eles devem ser feitos antes de ir para produção.
Além dos testes serem FIRST, é necessário também pensar que ele deve ser CORRECT.
Esse acrónimo é útil para validar se o seu teste está adequado. Para isso é necessário responder as seguintes perguntas:
Conformity: O dado representa o tipo esperado?
Order: A ordem dos resultados está conforme esperado?
Range: O tamanho do dado está validado?
Reference: O código faz referência a algo em um contexto externo?
Existence: O valor pode ser negativo, nulo, vazio?
Cardinality: Há valores suficientes?
Time: Está tudo sendo executado na ordem correta, está seguro contra concorrência?
Exemplo: Está consultando o registro e depois realizado o update.
Nomenclatura dos testes
Além desses acrónimos é muito importante você criar testes com nomes significativos. Os testes podem ser executados por novos integrantes para entender melhor o objetivo de determinada classe.
Para dar nomes aos testes, existem algumas abordagens mais famosas:
“Given-When-Then”: De acordo com determinado contexto, quando acontecer determinado acontecimento, deve gerar determinado resultado.
Por exemplo: dadoUsuarioEstaLogadoQuandoClicarSairDeveraRemoverSessao();
“When-Then”: É comum também utilizar sem o contexto.
Por exemplo: quandoUsuarioLogarDeveExibirTermosUso();
“Should-When”: Deve gerar determinado resultado quando acontecer alguma ação.
Por exemplo: deveHaverDescontoAoComprarMuito();
Essa foi uma introdução na importância dos testes e o que deve ser pensando quando for cria-los. Para finalizar, lembre-se que se os seus testes de degradarem, o seu código também irá, então mantenha limpos os seus testes.
Referências:
Pragmatic Unit Testing in Java 8 With JUnit
- Jeff Langr, Andy Hunt, Dave Thomas
Clean code
- Robert Cecil Martin