Testare con Chai e Mocha

(Supported since Remix IDE v0.22.0)

Remix supporta il test dei file in JavaScript utilizzando la libreria di asserzioni Chai e il framework di test Mocha

Chai è una libreria di asserzioni BDD / TDD per il nodo e il browser che può essere meravigliosamente abbinata a qualsiasi framework di test javascript.

Mocha è un framework di test JavaScript ricco di funzionalità che gira su Node.js e nel browser, eseguendo i test asincroni semplici e divertenti.

Scrivere i test

Create a js file in your project workspace. Better to create it inside scripts folder. Let’s name it sample.test.js.

Scrivete i vostri test nel file. Ecco un esempio:

const { expect } = require("chai");

describe("Sample", function () {
  it("Sample tests with mocha and chai", async function () {
    var foo = 'bar'
    var beverages = { tea: [ 'chai', 'matcha', 'oolong' ] };
    expect(foo).to.be.a('string');
    expect(foo).to.equal('bar');
    expect(foo).to.have.lengthOf(3);
    expect(beverages).to.have.property('tea').with.lengthOf(3);
  });
});

Eseguire i test

Una volta terminata la scrittura dei test, cliccate con il pulsante destro del mouse sul nome del file nel plugin File Explorers (Esplora File). Verranno mostrate alcune opzioni insieme all’opzione Run (Esegui). L’opzione Esegui viene utilizzata per eseguire gli script JS

Cliccando suRun (Esegui), i test verranno eseguiti e i risultati saranno visualizzati sul terminale.

Testare un contratto

Allo stesso modo, i test unitari possono essere scritti per testare la funzionalità di uno contratto intelligente. Un esempio per testare il contratto predefinito 1_Storage.sol può essere il seguente:

const { expect } = require("chai");

describe("Storage", function () {
  it("test initial value", async function () {
    // Make sure contract is compiled and artifacts are generated
    const metadata = JSON.parse(await remix.call('fileManager', 'getFile', 'contracts/artifacts/Storage.json'))
    const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner()
    let Storage = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer);
    let storage = await Storage.deploy();
    console.log('storage contract Address: ' + storage.address);
    await storage.deployed()
    expect((await storage.retrieve()).toNumber()).to.equal(0);
  });

  it("test updating and retrieving updated value", async function () {
    const metadata = JSON.parse(await remix.call('fileManager', 'getFile', 'contracts/artifacts/Storage.json'))
    const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner()
    let Storage = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer);
    let storage = await Storage.deploy();
    await storage.deployed()
    const setValue = await storage.store(56);
    await setValue.wait();
    expect((await storage.retrieve()).toNumber()).to.equal(56);
  });

  it("fail test updating and retrieving updated value", async function () {
    const metadata = JSON.parse(await remix.call('fileManager', 'getFile', 'contracts/artifacts/Storage.json'))
    const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner()
    let Storage = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer);
    let storage = await Storage.deploy();
    await storage.deployed()
    const setValue = await storage.store(56);
    await setValue.wait();
    expect((await storage.retrieve()).toNumber()).to.equal(55);
  });
});

Il risultato sarà come:

Debug di una transazione di test

Per eseguire il debug di una transazione in uno dei test, stampare l’hash della transazione e inserirlo nel plugin Debug di Remix.

Supporto Hardhat-ethers

Remix supporta anche i metodi del plugin hardhat-ethers del framework Hardhat. I metodi disponibili in questo plugin sono:

interface Libraries {
  [libraryName: string]: string;
}

interface FactoryOptions {
  signer?: ethers.Signer;
  libraries?: Libraries;
}

function getContractFactory(name: string, signer?: ethers.Signer): Promise<ethers.ContractFactory>;

function getContractFactory(name: string, factoryOptions: FactoryOptions): Promise<ethers.ContractFactory>;

function getContractFactory(abi: any[], bytecode: ethers.utils.BytesLike, signer?: ethers.Signer): Promise<ethers.ContractFactory>;

function getContractAt(name: string, address: string, signer?: ethers.Signer): Promise<ethers.Contract>;

function getContractAt(abi: any[], address: string, signer?: ethers.Signer): Promise<ethers.Contract>;

function getSigners() => Promise<ethers.Signer[]>;

function getSigner(address: string) => Promise<ethers.Signer>;

function getContractFactoryFromArtifact(artifact: Artifact, signer?: ethers.Signer): Promise<ethers.ContractFactory>;

function getContractFactoryFromArtifact(artifact: Artifact, factoryOptions: FactoryOptions): Promise<ethers.ContractFactory>;

function getContractAtFromArtifact(artifact: Artifact, address: string, signer?: ethers.Signer): Promise<ethers.Contract>;

In questo modo, si possono eseguire facilmente i test per un progetto hardhat utilizzando Remix.

Un esempio per testare il contratto Storage con i metodi di questo plugin può essere il seguente:

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Storage", function () {
  it("test initial value", async function () {
    const Storage = await ethers.getContractFactory("Storage");
    const storage = await Storage.deploy();
    await storage.deployed();
    console.log('storage deployed at:'+ storage.address)
    expect((await storage.retrieve()).toNumber()).to.equal(0);
  });
   it("test updating and retrieving updated value", async function () {
    const Storage = await ethers.getContractFactory("Storage");
    const storage = await Storage.deploy();
    await storage.deployed();
    const storage2 = await ethers.getContractAt("Storage", storage.address);
    const setValue = await storage2.store(56);
    await setValue.wait();
    expect((await storage2.retrieve()).toNumber()).to.equal(56);
  });
});

Il risultato sarà come: