Django-Rest-Framework e Code Coverage: uma métrica complexa e que não diz muita coisa
Tags: python, django, testing, braziliandevs
Published: 2022-12-30 14:32:57

Uma métrica bastante utilizada para direcionar a escrita de testes, principalmente quando os testes estão sendo escritos para ajudar a garantir a qualidade de uma aplicação já escrita, é a porcentagem de cobertura do código (ou, em inglês, o *code coverage*). 

Segundo [1], *code coverage* é uma métrica que determina o número de linhas do código que foi validada pelos testes. Essa é uma definição simplista e que não é muito verdadeira.

As ferramentas de *code coverage* não determinam, de fato, se uma linha foi validada pelos testes, mas sim se ela foi executada durante os testes e existe uma diferença enorme entre ela ser executada e ser validada. Para determinar se essa linha foi, efetivamente, validada é preciso analisar as asserções feitas pelo testes e, se possível, verificar todos os (ou a maioria dos) casos de uso.

Assim sendo, é extramente complexo que uma ferramenta automatizada verifique se uma linha foi, de fato, validada.

Essa introdução levanta alguns pontos sobre ferramentas de cobertura de código em geral que servem para embasar os apontamentos sobre testes com *django-rest-framework* e essas ferramentas.

## Por que verificar a cobertura do código?

O artigo [2] levanta algumas dicas sobre como começar a lidar com *code coverage* e, dentro dessas dicas, levanta um ponto que é um dos principais motivos para se usar essas ferramentas, mesmo com as ""deficiências"" comentadas acima:

> Use coverage reports to identify critical misses in testing

Traduzindo, e adequando, esse trecho quer dizer para "usar relatórios de cobertura para identificar locais críticos sem testes". Por exemplo, veja o caso de uso da imagem abaixo:

![relatório de coverage de um exemplo de autenticação](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1jxu2yyhycbyshrj0kbf.png)

Casos onde não foi possível gerar o Token de autenticação, por algum motivo, não foram testados. Assim, é possível analisar o relatório e decidir se esse será um caso recorrente de erro e que deverá estar coberto com novos testes ou se será algum caso raro e que não deve preocupar o time de desenvolvimento.

## Django-Rest-Framework

A relação entre os pontos comentados acima com o *django-rest-framework* é que, o *django*, principalmente em API's com o *rest-framework*, adota uma perspectiva declarativa para rotas de API com os *ModelViewSet* [3] e isso tem algumas implicações importantes na cobertura de códigos.

Quando um CRUD de algum *model* é definido, de forma declarativa, utilizando o `ModelViewSet`, conforme o exemplo retirado de [3], o que acontece é que não temos dados de cobertura de código sobre todas as rotas (GET, POST, PUT, PATCH, DELETE) desse determinado recurso:

![Exemplo de ModelViewSet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5xzoa3hmrgz074e8nmui.png)

Desse modo, os relatórios de cobertura de código não dizem muita coisa sobre o que está acontecendo dentro do nosso `ModelViewSet`. Porém, ainda assim, servem para casos onde você precisa de funcionalidades que sobrescrevem métodos em *serializers*, *models* ou no próprio *viewset*.

## Conclusão

A conclusão é que, assim como diversos programadores sempre alertam, cobertura de código é uma métrica que traz problemas se olhada cegamente. Para aplicações que utilizam o *django* e *django-rest-framework* (*drf*) isso deve ser levado, ainda mais, em consideração.

Olhar para um plano de testes (de integração principalmente) tendo o relatório de cobertura de código como uma métrica secundária dentro de aplicações *django* + *drf* faz muito mais sentido que olhar apenas para relatório de cobertura para definir o que testar. 

## Referências

1. [Everything you need to know about code coverage](https://www.codegrip.tech/productivity/everything-you-need-to-know-about-code-coverage)
2. [What is code coverage?](https://www.atlassian.com/continuous-delivery/software-testing/code-coverage)
3. [ViewSets](https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset)