19 de fevereiro de 2023
Se você ainda não ouviu falar ou não usou o Foundry ainda, eu recomendo fortemente que você dê uma olhada! Os documentos deles são bem detalhados e úteis para começar.
Este pequeno guia abordará o comando forge coverage
e algumas coisas que você pode fazer para adequá-lo melhor às suas necessidades específicas.
Uma descrição simples de forge coverage
retirada de um colaborador do núcleo da Foundry, que também é o desenvolvedor responsável por adicionar o comando é:
O relatório de cobertura informa quais partes do seu código seus testes cobrem! É essencialmente apenas uma ferramenta para dizer se você escreveu testes “o suficiente”.
Há uma ressalva no sentido de que, mesmo que você tenha 100% de cobertura, seu conjunto de testes ainda pode não ser suficiente.
Para ler mais alguns insights adicionais oferecidos por Oliver, você pode conferir o tópico do Twitter de onde tirei essa citação.
Ok, agora que você já sabe o que o forge coverage
faz, vamos brincar com isso.
Nosso amigo Oliver criou um repositório no Github onde você pode vê-lo em ação em uma série de testes e contratos. No entanto, para simplificar e esperançosamente permitir que você tenha um melhor entendimento, criei meu próprio repositório simples para ensiná-lo. Vamos começar clonando dentro dele:
git clone https://github.com/RohanNero/learn-foundry-coverage
Uma vez dentro do repositório, podemos executar o forge install
para obter quaisquer dependências necessárias e, é claro, forge build
para compilar todos os contratos. Agora estamos prontos para ver o forge coverage
em ação!
Quando você executar o forge coverage
pela primeira vez, você deve receber retorno de algo como a figura acima. Esta pequena tabela de terminal mostra a você qual a porcentagem de linhas, declarações, ramificações e funções que você cobriu por arquivo, bem como seus percentuais totais para todos os arquivos cobertos. Atualmente, podemos ver que apenas um dos arquivos é um contrato real e o outro é o nosso script. No momento em que escrevo este guia, parece não existir uma maneira de retornar apenas contratos específicos dentro do terminal. Felizmente, é aí que as opções forge coverage
entram em jogo.
Para ver algumas opções diferentes, você pode passar para o comando, executar forge coverage --help
(ou forge coverage -h
). Você poderá ver isto no seu terminal depois de executá-lo (talvez seja necessário rolar a tela um pouco para cima).
Podemos ver que a opção --report
está padronizada para summary
, o que significa que, quando executamos forge coverage --report summary
, obtemos como retorno exatamente a mesma saída que executando forge coverage
sem opções. Também vemos um lcov
e uma opção debug
. Antes de entrar no lcov
, vamos fazer uma tentativa com forge coverage --report debug
.
Você obtém como retorno uma longa lista de “âncoras” e linhas informando exatamente onde estão as linhas descobertas dentro de seus contratos. Este é um avanço em relação a um relatório de cobertura resumido normal, porque agora sabemos para quais linhas e funções ainda precisamos fornecer testes.
Agora, para a opção forge coverage
final: lcov
. Se você não ouviu falar de lcov
antes, é usado “para coletar dados de cobertura e genhtml para criar páginas HTML”. Você pode ler mais sobre isso aqui. Basicamente, vamos usar lcov e genhtml para converter nossos dados de cobertura em algo mais legível por humanos. Então vá em frente e execute forge coverage --report lcov
.
Você deve ver algo assim dentro do seu arquivo ”lcov.info” recém criado. Agora, para criar o arquivo HTML que podemos ler facilmente, execute o comando: genhtml -o report --branch-coverage
. Isso criará um arquivo HTML para você com o diretório de saída definido no ‘relatório’. Como passamos a opção --branch-coverage
, também obteremos dados de cobertura de ramificação dentro de nosso arquivo HTML. Para obter uma lista completa de opções genhtml
, consulte este link.
Agora, se você entrar na pasta report
, clicar no arquivo index.html e, em seguida, clicar no botão “visualizar” (preview) (canto superior direito por padrão para VS Code), você poderá ver uma tabela como abaixo:
Agora você conhece três maneiras diferentes de visualizar seu código coberto com coverage
! Parabéns por aprender a usar esse superpoder do Foundry, mas ainda não terminamos! Graças à extensão do VS Code “Coverage Gutters”, podemos ver as linhas cobertas e descobertas destacadas diretamente dentro de nossos arquivos de contratos inteligentes!
Tudo que você precisa fazer para usá-lo é instalá-lo pesquisando seu nome na guia de extensões do VS Code. Em seguida, execute forge coverage
com a opção --report lcov
e habilite ou o “Display Coverage” (mostrar cobertura) através da paleta de comando (ctrl+shift+p) ou use o atalho do painel : ctrl+shift+7. Agora você pode ver o contrato inteligente Counter.sol
com destaques verdes representando as linhas cobertas e destaques vermelhos para as descobertas:
A partir disso, podemos ver facilmente que a função decrement()
é a única deixada descoberta. Isso corresponde com o dado que podemos ver de um forge coverage --report summary
regular.
Agora, vamos retirar o comentário da função testDecrement_Vulnerable()
dentro do nosso arquivo de teste Counter.t.sol
e executar forge coverage
novamente.
Agora vemos que nosso arquivo Counter.sol
está completamente coberto! Podemos re-executar forge coverage --report lcov
para atualizar nosso arquivo lcov.info
e, em seguida, dentro do nosso Counter.sol
, o comando “Coverage Gutters: Display Coverage” (cobertura Gutters: mostrar cobertura) mostrará os resultados atualizados da cobertura:
Agora que temos 100% de cobertura, nosso contrato é inexplorável! Certo?
Não exatamente…
Espere, o que você quer dizer é que o comando
forge coverage
apenas permite que você veja linhas não testadas, não erros de lógica ou bugs?!
Ter 100% de cobertura de forma alguma garante que seu contrato esteja livre de explorações, apenas que cada linha/função/ramificação seja invocada pelo menos dentro do seu teste de contrato.
Por exemplo, dê uma olhada na nossa função decrement()
.
Ela contém um erro de lógica simples que a torna vulnerável à underflow. Ao invés de verificar que number >= 0
, deveríamos verificar para ter certeza que number > 0
.
Para demonstrar isso, você pode executar forge test
para ver que tudo passa.
Em seguida, comente a função testDecrement_Vulnerable()
e descomente a função testDecrement_OnSteroids()
abaixo dela.
Executar forge test
agora retornará algo assim como alternativa:
Agora, vemos que nosso contrato claramente tem um bug e nosso teste ainda falha! No entanto, o que acontece quando executamos forge coverage
?
Independente do contrato ser falho, ainda temos 100% de cobertura.
Portanto, para concluir, forge coverage
, como a maioria das ferramentas de desenvolvimento de contratos inteligentes em constante evolução, ainda é um trabalho em andamento e espero que seja aprimorada e afinada ao longo dos próximos meses/anos. Portanto, por enquanto, use-a da melhor forma que puder, lembre-se de que, só porque você tem 100% de cobertura, não significa que seu código esteja livre de erros e seja grato por termos forge coverage
de qualquer modo! (tweet do Oliver que achei engraçado).
Sempre que puder, certifique-se de agradecer os desenvolvedores e construtores maravilhosos que nos permitiram usar ferramentas incríveis e geniais como forge coverage
!
Agradecimentos especiais a Oliver e ao resto dos colaboradores do núcleo Foundry!
Você pode encontrar o GitHub e Twitter do Oliver assim como os links que eu usei para escrever este guia abaixo.
Do Oliver:
- GitHub: https://github.com/onbjerg
- Twitter: https://twitter.com/onbjerg
Fontes que usei e acho úteis:
- https://mirror.xyz/devanon.eth/RrDvKPnlD-pmpuW7hQeR5wWdVjklrpOgPCOA-PJkWFU
- https://www.rareskills.io/post/foundry-forge-coverage
- https://book.getfoundry.sh/
- https://twitter.com/gakonst/status/1541961559856975872
- https://twitter.com/fiveoutofnine/status/1622639955720675330
- https://twitter.com/0xasp_/status/1624456443327029248
- https://manpages.ubuntu.com/manpages/xenial/man1/genhtml.1.html
- https://github.com/foundry-rs/foundry/issues/2988
- https://github.com/foundry-rs/foundry/issues/3000
- https://github.com/foundry-rs/foundry/pull/1576
- https://github.com/foundry-rs/foundry/issues/99#issuecomment-1089486836
- https://github.com/foundry-rs/foundry/issues/387
- https://github.com/RohanNero/learn-foundry-coverage
Esse artigo foi escrito por Rohanzarathustra e traduzido por Isabela Curado Nehme. Seu original pode ser lido aqui.
Top comments (0)