Testes com Hardhat
A seguir, é apresentado um exemplo completo de como escrever e executar testes unitários para um contrato inteligente na Ethereum utilizando o Hardhat. Este exemplo incluirá a criação do contrato inteligente, a configuração dos fixtures e a escrita de diversos testes.
Paso 1: Configuração do Projeto
Devemos ter o Hardhat instalado e um projeto básico criado (caso não saibas como fazer isso, consulte o módulo 4).
Certifique-se de ter o plugin
hardhat-toolboxinstalado.npm install --save-dev @nomicfoundation/hardhat-toolboxAlém disso, é necessário adicionar a seguinte linha no inÃcio do arquivo
hardhat.config.jsrequire("@nomicfoundation/hardhat-toolbox");
Paso 2: Definir o contrato a ser testado
Utilizaremos o contrato Token.sol, que será colocado na pasta contracts com o seguinte conteúdo:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Token {
string public name = "KIPU";
string public symbol = "KIP";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
event Transfer(address indexed from, address indexed to, uint256 value);
constructor(uint256 _initialSupply) {
totalSupply = _initialSupply * (10 ** uint256(decimals));
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(_to != address(0), "Invalid address");
require(balanceOf[msg.sender] >= _value, "Insufficient balance");
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
}Paso 3: Escrever os testes
Crie um arquivo de testes chamado TokenTest.js dentro da pasta test com o seguinte conteúdo:
Explicação do script acima
Importações e configurações necessárias:
chai: Biblioteca de asserções que facilita a verificação dos resultados esperados nos testes.
ethers: Biblioteca para interação com contratos inteligentes e a blockchain.
loadFixture: Função que carrega um estado inicial fixo (fixture) para os testes, garantindo que todos comecem com as mesmas condições.
Depois definimos o fixture
deployTokenFixture: Esta função implanta o contrato
Tokencom um fornecimento inicial. Também obtém três contas para serem utilizadas nos testes (owner, addr1, addr2).
Primeiro teste: Verificar o proprietário
Propósito: Verificar se o proprietário inicial (a conta que implanta o contrato) recebe o fornecimento total de tokens.
Proceso:
Implantar o contrato utilizando o fixture.
Obter o saldo do proprietário.
Verificar se o saldo é igual ao fornecimento inicial (1000 tokens convertidos para a unidade mÃnima).
Segundo teste: Verificar o fornecimento total
Propósito: Garantir que o fornecimento total de tokens seja atribuÃdo corretamente ao proprietário.
Processo:
Implantar o contrato utilizando o fixture.
Obter o saldo do proprietário.
Verificar se o saldo do proprietário é igual ao fornecimento total de tokens
Terceiro teste: Transferência de tokens
Propósito: Verificar se os tokens são transferidos corretamente entre contas.
Processo:
Implantar o contrato utilizando o fixture.
Transferir 50 tokens do
ownerparaaddr1.Verificar que
addr1enha recebido 50 tokens.Transferir 50 tokens de
addr1paraaddr2.Verificar que
addr2tenha recebido 50 tokens e queaddr1tenha um saldo de 0 tokens.
Quarto teste: Verificar que uma conta não pode transferir se não tiver saldo suficiente
Propósito: Garantir que a transferência falhe se o remetente não tiver tokens suficientes.
Proceso:
Implantar o contrato utilizando fixture.
Tentar transferir 1 token de
addr1(que não possui tokens) para oowner.Verificar que a transação seja revertida com a mensagem "Insufficient balance".
Verificar que o saldo do
ownernão tenha sido alterado.
Quinto teste: Atualização dos saldos após uma transferência
Propósito: Verificar se os saldos são atualizados corretamente após as transferências.
Proceso:
Implantar o contrato utilizando o fixture.
Transferir 100 tokens do
ownerparaaddr1.Transferir 50 tokens do
ownerparaaddr2.Verificar se o saldo final do
owneré igual ao saldo inicial menos 150 tokens.Verificar se
addr1possui 100 tokens eaddr2possui 50 tokens.
Passo 4: Executar os testes
Para executar os testes, utilize o seguinte comando no terminal:
Este comando executará todos os testes definidos no arquivo TokenTest.js e exibirá os resultados no console.
Se os testes forem bem-sucedidos, você verá um resultado semelhante a este:

Parabéns!! Você executou com sucesso seus primeiros testes. Agora é hora de começar a testar outros contratos que você tenha criado.
O Hardhat também permite verificar a cobertura dos seus testes. Para isso, basta executar o seguinte comando:
E você obterá um relatório semelhante a este

Mais uma coisa: Chai
Neste exemplo, utilizamos Chai para realizar nossos testes. Chai é uma biblioteca de assertions (afirmações) para Node.js que pode ser combinada com qualquer framework de testes, como o Hardhat. No contexto de testes para contratos inteligentes, o Chai é amplamente utilizado devido à sua sintaxe amigável e capacidades robustas de asserção.
Para utilizar o Chai, primeiro é necessário importar a biblioteca e, em seguida, usar seus métodos nas suas asserções dentro dos testes. Aqui está um exemplo básico de configuração:
Chai oferece três estilos principais de asserção:
Assert: Estilo clássico baseado em funções.
Expect: Estilo BDD (Behavior-Driven Development), mais legÃvel.
Should: Outro estilo BDD, que adiciona propriedades ao
Object.prototype.
No nosso exemplo, utilizamos o estilo expect, pois é um dos mais usados em testes de contratos inteligentes com Hardhat, graças à sua clareza e sintaxe intuitiva.
Principais comandos do Chai
Igualdade (
equal,eql)
equalverifica igualdade estrita (===).eqlverifica igualdade profunda (ideal para objetos e arrays).
Booleanos (
true,false)
Verifica se um valor é verdadeiro ou falso.
Existência (
exist)
Verifica se um valor não é null nem undefined.
Tipos (
a,an)
Verifica o tipo de um valor.
Conteúdo (
include,contain)
Verifica se um valor contém outro (em arrays, strings ou objetos).
Comprimento (
lengthOf)
Verifica o comprimento de um array, string ou Map.
Maior e menor que (
above,below)
Verifica se um valor é maior ou menor que outro.
Aproximação (
closeTo)
Verifica se um número está próximo de outro, dentro de uma margem de erro.
Emissão de eventos (
emit,withArgs)
No contexto de testes de contratos inteligentes, verificamos se um evento é emitido com os argumentos corretos.
Para mais informações sobre Chai, consulte a documentação do Hardhat.
Last updated