🇧🇷
Ethereum Developer Pack - PT
  • Ethereum Developer Pack - PT
  • Módulo 1
    • Introdução a Smart Contracts
      • Fundamentos de Blockchain
        • Histórico
        • Bitcoin
        • O que é Blockchain
        • Conceitos-chave em Blockchain
        • Como funciona a Blockchain
        • Tipos de Blockchain
        • Modelos de Consenso
      • A nova Internet
        • Web 3
        • Elementos Fundamentais
        • Impacto do Ethereum em Diversos Setores
      • Wallets
        • Componentes de uma wallet
        • Tipos de Wallet
        • Códigos Mnemônicos
      • Ethereum 101
        • Smart Contracts
        • Contas
          • Tipos de contas
          • Conteúdo das contas
        • Transações
          • Componentes
          • Ciclo de vida
        • Gás
        • Solidity
        • EVM
          • A máquina de estados
          • Opcodes
          • Como funciona a EVM
          • Clientes de execução
          • DApps
      • Blockchain Explorer
        • Funções de um blockchain explorer
        • Beneficios de utilizar um blockchain explorer
      • Remix
        • Características do Remix
        • Workspaces ou espaços de trabalho
        • Carregar e compilar um contrato
        • Implantar na máquina virtual do Remix (Remix VM)
        • Interagindo com funções
        • Deployar em uma rede pública
      • Crie seu primeiro Smart Contract
  • Módulo 2
    • Fundamentos de Solidity
      • Hello World
      • Tipos de Dados
      • Funções
      • Variáveis
        • Exercício 1
      • Operadores
        • Ejercicio 2
      • Constructor
        • Exercício 3
      • Convenções de nomenclatura
      • Tipos de armazenamento para variáveis
      • Estruturas de Controle
        • Exercício 4
      • Modificadores
      • Eventos
        • Exercício 5
      • Tipos de Referencia
        • Arrays
          • Exercício 6
        • Mappings
          • Exercício 7
        • Structs
          • Exercício 8
      • Address Payable
      • Como os contratos e funções recebem Ether.
      • Transferências de Ether
      • Conceitos Avançados
        • Codificação de ABI
        • Hashing
        • This
        • Herança
        • Abstract
        • Interface
        • Chamada entre contratos
        • EVM
        • ABI
        • Bytecode
        • Opcodes
  • Módulo 3
    • ERCs, Bibliotecas e Padrões de Desenvolvimento
      • Boas Práticas de Desenvolvimento
      • Padrões de Desenvolvimento
      • EIP & ERC
      • ERC-20
      • ERC-721
      • Open Zeppelin
      • Crie um Token ERC-20
      • Almacenamiento Descentralizado: IPFS
      • Crea un Token ERC-721
      • DeFi
  • Módulo 4
    • Kit de ferramentas para desenvolvimento na Ethereum
      • Requisitos para o módulo 4
        • Terminal
        • Git e Github
        • Node.js e npm
        • Visual Studio Code para Solidity
      • Toolkit
        • JSON-RPC
        • Ethers.js
          • Exercício
        • Hardhat
          • Implantação de um contrato no Hardhat
          • Implantação de um contrato em uma rede pública
        • Scaffold-ETH
          • Características do Scaffold-ETHCaracterísticas
          • Como instalar o Scaffold-ETH
  • Módulo 5
    • Segurança, Testes e Auditorias
      • Testes
        • Importância de realizar testes
        • Métodos para testar contratos inteligentes
          • Testes automatizados
          • Testes manuais
        • Conceitos importantes em testes
        • Ferramentas para testes
        • Testes com Hardhat
        • Recursos adicionais
      • Segurança
        • Uma mentalidade diferente de design
        • Principais vulnerabilidades em contratos inteligentes
          • Reentrancy attack (ataque de reentrada)
          • Replay attack (ataque de repetición)
          • Price Oracle Manipulation (Manipulación de Oráculos de Precios)
          • Missing Access Control (Pérdida de Control de Acceso)
          • Reward Manipulation (Manipulación de Recompensas)
          • Failure to Initialize (Falla al Inicializar)
          • Front-running
          • Invariant Breaks (Quebra de Invariantes)
          • Mishandling of ETH (Má gestão de ETH)
          • Denial of Service (DoS - Negação de Serviço)
          • Integer overflow and underflow (Overflow e Underflow de inteiros)
          • Phishing y Typosquatting
        • Recursos adicionais
      • Auditoria de smart contracts
        • Processo de Auditoria
        • Ferramentas
        • Como se preparar para uma auditoria
        • O teste Rekt
        • Desafios
        • Recursos adicionais
  • Contribuye
    • Kipu Explorer
Powered by GitBook
On this page
  1. Módulo 5
  2. Segurança, Testes e Auditorias
  3. Testes
  4. Métodos para testar contratos inteligentes

Testes automatizados

Os testes automatizados utilizam ferramentas que verificam automaticamente o código de um contrato inteligente em busca de erros de execução. O benefício dos testes automatizados está no uso de scripts para orientar a avaliação das funcionalidades do contrato. Esses scripts podem ser programados para serem executados repetidamente com mínima intervenção humana, tornando os testes automatizados mais eficientes do que os testes manuais.

Os testes automatizados são particularmente úteis quando os testes são repetitivos e demorados, difíceis de realizar manualmente, suscetíveis a erros humanos ou envolvem a avaliação de funções críticas do contrato. No entanto, as ferramentas de teste automatizado podem apresentar desvantagens: podem deixar passar certos erros e gerar muitos falsos positivos. Por isso, combinar testes automatizados com testes manuais é o ideal para contratos inteligentes.

Tipos de Testes

  1. Testes unitários: Focam-se principalmente em funções e componentes individuais. Cada função opera com base em determinadas suposições sobre os parâmetros que recebe e o estado do sistema com o qual interage. Por isso, os testes unitários devem abranger todos os cenários possíveis — tanto válidos (o que o contrato deve fazer) quanto inválidos (o que o contrato não deve fazer) — nos quais uma função pode ser chamada, a fim de identificar erros de lógica.

    • Tenha clareza sobre quais são as funções do contrato e como os usuários irão acessá-las e utilizá-las.

    • Avalie todas as suposições relacionadas à execução do contrato. O que o contrato pode e o que não pode fazer?

    • Meça a cobertura do código. Quanto maior, melhor.

    • Utilize ferramentas de teste robustas e bem consolidadas no mercado.

  2. Testes de integração: Constituem a camada seguinte de testes, sendo construídos sobre os testes unitários. Após confirmar a funcionalidade dos componentes individuais, verifica-se sua integração. Este nível foca nas interações entre os componentes, sejam eles internos ou externos. Por exemplo, avalia se um sistema se comporta corretamente ao chamar um serviço de terceiros. Os testes de integração são essenciais, pois essas relações não são verificadas nos testes unitários.

    Os testes de integração são especialmente úteis quando o contrato adota uma arquitetura modular ou interage com outros contratos on-chain durante a execução. Uma forma comum de realizar testes de integração é fazer um fork da mainnet em uma altura específica utilizando ferramentas como Hardhat e Foundry, e simular interações entre os nossos contratos e os contratos já implantados.

    O fork se comporta de forma semelhante à mainnet e possui contas com estados e saldos associados. No entanto, atua apenas como um ambiente de desenvolvimento local isolado, o que significa que não será necessário utilizar ETH real para as transações e que quaisquer alterações realizadas não afetarão o ambiente real da rede Ethereum.

  3. Testes baseados em propriedades: Os testes baseados em propriedades são o processo de verificar se um contrato inteligente cumpre com alguma propriedade definida. As propriedades afirmam fatos sobre o comportamento de um contrato que se espera que se mantenham verdadeiros em diferentes cenários. Um exemplo de uma propriedade de um contrato inteligente poderia ser: "As operações aritméticas no contrato nunca causarão overflow ou underflow."

    A análise estática e a análise dinâmica são duas técnicas comuns para executar testes baseados em propriedades, e ambas podem verificar se o código de um contrato cumpre com alguma propriedade predefinida. Algumas ferramentas de testes baseados em propriedades vêm com regras predefinidas sobre as propriedades esperadas do contrato e verificam o código em relação a essas regras, enquanto outras permitem criar propriedades personalizadas para um contrato inteligente.

    1. Análise estática

      Um analisador estático recebe como entrada o código-fonte de um contrato inteligente e gera resultados declarando se o contrato satisfaz ou não uma propriedade. Ao contrário da análise dinâmica, a análise estática não envolve a execução de um contrato para analisá-lo quanto à sua correção. Em vez disso, a análise estática razoa sobre todos os possíveis caminhos que um contrato inteligente pode seguir durante a execução (ou seja, examina a estrutura do código-fonte para determinar o que isso significaria para a operação do contrato em tempo de execução). O linting (verificação automatizada do código em busca de erros programáticos e estilísticos) e os testes estáticos são métodos comuns para realizar análise estática em contratos. Ambos exigem analisar representações de baixo nível da execução de um contrato, como árvores de sintaxe abstrata e gráficos de fluxos de controle produzidos pelo compilador.

      Na maioria dos casos, a análise estática é útil para detectar problemas de segurança, como o uso de construções inseguras, erros de sintaxe ou violações de padrões de codificação no código de um contrato. No entanto, é sabido que os analisadores estáticos geralmente são pouco confiáveis para detectar vulnerabilidades mais profundas e podem gerar muitos falsos positivos.

    2. Análise dinâmica

      A análise dinâmica gera entradas simbólicas ou entradas concretas para as funções de um contrato inteligente para verificar se algum caminho de execução viola propriedades específicas. Essa forma de testes baseados em propriedades difere dos testes unitários, pois os casos de teste cobrem múltiplos cenários, e um programa gerencia a criação dos casos de teste.

      O fuzzing é um método automatizado que injeta entradas inválidas ou inesperadas em um sistema, revelando vulnerabilidades de segurança. Utiliza ferramentas especializadas que variam conforme a tecnologia. Um fuzzer invoca funções em um contrato alvo com variações aleatórias ou incorretas de um valor de entrada definido. Se o contrato inteligente entra em um estado de erro (por exemplo, onde uma asserção falha), o problema é sinalizado, e as entradas que levam ao erro são registradas em um relatório.

      Essa forma de testes baseados em propriedades pode ser ideal por várias razões:

      • É difícil escrever casos de teste para cobrir muitos cenários. Um teste de propriedade requer apenas que você defina um comportamento e um intervalo de dados para testar o comportamento; o programa gera automaticamente casos de teste com base na propriedade definida.

      • Seu conjunto de testes pode não cobrir suficientemente todos os possíveis caminhos dentro do programa. Mesmo com uma cobertura de 100%, é possível deixar de cobrir casos extremos.

      • Os testes unitários demonstram que um contrato executa corretamente para dados de uma amostra, mas se o contrato executará corretamente para entradas fora dessa amostra ainda é desconhecido. Os testes de propriedades executam um contrato alvo com múltiplas variações de um valor de entrada dado para encontrar caminhos de execução que causam falhas nas asserções. Portanto, um teste de propriedade fornece mais garantias de que um contrato será executado corretamente para uma ampla classe de dados de entrada.

PreviousMétodos para testar contratos inteligentesNextTestes manuais

Last updated 22 days ago