Sumário 🔗
Testes unitários para salvar sua vida 🔗
Pular os testes unitários é igual pular o dia de pernas na academia. Você pode até achar que está indo bem, mas no fundo sabe que está fazendo algo errado. A verdade é que os testes unitários são uma parte essencial do desenvolvimento de software. Eles garantem que o código funcione como esperado, ajudam a identificar bugs e facilitam a manutenção do código a longo prazo. Neste post, vamos explorar a importância dos testes unitários (e de integração) e como eles podem salvar sua vida (ou pelo menos seu código).
O que são testes unitários? 🔗
O teste unitário garante a confiabilidade específica de um componente do seu software. Ele também assegura que a manutenção do seu método seja mais fácil e reduz o risco de introduzir bugs.
Boas práticas 🔗
- Defina um padrão de nome para os testes: Use nomes descritivos para os testes, como
TestClient_Games
, para que seja fácil entender o que está sendo testado. Evite criar funções com nomes muito extensos ou complexos, comumente escritos em linguagens como Node.js e Ruby. Vide exemplo mais abaixo. - Defina a procentagem mínima de cobertura de código: Estabeleça uma porcentagem mínima de cobertura de código para garantir que os testes cubram uma parte significativa do seu código. Isso ajuda a identificar áreas que precisam de mais testes. Inclusive você pode fazer a sua pipeline de CI falhar caso a cobertura de código esteja abaixo do mínimo estabelecido. Por exemplo, 60% de cobertura de código é um bom ponto de partida.
- Testes de funções exportadas: Os testes devem ser escritos no arquivo
filename_test.go
e devem estar dentro do pacote{package}_test
. Isso garante que as funções exportadas sejam testadas corretamente e chamamos de black box testing. - Testes de funções não exportadas: Os testes devem ser escritos no arquivo
filename_internal_test.go
e devem estar dentro do mesmo pacote{package}
. Isso garante que as funções não exportadas sejam testadas de forma separada. - Crie cenários de sucesso e falha: Escreva testes para cenários de sucesso e falha, mas explore mais os cenário de falha.
- Return struct, accept interface: Ao escrever funções, retorne uma estrutura de dados e aceite interfaces como parâmetros. Isso facilita a criação de mocks e testes mais flexíveis. Evite criar interfaces muito genéricas e complexas, pois isso pode dificultar a compreensão e manutenção do código, além de tornar a criação de mocks mais difícil.
Node.js:
|
|
Ruby:
|
|
Go:
|
|
|
|
Deixo aqui uma sugestão de repositório com muitos testes unitários bem escritos: WakaTime CLI.
Na segunda parte deste post, vamos abordar subtests e table driven tests, que são técnicas avançadas para escrever testes mais eficientes e organizados. Fique ligado!