使用 Chai 和 Mocha 测试
(从 Remix IDE v0.22.0 起开始支持)
Remix支持使用断言库 Chai 和测试框架Mocha在JavaScript中对您的文件进行测试。
Chai是一个用于Node.js和浏览器的BDD / TDD断言库,可以与任何JavaScript测试框架完美地配对使用。
Mocha是一个功能丰富的JavaScript测试框架,在Node.js和浏览器上运行,使异步测试变得简单而有趣。
编写测试
在您的项目工作区创建一个 js 文件。最好将其创建在 scripts
文件夹中。我们给它命名为 sample.test.js
。
在该文件中编写您的测试代码。以下是一个示例:
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);
});
});
运行测试
完成编写测试后,在 “文件浏览器插件” 中右键单击文件名。它将显示一些选项,包括 “运行” 选项。此 “运行” 选项用于运行JS脚本。
点击 “Run” ,会执行测试,结果将显示在终端上。
测试一个合约
同样,可以编写单元测试来测试智能合约的功能。一个测试默认的1_Storage.sol
合约的示例可能如下:
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);
});
});
结果为:
调试测试交易
要在测试中调试交易,请打印交易哈希并将其输入到Remix Debugger插件。
支持 Hardhat-ethers
Remix 还支持 Hardhat 框架的 hardhat-ethers方法。该插件下可用的方法有:
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>;
通过这个,可以使用Remix轻松地运行Hardhat项目的测试。
例如,使用此插件方法测试 Storage
合约可以如下:
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);
});
});
结果为: