Uso de Brownie para testing en Python
En el ecosistema de desarrollo de smart contracts sobre Ethereum, la calidad y fiabilidad de nuestro código es esencial. Brownie emerge como una de las herramientas más potentes para el testing de contratos escritos en Solidity y Vyper, aprovechando el familiar entorno de Python y la robustez de pytest. En este artículo exploraremos su instalación, configuración, flujo de trabajo, características avanzadas y buenas prácticas para integrar Brownie en proyectos profesionales.
Índice de contenido
- ¿Qué es Brownie
- Requisitos e instalación
- Estructura de un proyecto Brownie
- Escribir y ejecutar tests
- Fixtures y parametrización
- Integración con redes locales y forking
- Medición de cobertura y reportes
- Plugins útiles
- Integración en CI/CD
- Buenas prácticas y recomendaciones
- Recursos y enlaces de interés
1. ¿Qué es Brownie
Brownie es un framework de desarrollo y testing para contratos inteligentes, creado por Luigi De Rosa. Ofrece:
- Integración nativa con pytest.
- Consola interactiva para debugging.
- Soporte para múltiples compiladores (Solidity, Vyper).
- Simulación de nodos locales con ganache-cli.
- Facilidad para deployments y scripts de migración.
2. Requisitos e instalación
Antes de comenzar, necesitamos un entorno de Python 3.7 y Node.js (para Ganache). A continuación, ejecutamos:
pip install eth-brownie
npm install -g ganache-cli
Verificamos la instalación:
brownie --version
ganache-cli --version
3. Estructura de un proyecto Brownie
Al crear un proyecto mediante brownie init, obtenemos:
| Carpeta/Archivo | Descripción |
|---|---|
| contracts/ | Código fuente Solidity/Vyper. |
| scripts/ | Scripts de despliegue y utilidades. |
| tests/ | Tests escritos en Python con pytest. |
| build/ | Artefactos compilados (.json). |
| brownie-config.yaml | Configuración global del proyecto. |
4. Escribir y ejecutar tests
Cada test es una función normal de pytest, usando accounts, contract y fixtures propias de Brownie:
from brownie import accounts, MyContract, reverts
def test_deploy_and_basic_behavior():
# Despliegue usando la cuenta 0
deployer = accounts[0]
# Despliega el contrato
instancia = MyContract.deploy({from: deployer})
# Verifica el valor por defecto
assert instancia.value() == 0
# Interacción y evento
tx = instancia.setValue(42, {from: deployer})
assert ValueChanged in tx.events
assert instancia.value() == 42
def test_error_when_unauthorized(accounts, MyContract):
owner = accounts[0]
attacker = accounts[1]
contrato = MyContract.deploy({from: owner})
# Esperamos revert
with reverts(Ownable: caller is not the owner):
contrato.changeOwner(attacker, {from: attacker})
Para ejecutar todos los tests:
brownie test
5. Fixtures y parametrización
Brownie expone fixtures como accounts, project, web3, entre otras. Podemos parametrizar tests con pytest:
import pytest
@pytest.mark.parametrize(initial,delta,expected, [
(0, 5, 5),
(10, -3, 7),
(100, 0, 100),
])
def test_multiple_values(initial, delta, expected, accounts, MyContract):
c = MyContract.deploy({from: accounts[0], args: [initial]})
c.adjust(delta, {from: accounts[0]})
assert c.value() == expected
6. Integración con redes locales y forking
Para simular redes realistas o testnets, Brownie permite configurar networks en brownie-config.yaml:
networks:
default: development
development:
cmd_settings:
gas_price: auto
mainnet-fork:
cmd_settings:
fork: https://mainnet.infura.io/v3/YOUR_INFURA_KEY
Y ejecutamos:
brownie console --network mainnet-fork
7. Medición de cobertura y reportes
Brownie cuenta con un plugin de cobertura, basta instalar pytest-cov y luego:
pip install pytest-cov
brownie test --coverage
Obtendremos un reporte detallado del porcentaje de líneas de Solidity cubiertas por los tests, lo cual es crucial para auditorías.
8. Plugins útiles
- brownie-cov: cobertura de tests.
- eth-gas-reporter: métricas de consumo de gas.
- brownie-upgrades: contratos proxy y migraciones.
- pytest-random: orden aleatorio de tests para detectar dependencias ocultas.
9. Integración en CI/CD
Para automatizar tests en GitHub Actions, un workflow básico:
name: Brownie CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install dependencies
run:
pip install eth-brownie pytest-cov
npm install -g ganache-cli
- name: Start Ganache
run: ganache-cli -p 8545 sleep 5
- name: Run tests
run: brownie test --network development --coverage
10. Buenas prácticas y recomendaciones
- Escribir tests aislados, sin dependencias de orden.
- Parametrizar escenarios límite (overflow, underflow).
- Simular múltiples cuentas y roles (owner, user, attacker).
- Verificar eventos y estados posteriores a cada transacción.
- Usar coverage y gas-reporter antes de cada release.
- Integrar linting de Solidity (solhint/solium) y formateo (prettier-plugin-solidity).
11. Recursos y enlaces de interés
- Brownie Documentation
- Solidity Official Docs
- GitHub – eth-brownie/brownie
- pytest – The Python Testing Framework
- Ganache – Truffle Suite
Con estos conocimientos y herramientas, podrás elevar la calidad de tus smart contracts, detectar errores con antelación y garantizar seguridad y fiabilidad en tus despliegues sobre Ethereum y redes compatibles. ¡Feliz testing con Brownie!
Deja una respuesta