编写自动化智能合约测试
设置测试环境
你可能想知道我们_如何_运行这些测试,因为智能合约是在区块链内部执行的。使用实际的 Ethereum 网络会非常昂贵,虽然测试网是免费的,但它们也很慢(区块时间为 12 秒或更长)。如果我们打算在每次更改代码时运行数百个测试,我们需要更好的东西。
我们将使用一种叫做_本地区块链_的东西:它是真实区块链的精简版本,与互联网断开连接,在你的机器上运行。这将大大简化事情:你不需要获得 Ether,并且会立即挖掘出新的区块。
编写单元测试
我们将使用 Chai 断言进行单元测试,可以通过安装 Hardhat Toolbox 来使用。
$ npm install --save-dev @nomicfoundation/hardhat-toolbox
我们将把测试文件保存在 test
目录中。最好通过镜像 contracts
目录来构建测试:对于那里的每个 .sol
文件,创建一个相应的测试文件。
是时候编写我们的第一个测试了!这些测试将测试 Box
合约的属性 来自之前的指南:一个简单的合约,允许你 retrieve
所有者之前 store
的值。
在你的项目根目录中创建一个 test
目录。我们将把测试保存为 test/Box.test.js
。每个测试 .js
文件通常包含单个合约的测试,并以该合约命名。
// test/Box.test.js
// Load dependencies
const { expect } = require('chai');
// Start test block
describe('Box', function () {
before(async function () {
this.Box = await ethers.getContractFactory('Box');
});
beforeEach(async function () {
this.box = await this.Box.deploy();
await this.box.waitForDeployment();
});
// Test case
it('retrieve returns a value previously stored', async function () {
// Store a value
await this.box.store(42);
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await this.box.retrieve()).toString()).to.equal('42');
});
});
已经有很多关于如何构建单元测试的书籍。查看 Moloch Testing Guide,了解一套专为测试 Solidity 智能合约而设计的原则。 |
我们现在准备好运行我们的测试了!
运行 npx hardhat test
将执行 test
目录中的所有测试,检查你的合约是否以你希望的方式工作:
$ npx hardhat test
Box
✓ retrieve returns a value previously stored
1 passing (578ms)
此时,设置一个持续集成服务(例如 CircleCI)也是一个非常好的主意,以便在每次将代码提交到 GitHub 时自动运行测试。
执行复杂断言
你的合约的许多有趣的属性可能难以捕获,例如:
-
验证合约是否在错误时恢复
-
测量帐户的 Ether 余额变化了多少
-
检查是否发出了正确的事件
我们建议使用 Hardhat Chai Matchers 来帮助你测试所有这些属性,并使用 Hardhat Network Helpers 来模拟区块链上的时间流逝。这些工具将让你编写强大的断言,而无需担心底层 Ethereum 库的底层细节。