链链上图谱Web3 Knowledge Atlas↗
链上图谱/开发技术路线/Foundry 测试

Foundry / Tutorial 02

让每个假设,都能被测试推翻。

合约开发的反馈循环不是“写完再部署”,而是先用测试证明权限、状态变化、失败回滚和资金路径符合预期。

01 / Workflow

先建立快速反馈循环

一个可复现的测试项目,应该能在本地快速编译、运行测试并定位失败。先把合约、测试、脚本和配置分开,再逐步增加集成场景。

01初始化项目固定编译器和依赖版本。
02写单元测试覆盖函数成功与拒绝路径。
03测试不变量验证余额、权限和状态关系。
04集成验证模拟真实协议和外部调用。
forge init counter-app
forge build
forge test -vvv
forge test --match-test testOnlyOwner

02 / Unit tests

先测最小行为,再测组合路径

测试名称应该说明行为和条件。除了“成功后值变成什么”,还要明确未授权调用、零值、边界值和失败时状态是否保持不变。

function testSetUpdatesValue() public {
    counter.set(42);
    assertEq(counter.value(), 42);
}

function testSetRevertsForStranger() public {
    vm.prank(stranger);
    vm.expectRevert("not owner");
    counter.set(42);
}
重要:测试通过只说明测试覆盖到的假设成立,不代表合约没有其他漏洞。

03 / Fuzzing

让输入不再只有一个“好例子”

模糊测试会为参数生成多组输入,适合发现边界、精度、极端数量和状态组合问题。先定义不变量,再让测试反复尝试打破它。

不变量需要观察什么
权限不变非授权账户不能改变管理员或关键参数。
余额守恒扣除费用后,系统总余额和用户余额关系符合设计。
失败回滚拒绝操作不会留下部分状态更新或资产变化。

04 / Fork testing

在本地模拟真实链上状态

本地 fork 可以让测试读取某个网络的历史状态,再在隔离环境中模拟协议交互。固定区块高度有助于复现问题,但不能替代对当前状态的独立核验。

forge test --fork-url $RPC_URL \
  --fork-block-number 19000000 \
  -vvv

不要把 RPC 密钥、私钥或生产凭证提交到仓库。测试脚本中使用专门的假账户和最小权限。

05 / Delivery

交付前检查清单

不要做:在测试脚本中使用真实私钥,或把未经审计的代码直接部署到真实资产环境。

上一课:Solidity 入门 → 返回开发路线 →