尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
cosmos-sdk 系统测试入门:从查询、JSON 断言到 Genesis 与交易驱动的状态测试
区块链【免费下载链接】cosmos-sdkFramework for building performant, customizable blockchains with native interoperability项目地址https://gitcode.com/gh_mirrors/co/cosmos-sdk点击查看免费下载本指南基于 cosmos-sdk 仓库中的 tools/systemtests/GETTING_STARTED.md完整讲解如何在本地编写并运行一个多节点链的系统测试system test。你将学会准备测试用二进制、编写第一个查询测试、用 gjson 做 JSON 断言、通过ModifyGenesisJSON修改创世状态以及通过提交真实交易驱动链上状态变化——全程以可运行的simdCLI 与真实多节点网络为验证对象。前置准备构建二进制并放入测试目录系统测试属于黑盒测试black-box test它只与编译后的链二进制打交道不直接调用 Go 内部 API参见 tests/systemtests/README.md。因此第一步是构建当前分支的二进制并把它复制到tests/systemtests/binaries目录。在项目根目录执行make test-systemmake test-system在根 Makefile 中定义为test-sdk-system加上各企业模块的系统测试而test-sdk-system会先构建当前分支二进制build-system-test-current将其复制到./tests/systemtests/binaries/再执行 tests/systemtests/Makefile 中的测试目标见 Makefile。也可以手动完成同样的准备make build mkdir -p ./tests/systemtests/binaries cp ./build/simd ./tests/systemtests/binaries/值得注意的细节框架在 system.go 的NewSystemUnderTest中会把二进制路径拼接为WorkDir/binaries/binary并依据二进制名解析出项目名而 test_runner.go 在测试启动时还会用ulimit -n校验文件句柄数量是否足够每个节点约需 260 个不足时会 Fail fast 并提示ulimit -n 值。tests/systemtests/binaries与tests/systemtests/testnet属于缓存目录不应提交到 git。Part 1编写第一个系统测试切到tests/systemtests目录进行开发。如果没有与你的场景匹配的测试文件就新建一个例如bank_test.go//go:build system_test package systemtests import ( testing ) func TestQueryTotalSupply(t *testing.T) { sut.ResetChain(t) sut.StartChain(t) cli : NewCLIWrapper(t, sut, verbose) raw : cli.CustomQuery(q, bank, total-supply) t.Log(### got: raw) }理解测试骨架Go build tag 排除常规运行文件首行//go:build system_test使该测试默认不会参与常规go test运行只有显式传入-tagssystem_test才会编译执行。tests/systemtests/下的所有测试如 staking_test.go、upgrade_test.go均采用这一约定。共享的测试运行器tests/systemtests下所有测试都构建在 main_test.go 初始化的测试运行器之上——TestMain调用systemtests.RunTests(m)实现在 test_runner.go。RunTests解析命令行 flag、初始化 SDK 配置、创建全局SystemUnderTestSut并执行SetupChain()调用simd testnet init-files在本地生成一个多节点测试网默认 4 个节点同时备份 genesis、keyring 与节点配置文件。重置与启动sut.ResetChain(t)会停止节点、通过comet unsafe-reset-all清空状态并恢复 genesis、keyring 和节点配置见 system.go随后sut.StartChain(t)异步拉起所有节点、等待节点上线并订阅NewBlock事件来跟踪区块高度。因此在每个测试开头重置状态是保证稳定基线的良好实践。CLI 包装器NewCLIWrapper(t, sut, verbose)构造一个 CLIWrapper它在内部持有可执行二进制路径、RPC 地址、chain ID、home 目录、默认手续费1stake等并把 keyring 指向 test 后端见 cli.go。本例中的cli.CustomQuery(q, bank, total-supply)等价于执行simd q bank total-supply --output json --node tcp://localhost:26657即查询 bank 模块的总供应量并以 JSON 输出WithQueryFlags会自动追加--output json与--node目标节点参数见 cli.go。运行测试go test -modreadonly -tagssystem_test -v ./... --run TestQueryTotalSupply --verbose输出会非常冗长你能看到所有用于启动服务器或客户端交互的 simd CLI 命令。示例代码中我们只是把结果打印出来请留意形如bank_test.go:15: ### got: { supply: [ { denom: stake, amount: 2000000190 }, { denom: testtoken, amount: 4000000000 } ], pagination: { total: 2 } }在输出末尾还会附上服务器日志的尾部片段调试问题时这有时非常有用。这得益于 system.go 中的watchLogs每个节点的 stdout/stderr 既写入testnet/nodeN.out日志文件也进入一个环形缓冲测试失败时可打印最近的内容。Tips传入--nodes-count1可覆盖默认节点数默认 4加快本地跑测试的速度。该 flag 在 test_runner.go 中定义并同步到sut.nodesCount。Part 2用 gjson 处理 JSON 并编写断言拿到 JSON 响应后tidwall/gjson 库就能大显身手。它提供类似 jquery 的路径语法方便在文档中导航。例如gjson.Get(raw, supply).Array()返回supply下的所有子项组成的数组gjson.Get(raw, supply.#(denomstake).amount).Int()取得 denom 为stake的 amount并转为 int64。为了在系统测试中验证我们的假设把代码改为用 gjson 提取数据raw : cli.CustomQuery(q, bank, total-supply) exp : map[string]int64{ stake: int64(500000000 * sut.nodesCount), testtoken: int64(1000000000 * sut.nodesCount), } require.Len(t, gjson.Get(raw, supply).Array(), len(exp), raw) for k, v : range exp { got : gjson.Get(raw, fmt.Sprintf(supply.#(denom%q).amount, k)).Int() assert.Equal(t, v, got, raw) }这里把期望值设计为节点数的函数500000000 * sut.nodesCount等这样测试对节点数量变化保持弹性。对 stake 代币的假设通常会失败因为 staking 代币会因通胀inflation被持续增发——这正是下一步要解决的问题。在真实测试中staking_test.go 展示了同类模式查询验证者地址、委托后断言余额与委托响应全部通过 gjson 解析。运行测试go test -modreadonly -tagssystem_test -v ./... --run TestQueryTotalSupply --verboseTips把raw这个原始 JSON 响应作为assert/require的最后一个参数传入。失败时你通常只有数值而缺乏上下文带上原始响应能极大方便调试——上面的断言正是这样做的。Part 3通过 Genesis 设置链上状态先关闭通胀。这可以通过ModifyGenesisJSON辅助方法完成为了增加一点复杂度我们同时引入一种新代币并更新node0账户的余额。此时 setup 代码看起来又大又不易读——通常是时候考虑把通用操作抽成辅助函数了genesis_io.go 中已经有一些例子比如GetGenesisBalance、SetConsensusMaxGas、SetGovVotingPeriod。这里保留内联写法正好用来展示 gjson、sjson 与标准库 json 的混合使用sut.ResetChain(t) cli : NewCLIWrapper(t, sut, verbose) sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { // disable inflation genesis, err : sjson.SetRawBytes(genesis, app_state.mint.minter.inflation, []byte(0.000000000000000000)) require.NoError(t, err) // add new token to supply var supply []json.RawMessage rawSupply : gjson.Get(string(genesis), app_state.bank.supply).String() require.NoError(t, json.Unmarshal([]byte(rawSupply), supply)) supply append(supply, json.RawMessage({denom: mytoken,amount: 1000000})) newSupply, err : json.Marshal(supply) require.NoError(t, err) genesis, err sjson.SetRawBytes(genesis, app_state.bank.supply, newSupply) require.NoError(t, err) // add amount to any balance anyAddr : cli.GetKeyAddr(node0) newBalances : GetGenesisBalance(genesis, anyAddr).Add(sdk.NewInt64Coin(mytoken, 1000000)) newBalancesBz, err : newBalances.MarshalJSON() require.NoError(t, err) newState, err : sjson.SetRawBytes(genesis, fmt.Sprintf(app_state.bank.balances.#[address%q]#.coins, anyAddr), newBalancesBz) require.NoError(t, err) return newState }) sut.StartChain(t)ModifyGenesisJSON 的工作原理ModifyGenesisJSON定义于 system.go它会先执行ResetChain然后把 mutator 回调按顺序作用于 genesis 原始字节上一个的输出作为下一个的输入写回临时文件后通过setGenesis同步到所有节点的config/genesis.json最后把链标记为 dirtyMarkDirty。正因为回调链式传递原始字节你可以自由混用 sjson、gjson 甚至标准库encoding/json。上例的四个关键操作关闭通胀把app_state.mint.minter.inflation置为0.000000000000000000从源头消除 stake 的持续增发新增代币到总供应读取app_state.bank.supply数组、追加{denom: mytoken,amount: 1000000}后写回给node0增加余额cli.GetKeyAddr(node0)取得账户地址对应simd keys show node0 -aGetGenesisBalance见 genesis_io.go用 gjson 的#[address...]#过滤语法取出该地址现有 coins再用sdk.NewInt64Coin(mytoken, 1000000)追加写回余额用sjson.SetRawBytes以app_state.bank.balances.#[address%q]#.coins路径定位并替换该账户的 coins。这里使用的sdk.Coins类型来自仓库的 types/coin.go 与 types/coin.pb.gosdk.NewInt64Coin用于构造代币。更新断言并运行把新代币加入期望 map同时保持对节点数的弹性exp : map[string]int64{ stake: int64(500000000 * sut.nodesCount), testtoken: int64(1000000000 * sut.nodesCount), mytoken: 1000000, }go test -modreadonly -tagssystem_test -v ./... --run TestQueryTotalSupply --verbose --nodes-count1除ModifyGenesisJSON外框架还提供了ModifyGenesisCLI对每个节点执行如genesis add-genesis-account等命令见 system.gostaking_test.go 中就是用它在 genesis 阶段为测试账户注入代币的。注意ModifyGenesisCLI同样会把链标记为 dirty。Part 4通过 TX 修改链上状态更复杂的工作流与测试要求在运行中的链上修改状态这只能依赖链的内建逻辑与操作。例如要销毁部分新代币就需要提交一个 bank burn 消息。CLI 包装器的用法与查询类似直接传入参数即可它默认使用node0密钥作为--from// and when txHash : cli.Run(tx, bank, burn, node0, 400000mytoken) RequireTxSuccess(t, txHash)RequireTxSuccess与RequireTxFailure用于确保操作得到预期结果实现在 cli.go前者要求响应中的code 0后者要求非零 code 并可选校验错误消息片段。注意从 CometBFT v1 起RPC 错误可能不返回 ABCI 响应RequireTxFailure会先识别broadcast error on transaction validation这类情况。cli.Run是执行交易命令的主入口见 cli.go它会自动追加默认手续费--fees1stake未显式指定时、交易 flag--broadcast-mode sync、--output json、--yes、--chain-id、keyring flag、--node见WithTXFlags并通过AwaitTxCommitted最多等待 3 个区块内交易提交最终断言expTXCommitted的期望值。接下来验证变更已生效exp[mytoken] 600_000 // update expected state raw cli.CustomQuery(q, bank, total-supply) for k, v : range exp { got : gjson.Get(raw, fmt.Sprintf(supply.#(denom%q).amount, k)).Int() assert.Equal(t, v, got, raw) } assert.Equal(t, int64(600_000), cli.QueryBalance(cli.GetKeyAddr(node0), mytoken))这里的cli.QueryBalance封装了simd q bank balance addr denom并用 gjson 提取balance.amount见 cli.go。此外框架还提供了FundAddress、QueryBalances、QueryTotalSupply、AddKey、AddKeyFromSeed、SubmitGovProposal、SubmitAndVoteGovProposal等高频辅助见 cli.go。测试越长可读性越难保持。建议在测试开头用注释描述意图例如// scenario: // given a chain with a custom token on genesis // when an amount is burned // then this is reflected in the total supply真实测试 staking_test.go 正是这种风格先写// Scenario:注释再依次执行重置、建账户、加 genesis 账户、启动链、委托、停链重启、断言、解委托、再断言。框架常用运行参数与端口布局测试运行器的全部 flag 定义在 test_runner.go参数默认值说明-chain-idtesting测试网 chain ID-wait-timeDefaultWaitTime默认 30s等待链事件的时间duration-nodes-count4集群节点数量-block-time3000ms期望的出块时间-binarysimd服务端/客户端使用的可执行二进制-bech32cosmos地址使用的 bech32 前缀-verbosefalse是否输出详细日志多节点测试网的端口按 n 个节点递增布局见 tests/systemtests/README.md 与 system.go26657-26657nRPC1317-1317nAPI9090-9090ngRPC16656-16656nP2P例如节点 3 的 RPC 端口为26660。测试网初始化默认走simd testnet init-files --single-host见 testnet_init.go并设置min-gas-price为0.000001stake、块最大 gas 为MaxGas 10_000_000见 system.go。测试策略上系统测试覆盖 CLI 与运行中多节点网络的完整链路比单元/集成测试更耗时因此框架聚焦关键路径而非穷举所有分支见 tools/systemtests/README.md。至此你已经掌握了 cosmos-sdk 系统测试的完整闭环准备二进制 → 编写查询测试 → 用 gjson 断言 JSON → 通过 genesis 定制初始状态 → 通过真实交易驱动状态变化并验证。这套流程同样适用于编写升级、质押、节点服务等更复杂的黑盒场景可参考 tests/systemtests 下已有的测试文件。赞分享区块链【免费下载链接】cosmos-sdkFramework for building performant, customizable blockchains with native interoperability项目地址https://gitcode.com/gh_mirrors/co/cosmos-sdk点击查看免费下载相关推荐Anteon性能测试断言系统响应状态码与JSON字段验证实战Anteon性能测试断言系统响应状态码与JSON字段验证实战 在现代Web应用开发中性能测试不仅需要关注系统的吞吐量和响应时间更需要确保每个请求的响应都符性能测试可观测性云原生BAML SDK 端到端测试体系用 cargo nextest 驱动多语言 SDK 生成、验证与门控BAML SDK 端到端测试体系用 cargo nextest 驱动多语言 SDK 生成、验证与门控 BAML 是一种面向 Agent 的编程语言用户可以用编程语言AI Agent编译器CLI人工智能深入 exa 的 xtests 集成测试体系从 Specsheet 配置、测试文件系统生成到输出断言深入 exa 的 xtests 集成测试体系从 Specsheet 配置、测试文件系统生成到输出断言 本文以 exaA modern replacement开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

GitHub Trending日榜怎么读?从排名机制到项目过滤实战指南

GitHub Trending日榜怎么读?从排名机制到项目过滤实战指南

每天打开一遍 GitHub Trending 已经成了我的固定动作,尤其在 2026-10-05 这天,榜单上的项目更替速度比平时快了不少。有人会觉得日榜就是“谁涨星星快谁就上”,真按这个思路去刷,大概率只是看个热闹。这篇想聊的,不光是…

📅 2026/10/11 20:07:02
用Kiro-account-manager搭建Claude兼容API网关:Kiro多账号反代完整教程

用Kiro-account-manager搭建Claude兼容API网关:Kiro多账号反代完整教程

【免费下载链接】Kiro-account-manager 项目地址: https://gitcode.com/gh_mirrors/kir/Kiro-account-manager 点击查看 免费下载 Kiro-account-manager 是一款开源的 Kiro 多账号管理工具,内置 API 反代服务,可以把多个 Kiro 账号聚合成一个…

📅 2026/10/11 20:07:02
大模型推理集群化调度:负载均衡与异常容错体系实战

大模型推理集群化调度:负载均衡与异常容错体系实战

商用大模型服务上线之前,我一直觉得集群化调度是个“大厂才需要操心的奢侈品”。直到某次线上压测,一台装了两张卡的推理节点在QPS冲到20以后直接OOM,紧接着网关把所有重试流量打到了另一台节点,不到两分钟整条链路雪崩&#xff0…

📅 2026/10/11 20:07:02
MORE NEWS

更多资讯

📰

遥感电力塔检测:10000张图三格式标签实战指南

简介:本资源是面向计算机视觉初学者与遥感图像分析实践者的YOLO电力塔目标检测专项数据集,解决遥感场景下小目标、密集目标检测的数据匮乏与标注格式适配难题。资源包含10000张真实遥感影像及高质量人工标注,提供VOC(XML&#xff…

📰

YOLOv8深基坑变形监测:毫米级位移校准与边缘部署实战

简介:本资源是一套面向计算机、人工智能及相关专业在校学生与初学者的毕业设计级项目,聚焦工地深基坑变形智能监测场景,基于YOLOv8目标检测框架实现高精度位移与形变识别。项目开箱即用,涵盖模型训练、视频实时检测、结果可视化全…

📰

Spark信用卡评分卡分析:从特征工程到WOE与分数映射

简介:这是一份基于Spark的信用卡评分数据分析课程设计资源,面向大数据或数据分析方向的高校学生与入门开发者,适合需要完成类似课程设计或想了解Spark数据处理流程的学习者。资源以和鲸社区信用卡评分模型构建数据为数据集,使用Py…

📰

从自建数据集到部署排查:打电话/抽烟检测的VOC与YOLO全流程实践

简介:这是一份用于目标检测项目的数据集,覆盖打电话与抽烟两类行为,共2037张真实场景图片。图片来自日常驾驶/监控视角,适合训练YOLO系列检测模型,也可用于安全驾驶、作业监管、公共场所违规行为识别等实际业务。每张图…

📰

哈工大通信复试不考专业题?真正在考什么

简介:本资源是哈尔滨工业大学通信专业考研复试面试的高频问题精编汇总,专为冲刺哈工大通信方向的考生设计,聚焦近三年真实面试场景中反复出现的基础理论与综合素养考察点。内容覆盖抽样定理、调制方式(FM/AM/PM)、基带…

📰

PHP开源工单系统FeelDesk全解析:部署、模板定制与二次开发

简介:一套面向中小团队、工单流程不复杂企业的轻量级开源工单系统源码。基于PHP构建,前端配合JavaScript与HTML/CSS模板,支持工单字段、状态自定义以及路由规则配置,适合需要快速部署、按业务调整工单流程的PHP开发人员。压缩包共…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬