Cobertura de testes em Flutter

Como gerar e visualizar um relatório de cobertura

Matheus de Vasconcelos
Mar 26 · 7 min read

Escrever testes é uma das tarefas mais importantes durante o desenvolvimento de um bom produto digital, principalmente porque os testes podem ser um bom indicativo de como está a qualidade do código e, por consequência, do produto. Usamos “pode ser” aqui porque para que seja um bom indicativo é importante que o teste esteja bem escrito e bem estruturado, se não a garantia se perde.

Para quantificar a qualidade que os testes podem atribuir a um produto, uma das métricas mais utilizadas é a cobertura de testes, que indica por quantas linhas do código escrito os testes passaram.

Por exemplo: suponha que seu projeto tenha 10 arquivos e que cada arquivo tenha 10 linhas, resultando um total de 100 linhas. Para descobrir a cobertura de testes desse projeto basta executar os testes e contar as linhas pelas quais ele passa. Supondo que os testes tenham passado por 80 linhas, isso significa que a sua cobertura é de 80%.

Embora não exista uma verdade absoluta sobre qual valor a cobertura deve ter, de modo geral é importante que esse valor seja o mais alto possível sem que a qualidade dos testes se perca. A partir disso, fica clara a importância da cobertura no contexto do produto, certo?

A partir disso, também é importante que o time de desenvolvimento consiga extrair esse dado de maneira fácil, e o mais comum nesses casos é gerar um relatório de cobertura, ou seja, um arquivo que exibe a cobertura do projeto e, muitas vezes, dos arquivos do projeto. Assim, é possível ter um visão macro e micro da métrica de cobertura de testes.

Neste post, vamos entender como gerar esse relatório e garantir que essa métrica esteja gerando valor no Flutter. Como o Flutter não possui uma IDE própria, o desenvolvimento precisa ser feito em outras IDEs ou editores de texto. Os mais utilizados são o VSCode (editor de texto desenvolvido pela Microsoft) e o Android Studio (IDE para desenvolvimento de aplicações Android). Para este post, vamos usar o VSCode.

Para que seja possível gerar um relatório de cobertura, é preciso gerar antes de tudo um arquivo de cobertura. Para gerar esse arquivo no Flutter basta utilizar a flag --coverage ao comando de teste.

Para utilizar a flag é necessário gerar uma nova launch configuration no VSCode. Uma launch configuration é um arquivo em que se pode definir alguns detalhes de como a aplicação vai ser executada.

Com o projeto Flutter aberto no VSCode, é possível adicionar uma launch configuration ao ir na aba “Run and Debug”, clicando em “create a launch.json file” e por fim selecionando a opção “Dart & Flutter”.

Após essa ação, uma nova pasta será criada na raiz do projeto com o nome “.vscode” e dentro dela teremos um arquivo chamado “launch.json”.

O arquivo “launch.json” criado traz uma configuração simples que vai executar o main.dart do projeto. No entanto, para que a configuração rode os testes ao invés do programa, é preciso definir a propriedade “program” do JSON como sendo a pasta na qual os testes estão. No caso do exemplo a seguir a pasta se chama “test”.

Para validar essa configuração, clique na aba “Run and Debug” e, em seguida, no botão de play com o nome da configuração.

Com a configuração criada é possível, então, definir a flag --coverage utilizando a propriedade “args” para que o arquivo de cobertura seja gerado.

Ao executar a configuração com essa modificação, uma nova pasta chamada “coverage” será criada na raiz do projeto. Dentro da pasta gerada há um arquivo chamado “lcov.info” — formato de arquivo de cobertura open source.

Esse arquivo tem um formato que não exibe da melhor maneira possível a cobertura de cada arquivo. Por isso, para visualizar essas informações de uma melhor maneira no VSCode podemos utilizar um plugin.

O plugin Coverage Gutters é um dos mais utilizados — baseado na quantidade de downloads em relação aos outros que fazem essa função — e um dos mais úteis para visualizar a cobertura de formato lcov no VSCode.

Para instalar, basta acessar sua página Coverage Gutters e seguir com a instalação ou acessar a aba “plugins” do VSCode.

Com o plugin instalado, acione a opção “watch” na parte inferior.

Com essa opção selecionada, basta escolher um arquivo e visualizar por quais linhas seu teste passou ou não. Ao lado dos números das linhas teremos uma cor: vermelha, quando o teste não passou por ela, e verde, quando o teste passou por ela.

Observações
1. Para desabilitar o watch, basta clicar novamente na opção que mudou de nome para “Remove Watch”.
2. Com o watch ativo não é possível adicionar um “breakpoint” para a linha que foi colorida, sendo necessário desativar o watch para debugar. Existem formas de viabilizar isso, mas fogem do escopo deste post.
3. É possível também ativar e desativar o watch pelo “command pallet” do VSCode: digite “Coverage” e você terá acesso a uma lista de comandos do plugin e, entre elas, o watch.

Com o plugin já é possível ver a cobertura nas linhas de cada arquivo, mas não conseguimos ver a sua porcentagem e muito menos a do projeto como um todo. Para configurar um relatório de cobertura geral do projeto e dos arquivos outras etapas são necessárias.

A primeira delas é instalar o lcov no terminal, já que esse é o formato de relatório que o Flutter gera. Para isso, gere o seguinte comando:
$ brew install lcov

Com o lcov instalado é possível gerar um relatório utilizando a ferramenta “genhtml” presente nele. Essa ferramenta gera um relatório HTML com a cobertura geral do projeto, das pastas e até dos arquivos.

O comando para gerar o relatório é o seguinte:
$ genhtml <path/lcov.info> --output=<pathForReport>

No caso de um projeto Flutter com configurações padrões é possível utilizar o comando da seguinte forma:
$ genhtml coverage/lcov.info --output=./coverage

Ao rodar esse comando, criamos um relatório HTML dentro da pasta “coverage”. Para visualizar, abra o arquivo index.html em seu navegador.

Com os comandos e plugin configurados, já é possível gerar e visualizar o relatório de cobertura, mesmo que de maneira manual todas as vezes.

Unindo os comandos, o plugin e o arquivo de configuração do VSCode, é possível automatizar o processo de gerar o relatório e apresentá-lo pelo comando de teste do Flutter.

Para fazer essa automação é preciso alterar novamente o arquivo “launch.json”. Desta vez, será necessário adicionar um script de pós-execução. O script é feito por meio de tasks do VSCode.

Para criar as tasks é preciso criar um novo arquivo dentro da pasta “.vscode”, que podemos chamar de “tasks.json”. Utilize o seguinte snippet:

Neste JSON, podemos criar tasks que podem ser executadas antes ou após as configurações do “launch.json”.

A task é criada por meio de uma “label”, que vai ser utilizada para referenciar essa task no arquivo “launch.json”, por um “command”, que será o comando executado pela task, e por um “type”, que descreve qual o tipo de ambiente que será utilizado.

Observações
1. Existem outras propriedades que podem ser utilizadas, é legal dar uma lida na documentação.
2. O comando utilizado vai gerar o relatório e em seguida abri-lo com o comando “open”. Esse comando vai procurar o aplicativo padrão para abrir o arquivo com a extensão passada. Caso queira trocar, basta colocar o comando da aplicação que deseja.

Com o arquivo de “tasks” criado, é preciso modificar o arquivo de “launch.json” para que a configuração de testes rode a task criada ao finalizar. Para isso, utilizamos a propriedade “postDebugTask.

Um detalhe importante é que o valor passado na propriedade “postDebugTask” seja o mesmo valor passado para a propriedade “label” da task que foi referenciada.

Com isso, basta rodar a configuração de execução de testes. No fim, teremos um relatório de testes gerado e aberto em seu navegador padrão.

Como apresentado, é de suma importância para um time ter acesso a um relatório de cobertura do projeto, uma vez que esse arquivo serve como um ótimo insumo para entender como está a qualidade do produto como um todo.

Para o Flutter, embora não haja uma maneira completamente nativa de se gerar esse relatório, é possível utilizar a união de alguns conhecimentos e ferramentas para criar uma solução automatizada que gera o relatório e o apresenta da melhor maneira.

Ficou com dúvida ou tem algo a acrescentar? Aproveite os campos de comentários! E se você quiser fazer parte de um time que está sempre preocupado com as métricas e a qualidade de engenharia, dá uma olhada nesse link e vamos aprender juntos. Até a próxima!

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade…

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade e excelentes práticas, para que o mercado brasileiro e latino-americano acompanhe a velocidade do mercado digital mundial.

Matheus de Vasconcelos

Written by

iOS Developer — Apple Developer Academy Alumni | Mackenzie. Studying Unit Tests.

Concrete

Nós desenvolvemos produtos digitais com inovação, agilidade e excelentes práticas, para que o mercado brasileiro e latino-americano acompanhe a velocidade do mercado digital mundial.