90% de cobertura de testes em projetos Python
O benefício dos testes de software é reconhecido pela maioria dos desenvolvedores. Quando guiados por testes, os times criam código mais resiliente e controlado; seus deploys tendem a ser eventos triviais no dia-a-dia; os bugs são descobertos rapidamente, entre inúmeras outras vantagens. No entanto, é atípico encontrar equipes que levem a teoria à prática desenvolvendo e mantendo seus testes.
Com a cultura ágil da OLX Brasil, essa boa prática é fundamental em nossos projetos. O time de Produtos Pagos, onde atuo, têm projetos em Python com, no mínimo, noventa por cento de cobertura de testes.
Como medimos?
Nossos projetos utilizam o Coverage.py, uma lib que permite executar os testes por linha de comando. Além disso, ela possibilita o uso de parâmetros e exibe um relatório para cada arquivo com as linhas que não foram testadas.
Adicionar essa lib ao projeto é bem simples, basta instalá-la com:
$ pip3 install coverage
Para usá-la, basta:
$ coverage run tests/tests.py
Para medir a cobertura, garantir que falhe se estiver abaixo do parâmetro definido e exibir o relatório, use:
$ coverage report — fail-under=90 — show-missing
Esse é um relatório de cobertura:
Como garantimos?
Usando o parâmetro fail-under=90 em nosso estágio de testes da pipeline do CI, nós definimos que esse é o mínimo para sucesso nessa etapa. Caso contrário, mesmo que todos os testes passem, teremos um erro ao final da execução, bloqueando os estágios seguintes.
A decisão de parametrizar os testes na pipeline do CI deu visibilidade e garantiu a preservação desse valor alto no longo prazo.
Adoção do time
Antes disso, tínhamos pouca clareza da porcentagem e distribuição dos testes, que eram deixados para o final do processo de desenvolvimento.
Nós amadurecemos com esse método e hoje é normal que a equipe use o TDD e que nossos merge requests tenham mais linhas de teste do que de código. Escrever testes deixou de ser um trabalho extra e passou a ser parte, por vezes guia, do desenvolvimento.
Criatividade nos testes
Outra mudança consequente disso é que passamos a testar o código exaustivamente (já que precisávamos de alta cobertura). Agora testamos fluxos de sucesso mas também de erro, assim como falhas isoladas e combinadas (um serviço fora do ar, um payload inválido, um serviço fora do ar e um payload inválido).
Expandimos não só os testes unitários mas também de integração, exploramos cada função separada e cada classe que une vários métodos para responder uma requisição.
Hoje falamos e nos preocupamos mais sobre esse assunto, a ponto de monitorar o valor e sempre buscar melhorá-lo. Noventa por cento pareceu assustador no momento que decidimos, mas se mostrou viável no dia-a-dia.
Quantidade é tudo?
Não mesmo. Outra lenda que é reconhecida pela grande maioria dos desenvolvedores é que o usuário é um ser fascinante.
Então, por mais que o time garanta noventa por cento de cobertura, não garantimos a inexistência de falhas, até porque as aplicações e necessidades mudam, pois estão sempre evoluindo. Mas, com essa verificação, evitamos de colocar vários bugs em produção e temos muito mais segurança de seguir com os deploys para atender de forma rápida o propósito dos nossos serviços: trazer valor pro usuário.