当我们在 Hardhat 项目中运行 npx hardhat test 命令时,终端会输出一份详细的报告。这份报告不仅告诉我们测试是否通过,还提供了关于合约编译、Gas 消耗和网络配置的宝贵信息。理解这份报告的每一个部分,对于编写出高效、安全的智能合约至关重要。
让我们逐段分析一份典型的 Hardhat 测试输出。
第一部分:编译与测试结果摘要
npx hardhat test
Compiled 1 Solidity file successfully (evm target: paris).
Lock
Deployment
✔ Should set the right unlockTime (58ms)
✔ Should set the right owner
✔ Should receive and store the funds to lock
✔ Should fail if the unlockTime is not in the future
Withdrawals
Validations
✔ Should revert with the right error if called too soon
✔ Should revert with the right error if called from another account
✔ Shouldn't fail if the unlockTime has arrived and the owner calls it
Events
✔ Should emit an event on withdrawals
Transfers
✔ Should transfer the funds to the owner
9 passing (121ms)
这是报告中最直观的部分,也是我们首先会关注的部分。
Compiled 1 Solidity file successfully (evm target: paris).这行告诉我们,Hardhat 成功编译了一个 Solidity 源文件。evm target: paris指的是编译时所针对的以太坊虚拟机 (EVM) 版本,"Paris" 是以太坊合并 (The Merge) 后的升级代号。这确保了我们的合约字节码与目标链的 EVM 兼容。测试套件 (
Lock)Lock是我们正在测试的智能合约的名称。接下来的缩进结构清晰地展示了测试用例的组织方式,这通常与我们在测试文件中使用的describe和it块相对应。✔ Should revert...这两个测试验证了在错误条件下(时间未到、调用者非所有者)调用提款函数会如期失败回滚。 ✔ Shouldn't fail...验证了在正确条件下(时间到达且是所有者调用),提款操作能够成功执行。 ✔ Should emit an event on withdrawals验证了成功提款时,会触发一个预期的事件(Event)。 ✔ Should transfer the funds to the owner验证了提款时,合约中的资金确实被转移到了所有者的地址。 ✔ Should set the right unlockTime (58ms)测试通过,验证了合约部署后 unlockTime变量被正确设置。括号内的58ms表示执行这个测试用例花费的时间。✔ Should set the right owner验证了合约的 owner是否为部署者。✔ Should receive and store the funds to lock验证了合约在部署时能够正确接收并存储资金。 ✔ Should fail if the unlockTime is not in the future这是一个重要的负向测试,验证了如果部署时设置的解锁时间是过去的时间点,合约部署应该失败。 Deployment(部署测试): 这个测试块专注于验证合约部署时的初始状态是否正确。Withdrawals(提款功能测试): 这个测试块专注于合约的核心功能——提款。它被进一步细分为Validations(验证)、Events(事件) 和Transfers(转账)。9 passing (121ms)这是最终的测试摘要。它总结了所有测试用例的结果:总共有 9 个测试全部通过,完成所有测试的总耗时为 121 毫秒。
第二部分:Gas 和网络配置报告
这部分由 hardhat-gas-reporter 插件生成,提供了关于 Gas 使用情况的详细洞察,这对于优化合约成本至关重要。
Solidity 和网络配置
这部分展示了编译和测试时的环境配置。
Solidity: 0.8.28使用的 Solidity 编译器版本。 Optim: false表示编译时未开启优化器。在生产环境中,通常会将其设置为 true以减少 Gas 消耗。Runs: 200这是优化器的一个参数,表示假设每个函数被调用的次数。仅在 Optim为true时生效。viaIR: false表示是否通过中间表示(IR)进行编译,这是一种新的、更强大的优化流程。 Block: 30,000,000 gas测试时所模拟的区块 Gas 上限 (Block Gas Limit)。
方法 Gas 消耗
这张表格分析了在测试过程中,合约的每个外部 (external) 或公共 (public) 函数的 Gas 消耗情况。
Contracts / Methods合约和方法名。 Min / Max / Avg在所有调用中,该方法消耗 Gas 的最小值、最大值和平均值。 # calls在测试中该方法被调用的总次数。 usd (avg)根据预设的 Gas价格 估算出的平均调用成本(美元)。这里显示 -可能是因为未配置价格或者成本过低。
withdraw 函数分析
-
平均 Gas 消耗 ( Avg) 为 34,096。 -
在测试中总共被调用了 7 次 ( # calls)。
部署 Gas 消耗
这张表格展示了部署合约本身所需的 Gas 成本。
Lock 合约部署分析
-
平均部署成本 ( Avg) 为 326,112 Gas。 % of limit部署成本占区块 Gas 上限的百分比,这里是 1.1%。这是一个有用的指标,可以帮助我们判断我们的合约是否过于庞大,以至于有在某些网络上部署失败的风险。
结论
这份 Hardhat 测试报告是一份全面的合约“体检报告”。它告诉我们:
- 功能正确性
所有的 9 个测试用例都已通过,证明 Lock合约在预设场景下的行为符合预期。 - 代码健康度
测试覆盖了部署、核心功能、边界条件和事件等多个方面,是一套比较完善的测试。 - 性能与成本
我们清晰地看到了 withdraw函数的平均调用成本和Lock合约的部署成本。这些数据是优化的起点。例如,如果部署成本过高,我们可能会考虑将合约拆分或优化存储变量。如果某个函数调用成本异常,我们需要深入代码检查是否存在效率低下的操作。
通过定期运行并仔细分析这份报告,开发者可以持续迭代和改进自己的智能合约,确保其在上线前既安全可靠,又经济高效。

