Hardhat 3设置10000次却只跑100:核Test Profile与inline优先级
链小知 · 进阶 · 核验 · 依官方文档整理
从实际命令、独立profile、函数/合约注释与错误编号解释fuzz参数为何没按预期生效。
开始前准备
- 准备已有工程的依赖锁、配置、源码和脱敏编译/测试日志;保留工具、编译器完整版本与执行命令。
- 本教程对照官方文档与已有材料,本次不安装、编译或运行测试,不运行SDK、外部脚本、RPC/API、钱包或部署;命令仅用于辨认原流程。
1. 先核实际选中的测试profile
对照原npx hardhat test solidity --test-profile ci及HARDHAT_TEST_PROFILE;CLI参数优先,没有选择时用default。--build-profile只影响编译,不能代替--test-profile。
确认原日志实际发现带参数的test函数并显示fuzz runs;本例讨论原记录,没有启动测试或假定所有Hardhat 3历史小版本都已有当前方法。
检查结果:测试/编译profile和原选择来源分别明确。
2. 核profile配置形状与独立默认值
test.solidity.profiles需包含default,且不能与test.solidity顶层选项混用。每个profile从Hardhat自身默认值独立解析,不继承用户default里的seed、isolate等设置;要共享须在各profile明确配置。
例如default配置isolate=true,ci只写fuzz.runs,并不能推出ci也保留isolate=true;检查实际配置,而非借名字猜它是加强版default。
检查结果:profiles形状合法、共享选项有明确来源,未假定自动继承。
3. 按函数层级先算有效runs
NatSpec注释如/// hardhat-config: fuzz.runs = 100作用于函数时,优先于合约上的ci.fuzz.runs=10000;同层级才是profile前缀优先。普通//注释不能直接当NatSpec指令。
函数未设的其他选项仍可由合约指令提供。对每个字段分开算,不能因函数只有runs就清空所有合约配置。
检查结果:函数/合约、带前缀/不带前缀按顺序解释出有效值。
4. 迁移Foundry时核default前缀差异
当前Hardhat也接受forge-config:,支持camelCase/snake_case/kebab-case键。Foundry的default.通过profile继承适用其他profile,Hardhat的default.仅适用default;保留前缀迁到ci后,原覆盖不一定继续生效。
同一个测试函数正文可兼容,不代表注释、profile、cheatcode或随机输入完全等价。对照目标工具当前正文和原版本,勿仅根据第三方比较文章推配置可移植。
检查结果:原注释和目标profile逐字段对应,未把default限定扩展为全profile。
5. 由错误编号区分配置失败与测试失败
HHE813表示fuzz/invariant键不适用该测试类型;HHE821是无效inline指令;HHE822是所选profile未定义。HHE814表示--no-compile下测试未编译,官方建议先hardhat build或移除该flag;这些都不是业务属性反例。
原fuzz配置failurePersistDir若已启用,会记录/重放反例;新活动和旧反例各记。用原测试名、runs和错误收尾,不能通过删失败目录或放宽断言把错误变成通过。
检查结果:配置、发现/编译失败与真实断言失败分清,保留原记录。
怎样确认完成
- 能从原命令、配置、注释及错误编号解释有效fuzz设置和未完成范围。
常见错误与边界
- Test Profile不继承用户default;Build Profile与它独立。
- 函数无前缀可覆盖合约ci前缀;default在两工具里的范围不同。
- 零测试或配置错误不代表业务测试通过。