
Los t茅rminos del contrato inteligente no se pueden cambiar. Por lo tanto, cada vez que cree un contrato inteligente, debe asegurarse de que funcione correctamente. La prueba es una forma segura de probar un contrato en diferentes situaciones. En este tutorial, aprender谩 qu茅 pasos tomar.
Te dir茅:
- C贸mo preparar un entorno de prueba.
- C贸mo escribir pruebas de JavaScript y ejecutarlas en Truffle .
El tutorial est谩 dirigido a principiantes que acaban de comenzar a profundizar en el desarrollo y las pruebas de contratos inteligentes en Ethereum. Para comprender este tutorial, debe tener al menos un conocimiento b谩sico de
JavaScript y
Solidity .
1. C贸mo preparar un entorno de prueba
Hay muchas formas de probar contratos inteligentes, pero
Truffle es la herramienta de escritura de prueba m谩s popular que usa
JavaScript . En
Truffle, puede escribir pruebas unitarias o realizar pruebas de integraci贸n completas con par谩metros reales del entorno de producci贸n.
Primero debe instalar la 煤ltima versi贸n de Node.js desde el
sitio oficial .
Luego abra una terminal e instale
Truffle usando el siguiente comando:
npm install -g truffle
Despu茅s de instalar
Truffle , sin cerrar la terminal, cree el directorio de
Financiaci贸n :
mkdir Funding
A continuaci贸n, vaya al directorio con el comando:
cd Funding
Para inicializar el directorio, ejecute el comando:
truffle init
Despu茅s de ejecutar el comando, se crear谩n las siguientes carpetas y archivos en el directorio de
Financiaci贸n :

Adem谩s trabajaremos con cada directorio. Mientras tanto, continuamos preparando el entorno de prueba.
Para ejecutar las pruebas, necesita bibliotecas Javascript.
Mocha es una biblioteca que contiene funciones comunes para la prueba, incluida la
descripci贸n y.
Chai es una biblioteca que admite una variedad de funciones para cheques. Existen diferentes "estilos" para verificar los resultados, y Chai nos brinda esta oportunidad. En el tutorial usaremos
deber铆a .
Por defecto, Mocha es parte de Truffle, podemos usar f谩cilmente las funciones de la biblioteca. Chai debe instalarse manualmente. Para hacer esto, use la terminal y en el directorio ra铆z del proyecto, ejecute el comando:
npm install chai
Tambi茅n instal茅 la
biblioteca chai-bignumber para comparar n煤meros con precisi贸n arbitraria:
npm install --save-dev chai-bignumber
El entorno de prueba est谩 listo para esto. Ahora puede comenzar a desarrollar un contrato inteligente y probarlo.
2. C贸mo escribir pruebas de JavaScript y ejecutarlas en Truffle
Para desarrollar pruebas, necesita un contrato inteligente. Desarrollaremos un contrato que le permita recolectar donaciones, establecer una cantidad espec铆fica para lograr la recolecci贸n y retirar fondos. Si alguien dona m谩s, se le devolver谩 la diferencia entre la cantidad que se ha acumulado y la cantidad que se debe cobrar.
Vaya al directorio
Financiaci贸n -> contratos . En
Financiaci贸n / contratos, cree el archivo
Funding.sol con la extensi贸n
.sol ; este ser谩 el contrato inteligente para las pruebas.
En
Funding.sol, agregue el siguiente c贸digo:
pragma solidity 0.4.24; contract Funding { uint public raised; uint public goal; address public owner; event Donated(uint donation); event Withdrew(uint amount); modifier onlyOwner() { require(owner == msg.sender); _; } modifier isFinished() { require(isFunded()); _; } modifier notFinished() { require(!isFunded()); _; } constructor (uint _goal) public { owner = msg.sender; goal = _goal; } function isFunded() public view returns (bool) { return raised >= goal; } function donate() public payable notFinished { uint refund; raised += msg.value; if (raised > goal) { refund = raised - goal; raised -= refund; msg.sender.transfer(refund); } emit Donated(msg.value); } function withdraw() public onlyOwner isFinished { uint amount = address(this).balance; owner.transfer(amount); emit Withdrew(amount); } }
El contrato esta listo. Implementaremos un contrato inteligente a trav茅s de la migraci贸n.
Las migraciones son archivos
JavaScript que lo ayudan a implementar contratos en la red Ethereum. Esta es la principal forma de implementar contratos.
Vaya al directorio
Financiaci贸n -> migraciones y cree el archivo
2_funding.js , agregando el siguiente c贸digo:
const Funding = artifacts.require("./Funding.sol"); const ETHERS = 10**18; const GOAL = 20 * ETHERS; module.exports = function(deployer) { deployer.deploy(Funding, GOAL); };
Para ejecutar las pruebas, debe usar el comando de
prueba de trufa . En la terminal, vaya a la ra铆z del directorio de
Financiaci贸n , que se cre贸 durante la preparaci贸n del entorno de prueba e ingrese:
truffle test
Si la siguiente salida aparece en la terminal, entonces todo se hace correctamente:

Ahora comencemos a escribir pruebas.
Verificaci贸n del propietario
Vaya al directorio
Financiaci贸n -> prueba y cree un archivo
test_funding.js con la extensi贸n
.js . Este es el archivo en el que se escribir谩n las pruebas.
Agregue el siguiente c贸digo al archivo
test_funding.js :
const Funding = artifacts.require("Funding"); require("chai").use(require("chai-bignumber")(web3.BigNumber)).should(); contract("Funding", function([account, firstDonator, secondDonator]) { const ETHERS = 10**18; const GAS_PRICE = 10**6; let fundingContract = null; it("should check the owner is valid", async () => { fundingContract = await Funding.deployed(); const owner = await fundingContract.owner.call() owner.should.be.bignumber.equal(account); });
En la prueba, verificamos que el contrato de
Financiaci贸n almacena la direcci贸n del propietario que implement贸 el contrato. En nuestro caso, la
cuenta es el primer elemento de la matriz.
Truffle le permite usar hasta diez direcciones, en las pruebas solo necesitamos tres direcciones.
Aceptaci贸n de donaciones y verificaci贸n del fin de la recaudaci贸n de fondos.
En esta secci贸n revisaremos:
- Aceptaci贸n y cantidad de donaciones.
- 驴Se ha alcanzado una cierta cantidad de donaci贸n?
- 驴Qu茅 sucede si dona m谩s de lo que necesita recolectar?
- El monto total de la donaci贸n.
- 驴Puedo continuar recaudando fondos si se ha recaudado la cantidad requerida?
Escribiremos y analizaremos las pruebas:
. . . . . . . . . . . . . . . . . . . . . . const ETHERS = 10**18; const GAS_PRICE = 10**6; let fundingContract = null; let txEvent; function findEvent(logs, eventName) { let result = null; for (let log of logs) { if (log.event === eventName) { result = log; break; } } return result; }; it("should accept donations from the donator #1", async () => { const bFirstDonator= web3.eth.getBalance(firstDonator); const donate = await fundingContract.donate({ from: firstDonator, value: 5 * ETHERS, gasPrice: GAS_PRICE }); txEvent = findEvent(donate.logs, "Donated"); txEvent.args.donation.should.be.bignumber.equal(5 * ETHERS); const difference = bFirstDonator.sub(web3.eth.getBalance(firstDonator)).sub(new web3.BigNumber(donate.receipt.gasUsed * GAS_PRICE)); difference.should.be.bignumber.equal(5 * ETHERS); });
Antes de analizar la prueba, quiero se帽alar 2 puntos:
- Para buscar eventos (eventos) y verificar sus argumentos, se escribi贸 una peque帽a funci贸n findEvent .
- Para la conveniencia de las pruebas y los c谩lculos, se estableci贸 el valor intr铆nseco para el gas (constante GAS_PRICE).
Ahora analicemos la prueba. En la prueba, verificamos:
- que podemos aceptar donaciones llamando al m茅todo donate () ;
- que la cantidad donada a nosotros est谩 indicada correctamente;
- que quien don贸 fondos, el saldo disminuy贸 en la cantidad donada.
it("should check if donation is not completed", async () => { const isFunded = await fundingContract.isFunded(); isFunded.should.be.equal(false); });
En esta prueba, verificamos que la recaudaci贸n de fondos a煤n no se ha completado.
it("should not allow to withdraw the fund until the required amount has been collected", async () => { let isCaught = false; try { await fundingContract.withdraw({ gasPrice: GAS_PRICE }); } catch (err) { isCaught = true; } isCaught.should.be.equal(true); });
En la prueba, verificamos que no podemos retirar fondos hasta que se obtenga la cantidad que necesitamos.
it("should accept donations from the donator #2", async () => { const bSecondDonator= web3.eth.getBalance(secondDonator); const donate = await fundingContract.donate({ from: secondDonator, value: 20 * ETHERS, gasPrice: GAS_PRICE }); txEvent = findEvent(donate.logs, "Donated"); txEvent.args.donation.should.be.bignumber.equal(20 * ETHERS); const difference = bSecondDonator.sub(web3.eth.getBalance(secondDonator)).sub(new web3.BigNumber(donate.receipt.gasUsed * GAS_PRICE)); difference.should.be.bignumber.equal(15 * ETHERS); });
En la prueba, verificamos que si dona una gran cantidad, el m茅todo
donate () calcula y devuelve los fondos a la persona que don贸 m谩s de lo necesario. Este monto es la diferencia entre el monto acumulado y el monto que desea cobrar.
it("should check if the donation is completed", async () => { const notFunded = await fundingContract.isFunded(); notFunded.should.be.equal(true); }); it("should check if donated amount of money is correct", async () => { const raised = await fundingContract.raised.call(); raised.should.be.bignumber.equal(20 * ETHERS); }); it("should not accept donations if the fundraising is completed", async () => { let isCaught = false; try { await fundingContract.donate({ from: firstDonator, value: 10 * ETHERS }); } catch (err) { isCaught = true; } isCaught.should.be.equal(true); });
En estas tres pruebas, verificamos:
- que la recaudaci贸n de fondos se ha completado;
- que el monto de la donaci贸n es correcto;
- que nadie m谩s puede donar, ya que la recaudaci贸n de fondos se ha completado.
Retirar fondos
En la secci贸n anterior del tutorial, recopilamos la cantidad que necesitamos, ahora se puede mostrar:
. . . . . . . . . . . . . . . . . . . . . . it("should allow the owner to withdraw the fund", async () => { const bAccount = web3.eth.getBalance(account); const withdraw = await fundingContract.withdraw({ gasPrice: GAS_PRICE }); txEvent = findEvent(withdraw.logs, "Withdrew"); txEvent.args.amount.should.be.bignumber.equal(20 * ETHERS); const difference = web3.eth.getBalance(account).sub(bAccount); difference.should.be.bignumber.equal(await fundingContract.raised.call() - withdraw.receipt.gasUsed * GAS_PRICE); });
Al llamar a la funci贸n
retirada () , retiramos los fondos del propietario del contrato inteligente, en nuestra
cuenta de caso. Luego verificamos que realmente hab铆amos retirado la cantidad que necesit谩bamos. Para hacer esto,
escriba la diferencia en el saldo antes y despu茅s del retiro de fondos en la constante de
diferencia . El resultado se compara con la cantidad de donaciones menos la tarifa de transacci贸n. Como se mencion贸 anteriormente, para la conveniencia de las pruebas y los c谩lculos, establec铆 mi propio precio para el
gas .
Ejecute las pruebas escritas con el comando de
prueba de trufa . Si todo se hizo correctamente, el resultado deber铆a ser el siguiente:

Resultado
Trat茅 de describir los pasos para probar contratos inteligentes en un lenguaje simple y comprensible: desde preparar un entorno de prueba hasta escribir las mismas pruebas.
Ahora puede probar cualquier contrato inteligente y asegurarse de que funciona correctamente.