考试通知
web3.py Testing API 完全指南:用 timeTravel、mine、snapshot 与 revert 掌控测试链时间与状态 Web3区块链【免费下载链接】web3.pyA python interface for interacting with the Ethereum blockchain and ecosystem.项目地址https://gitcode.com/gh_mirrors/we/web3.py点击查看免费下载web3.testing是 web3.py 暴露的一组非标准 RPC 接口封装用于在本地测试环境中操纵 EVM 状态推进区块时间、批量挖块、快照与回滚状态、重置到创世状态。本文将以 docs/web3.testing.rst 为骨架结合仓库源码与测试用例深入讲解每一个方法的语义、底层 RPC 委托链路与实际用法帮助你编写可精确控制时间与链状态的合约测试。一、web3.testing是什么web3.testing对象提供了一组用于测试的辅助方法它们通过非标准 RPC API与测试节点通信。文档明确指出这些 API 只在测试用 RPC 服务如eth-tester/eth-testrpc生态中可用并不存在于生产环境的以太坊节点如 geth 主网/测试网节点中——因此它们天然适合本地单元测试、集成测试与 CI 场景。在 web3.py 中Testing模块是Web3实例的默认模块之一。从 web3/main.py 的get_default_modules()可以看到def get_default_modules() - dict[str, type[Module] | Sequence[Any]]: return { eth: Eth, net: Net, geth: ( Geth, { admin: GethAdmin, txpool: GethTxPool, debug: GethDebug, }, ), tracing: Tracing, testing: Testing, # 默认挂载直接可通过 w3.testing 访问 }也就是说创建Web3实例后无需任何额外配置即可访问w3.testing。注意该模块只在同步Web3上默认挂载异步AsyncWeb3见get_async_default_modules()并未包含testing。Testing类继承自web3.module.Module完整实现位于 web3/testing.pyfrom web3._utils.rpc_abi import ( RPC, ) from web3.module import ( Module, ) class Testing(Module): def timeTravel(self, timestamp: int) - None: self.w3.manager.request_blocking(RPC.testing_timeTravel, [timestamp]) def mine(self, num_blocks: int 1) - None: self.w3.manager.request_blocking(RPC.evm_mine, [num_blocks]) def snapshot(self) - int: self.last_snapshot_idx self.w3.manager.request_blocking(RPC.evm_snapshot, []) return self.last_snapshot_idx def reset(self) - None: self.w3.manager.request_blocking(RPC.evm_reset, []) def revert(self, snapshot_idx: int | None None) - None: if snapshot_idx is None: revert_target self.last_snapshot_idx else: revert_target snapshot_idx self.w3.manager.request_blocking(RPC.evm_revert, [revert_target])可以看到每个方法都非常薄它们只是把参数包装成列表后交给RequestManager.request_blocking()发送底层 RPC。对应的 RPC 端点常量定义在 web3/_utils/rpc_abi.pyevm_mine RPCEndpoint(evm_mine) evm_reset RPCEndpoint(evm_reset) evm_revert RPCEndpoint(evm_revert) evm_snapshot RPCEndpoint(evm_snapshot) # ... testing_timeTravel RPCEndpoint(testing_timeTravel)二、环境准备使用支持 Testing API 的 Provider要实际调用这些方法需要连接一个实现了上述非标准 RPC 的测试后端。web3.py 官方推荐的是EthereumTesterProvider它集成eth-tester库与py-evm后端。在 docs/providers.rst 中给出了安装与初始化方式pip install web3[tester]from web3 import Web3, EthereumTesterProvider w3 Web3(EthereumTesterProvider())EthereumTesterProvider的构造函数签名是EthereumTesterProvider(ethereum_testerNone, api_endpointsNone)其中ethereum_tester可以是eth_tester.EthereumTester实例或其BaseChainBackend子类api_endpoints用于覆盖默认的 RPC 端点映射。该 Provider 在文档中被标记为Experimental实验性功能仍有缺口但处于积极开发与维护中适合测试场景而非生产。在仓库的测试体系中w3.testing配合EthereumTesterProvider被大量使用例如 tests/integration/test_ethereum_tester.py 中用它构造空区块fixturepytest.fixture def empty_block(w3): w3.testing.mine() block w3.eth.get_block(latest) assert not block[transactions] return block三、五个核心方法详解1.timeTravel(timestamp)—— 控制时间跳过依赖时间的逻辑签名Testing.timeTravel(timestamp: int) - None委托给testing_timeTravelRPC 方法。语义将测试链推进一个区块并把新块的时间戳设置为传入的整型timestamp。适用场景测试依赖时间戳的合约逻辑例如锁仓到期、拍卖截止、期权行权、block.timestamp相关的状态转换等。你不需要真的等待真实时间流逝直接穿越到目标时间即可。仓库测试佐证tests/core/testing-module/test_testing_timeTravel.pydef test_time_traveling(w3): current_block_time w3.eth.get_block(pending)[timestamp] time_travel_to current_block_time 12345 w3.testing.timeTravel(time_travel_to) latest_block_time w3.eth.get_block(pending)[timestamp] assert latest_block_time time_travel_to该测试展示了典型用法先读取pending区块的当前时间戳加上偏移量12345 秒后调用timeTravel再断言最新区块时间戳确实到达了目标时间。注意传入的时间戳应为绝对 Unix 时间戳秒而非相对偏移。2.mine(num_blocks1)—— 批量出块签名Testing.mine(num_blocks: int 1) - None委托给evm_mineRPC 方法。语义挖出num_blocks个新区块默认值为 1。适用场景推进区块高度使区块号相关的逻辑如在第 100 块后可领取奖励进入可测试状态触发区块级事件newHeads订阅、区块过滤器在测试中被真实产生结合合约调用确认交易已被打包进后续区块。仓库测试佐证tests/core/testing-module/test_testing_mine.pydef test_testing_mine_single_block(w3): w3.testing.mine() before_mining_block w3.eth.get_block(latest) w3.testing.mine() after_mining_block w3.eth.get_block(latest) assert after_mining_block[number] - before_mining_block[number] 1 def test_testing_mine_multiple_blocks(w3): w3.testing.mine() before_mining_block w3.eth.get_block(latest) w3.testing.mine(5) after_mining_block w3.eth.get_block(latest) assert after_mining_block[number] - before_mining_block[number] 5两条用例分别验证默认挖 1 块、以及mine(5)一次推进 5 个区块高度用区块号差值精确断言。3.snapshot()—— 保存 EVM 状态快照签名Testing.snapshot() - int委托给evm_snapshotRPC 方法。语义对当前 EVM 状态账户余额、存储、区块高度等拍摄快照返回一个整数标识符snapshot index该标识符可用于后续revert()恢复现场。实现细节从 web3/testing.py 可以看到snapshot()会把返回值同时保存在实例属性self.last_snapshot_idx上因此后续无参调用revert()时能自动定位到最近一次快照。适用场景在测试前置步骤中固定状态例如部署好合约、转入初始资金、设定特定区块高度然后放心执行任意操作最后一键恢复无需重新部署。4.revert(snapshot_idxNone)—— 恢复到快照签名Testing.revert(snapshot_idx: int | None None) - None委托给evm_revertRPC 方法。语义不传snapshot_idx恢复到最近一次快照即last_snapshot_idx传入snapshot_idx恢复到该整数标识符对应的快照。实现细节revert()内部对None与显式索引做了分流if snapshot_idx is None: revert_target self.last_snapshot_idx else: revert_target snapshot_idx self.w3.manager.request_blocking(RPC.evm_revert, [revert_target])仓库测试佐证tests/core/testing-module/test_testing_snapshot_and_revert.py—— 覆盖恢复到最近快照与恢复到指定快照两种路径def test_snapshot_revert_to_latest_snapshot(w3): w3.testing.mine(5) block_before_snapshot w3.eth.get_block(latest) w3.testing.snapshot() # ... 中间继续 mine(3)链状态发生变化 ... w3.testing.revert() # 无参回到最近快照 block_after_revert w3.eth.get_block(latest) # 断言快照时与回退后的区块哈希完全一致 def test_snapshot_revert_to_specific(w3): w3.testing.mine(5) block_before_snapshot w3.eth.get_block(latest) snapshot_idx w3.testing.snapshot() # 记录第一个快照索引 # 之后又连续多次 mine snapshot产生多个快照 w3.testing.mine() w3.testing.snapshot() w3.testing.mine() w3.testing.snapshot() w3.testing.mine() w3.testing.snapshot() w3.testing.revert(snapshot_idx) # 显式回退到最初那个快照 block_after_revert w3.eth.get_block(latest) assert block_before_snapshot[hash] block_after_revert[hash]两个用例都用区块哈希作为状态一致性的强证据只有 EVM 状态被精确恢复哈希才会逐字节相同。5.reset()—— 重置回创世状态签名Testing.reset() - None委托给evm_resetRPC 方法。语义将 EVM重置回创世genesis状态相当于把链完全归零重新开始通常用于在每个测试用例之间保证绝对干净的起点。实现细节reset()不带任何参数直接发送evm_reset。注意与revert()不同reset()不依赖任何已保存的快照索引是整体性的状态重建。四、底层原理RPC 委托链与后端映射w3.testing.xxx()的调用链可以概括为w3.testing.mine(3) └─ Testing.mine() → request_blocking(RPC.evm_mine, [3]) └─ RequestManager._make_request / formatted_response (web3/manager.py#L218-L231) └─ Provider 收到 JSON-RPC 请求: {method: evm_mine, params: [3]} └─ eth-tester 后端执行对应操作并返回结果在 web3/manager.py 中request_blocking()是同步请求的统一切入点它通过 provider 发起请求再经formatted_response完成结果格式化与错误处理。当使用EthereumTesterProvider时这些非标准 RPC 方法被映射到eth-tester的底层调用。映射表定义在 web3/providers/eth_tester/defaults.pytesting: { timeTravel: call_eth_tester(time_travel), }, # ... evm: { mine: call_eth_tester(mine_blocks), revert: call_eth_tester(revert_to_snapshot), snapshot: call_eth_tester(take_snapshot), },也就是说testing_timeTravel→eth_tester.time_travel(timestamp)evm_mine→eth_tester.mine_blocks(num_blocks)evm_snapshot→eth_tester.take_snapshot()evm_revert→eth_tester.revert_to_snapshot(idx)这是方法名 → RPC 端点 → Provider 后端实现的三层委托因此只要后端实现了对应 RPC例如支持这些非标准方法的 geth--dev模式或 ganachew3.testing的接口同样可用无需修改调用方代码。另外值得一提的细节在 web3/providers/rpc/utils.py 的REQUEST_RETRY_ALLOWLIST中testing与evm前缀都被列入请求重试白名单。这意味着在 HTTP Provider 的失败重试机制下testing_*与evm_*这类方法默认允许重试结合默认重试次数 5 次、退避因子 0.125 的ExceptionRetryConfiguration。五、典型实战模式一套可重复的合约测试流程将上述方法组合起来可以形成一套标准的布置 → 快照 → 破坏 → 还原测试模式from web3 import Web3, EthereumTesterProvider w3 Web3(EthereumTesterProvider()) w3.eth.default_account w3.eth.accounts[0] # 1) 布置部署合约、推进到目标区块、穿越时间 w3.testing.mine(10) # 快速推进 10 个区块 w3.testing.timeTravel(w3.eth.get_block(latest)[timestamp] 86400) # 穿越 1 天 # 2) 快照保存当前状态作为基线 snapshot_id w3.testing.snapshot() # 3) 破坏性测试执行任意可能导致状态变化的操作 w3.testing.mine(3) # ... 合约交互、状态断言 ... # 4) 还原无参 revert 回到最近快照链状态与区块哈希完全一致 w3.testing.revert() # 5) 需要绝对干净的起点时直接 reset 回创世状态 w3.testing.reset()实践建议每个测试用例开头用reset()或snapshot()建立基线结尾用revert()还原避免用例间相互污染验证时间敏感逻辑时先timeTravel再调用目标合约函数用区块哈希而非仅区块号断言还原是否精确对snapshot()的返回值妥善保存尤其是在嵌套多级快照时显式传给revert()而非依赖隐式的最近快照。六、注意事项与适用边界仅限测试环境这些方法对应非标准 RPC文档明确指出它们只在测试 RPC 服务eth-testrpc/eth-tester生态中提供生产节点上调用会失败或返回MethodUnavailable错误。Provider 属实验性EthereumTesterProvider在 docs/providers.rst 中明确标注为 Experimental存在功能缺口但处于活跃开发中安装依赖请使用pip install web3[tester]以获得版本匹配的eth-tester与py-evm。同步专属testing只注册在同步Web3的默认模块中见 web3/main.pyAsyncWeb3默认不挂载该模块。reset()的后端支持从 defaults.py 的端点映射看EthereumTesterProvider默认端点集里没有为evm_reset提供映射reset()是否可用取决于所连接后端是否实现该 RPC——这再次印证了接口统一、后端能力决定行为的设计。七、总结web3.testing是 web3.py 面向本地测试场景的时间与状态控制台方法底层 RPC作用timeTravel(timestamp)testing_timeTravel推进一个区块并设置其时间戳mine(num_blocks1)evm_mine批量挖出指定数量的新区块snapshot()evm_snapshot保存当前 EVM 状态并返回整数快照 IDrevert(snapshot_idxNone)evm_revert恢复到最近或指定快照reset()evm_reset将 EVM 重置回创世状态五个方法共同覆盖了测试中最常见的链操作诉求。配合EthereumTesterProvider与 tests/core/testing-module 目录下的真实测试用例你可以快速验证自己对时间、区块与状态控制的直觉并搭建出高度可复现、互不干扰的智能合约测试套件。赞分享Web3区块链【免费下载链接】web3.pyA python interface for interacting with the Ethereum blockchain and ecosystem.项目地址https://gitcode.com/gh_mirrors/we/web3.py点击查看免费下载相关推荐Jest 快照测试(Snapshot Testing)完全指南Jest 快照测试 Snapshot Testing 完全指南 什么是快照测试 快照测试是一种特殊的测试方法主要用于确保UI界面不会发生意外改变。它的工作原测试质量保障代码覆盖率开发工具Jest 快照测试(Snapshot Testing)完全指南Jest 快照测试 Snapshot Testing 完全指南 什么是快照测试 快照测试是 Jest 提供的一种独特的测试方法主要用于确保 UI 界面或数据测试质量保障代码覆盖率开发工具Jest 快照测试(Snapshot Testing)完全指南Jest 快照测试 Snapshot Testing 完全指南 还在为UI组件测试而头疼吗每次修改代码后都要手动验证渲染结果是否正确Jest快照测试帮你一键测试质量保障代码覆盖率开发工具上一篇QrCodeScan扫描动画实现自定义扫描线与扫描框的UI设计教程下一篇3分钟搞定RustDesk Server容器健康检查从故障到自愈的实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考