TiDB 集成测试录制工作流:tests/integrationtest 的 .test/.result 最小化录制实践
本文围绕 TiDB 仓库中 Agent 技能文档 .agents/skills/tidb-integrationtest-recorder/SKILL.md 展开,讲清 tests/integrationtest 集成测试套件的“录制(record)- 复核(review)- 最小化 diff”完整工作流:如何从 t/ 目录下的用例路径推导 TestName、如何用 ./run-tests.sh -r 精准再生 .result 文件、以及为什么必须避免无关 result churn。读完你可以独立完成 TiDB 集成测试的录制、校验与结果文件治理,理解底层 mysql-tester 的启用/禁用新 collation 双跑机制与数据竞争检查逻辑。
技能定位与适用场景
该技能文档以 Agent 技能(skill)的形式定义了一套操作规范,其核心声明如下:
- 适用场景:当修改位于
tests/integrationtest/t/**下的集成测试用例,或需要为 SQL 行为补充集成测试覆盖时,使用本工作流。 - 明确禁忌:对该套件不要使用 Go 测试的
-record标志(-record仅属于那些显式支持的测试套件,这一点在 docs/agents/testing-flow.md 的单元测试一节中被再次强调:Use -record only for test suites that explicitly support it.)。 - 权威出处:规范命令细节不写在技能文件里,而是统一指向 docs/agents/testing-flow.md 中的
Integration tests (/tests/integrationtest)小节。技能文件只保留“指路 + 流程约束”,长命令块集中维护在 playbook 中,避免命令细节在多处重复后产生漂移——这一设计原则在 docs/agents/testing-flow.md 开头即有说明:“skills under.agents/skills/should point here rather than duplicating long command blocks”。
该技能也是仓库级技能清单中的一员,.agents/skills/README.md 将其列为九个运维工作流技能之一(tidb-integrationtest-recorder: run and review tests/integrationtest recording flow),与 tidb-verify-profile、tidb-failpoint-test-runner、tidb-realtikv-runner 等技能共同构成 TiDB 的 Agent 测试纪律体系。
集成测试套件的目录结构
理解录制工作流之前,先明确 tests/integrationtest 的布局(来源:tests/integrationtest/README.md 的 “How It Works” 一节与 tests/integrationtest/run-tests.sh 脚本默认值):
| 路径 | 角色 |
|---|---|
tests/integrationtest/t/ |
测试输入:.test 文件定义 SQL 用例,可含 ## 行内注释说明(如 t/planner/core/binary_plan.test 中为每段 base64 输入附带的注释) |
tests/integrationtest/r/ |
期望结果:与 .test 同路径的 .result 文件,执行后与之逐字比对 |
tests/integrationtest/s/(由 s.zip 解压得到) |
统计信息:s/*.json 在测试运行前装载,保证 planner 相关结果稳定可复现 |
tests/integrationtest/config.toml |
默认服务端配置,开启新 collation、table lock、新字符集等 |
tests/integrationtest/disable_new_collation.toml |
禁用新 collation 时的替代配置 |
从 run-tests.sh 的默认变量可确认脚本行为:stats="s"、mysql_tester_log="./integration-test.out",脚本在每次运行时通过 unzip -qq s.zip 重新解压统计目录,保证统计基线一致。
run-tests.sh 还导出了 TZ="Asia/Shanghai"(注释写明 “make tests stable time zone wise”),即结果比对对时区敏感的用例依赖这一固定时区,本地调试环境应保持默认。
TestName 推导规则
技能工作流的第 2 步给出了录制命令的关键输入:
Derive
TestNamefrom the path undertests/integrationtest/t/without the.testsuffix (example:planner/core/binary_plan).
docs/agents/testing-flow.md 中给出了完全一致的映射示例:
Mapping example: if you modify
t/planner/core/binary_plan.test, thenTestNameisplanner/core/binary_plan.
也就是说,TestName 就是 .test 文件相对 t/ 的目录路径(保留子目录层级、去掉扩展名),目录结构在 t/ 与 r/ 之间一一对应。仓库中可以直接验证这一点:输入文件 tests/integrationtest/t/planner/core/binary_plan.test 与期望结果文件 tests/integrationtest/r/planner/core/binary_plan.result 位于镜像路径上。
用例的粒度决定了录制的粒度:例如 t/ 顶层散布着 explain.test、index_merge.test、cte.test 等单文件用例,而 t/planner/core/、t/executor/、t/ddl/ 等子目录承载成套用例。录制时只指定受影响的 TestName,这正是下一节“定向录制”要求的直接原因。
录制命令:定向记录受影响的套件
docs/agents/testing-flow.md 的 Integration tests 小节是权威命令出处:
pushd tests/integrationtest
./run-tests.sh -r <TestName>
popd
结合 tests/integrationtest/README.md 的 Script Options 与 run-tests.sh 的 getopts 解析逻辑,完整参数语义如下:
-r <test-name>|all:运行t/<test-name>.test并将执行结果录制回r/<test-name>.result。指定all表示运行全部用例并整体重录——这正是技能 Guardrails 中“Prefer targeted recording of the affected suite only”要防止的做法,除非刻意做全量刷新,否则不要使用。-t <test-name>:仅运行不录制(提供-r时该选项被忽略,脚本中record_case分支优先于$tests分支)。回归验证时应使用-t。-d <y|Y|n|N|b|B>:控制测试期间新 collation 的启用状态。默认b(collation_opt=2):以collation为前缀的用例在启用/禁用两种状态下各跑一遍(因此r/下会出现collation_agg_func_enabled.result/collation_agg_func_disabled.result这类成对文件),其他用例仅以启用状态运行。y仅启用、n仅禁用。-s <tidb-server-path>:使用已有 tidb-server 二进制,跳过构建。-b <y|Y|n|N>:是否构建测试二进制,默认构建;提供-s时自动跳过。-P <port>:连接已在指定端口运行的 tidb-server,跳过本地构建与启停。
脚本在执行录制时的实际行为(见 run-tests.sh 的 run_mysql_tester 函数):
extract_stats解压s.zip得到统计基线;start_tidb_server启动服务——默认走unistore(-store unistore -path ''),只有设置了TIDB_TEST_STORE_NAME=tikv环境变量且提供TIKV_PATH时才走-store tikv -path ...;-d为禁用模式时改用disable_new_collation.toml配置;- 调用外部工具
mysql_tester(脚本用go install github.com/pingcap/mysql-tester/src@f2d90ea9522d30c9a8e8d70cc31c7f016ca2801f安装固定版本),录制模式即追加--record <case>参数,并始终带--check-error=true与--collation-disable=<true|false>; - 结束后
kill -15等待服务退出,并在 unistore 场景下check_data_race:grep 服务日志中的DATA RACE,命中则整轮测试判失败并打印日志。
技能工作流的第 1 步与 AGENTS.md 的 Validation Matrix 相互印证:tests/integrationtest/t/** 发生变更时的最小验证动作正是 “Record and verify regenerated result correctness (see docs/agents/testing-flow.md -> Integration tests)”。
结果文件复核:把 diff 压到最小
技能工作流的第 3 步是“Review changed files in tests/integrationtest/r/** and keep result diffs minimal”,配合 docs/agents/testing-flow.md 的补充说明:
Review changed files in
tests/integrationtest/rand confirm each diff matches expected behavior. Result files usually do not need manual edits; if edits are necessary, keep them minimal and verify correctness before reporting.
落地成可操作清单:
- 录制完成后,用
git diff tests/integrationtest/r/审视全部被重写的结果文件; - 逐行确认每一处变化都能对应到你本次改动应当引起的行为差异(计划节点、类型推断、报错文案等)。任何无法解释的变化都说明录制范围过大或环境不一致(例如统计信息、时区、collation 状态变化);
- 结果文件通常不需要人工编辑。README 指出
.result是从执行结果“再生”出来的(To generate new .result and .json files from execution, use the -r parameter);若确需手工修正某一行,修改必须最小化,并再跑一次(用-t <TestName>只跑不录制的验证模式)确认通过后才可报告。
技能 Guardrails 的三条规则与上述流程一一对应:
- Prefer targeted recording of the affected suite only:只录受影响的
TestName,避免-r all把无关用例一并重写; - Avoid unrelated result churn:
r/下数百个结果文件之间是“零漂移”基线,一次 PR 只应触碰与改动相关的文件; - If result files need manual edits, keep them minimal and verify with another run:手工编辑后必须二次验证。
进阶:next-gen 运行器与真实 TiKV 集群
tests/integrationtest/README.md 还记录了第二套运行入口:./run-tests-next-gen.sh [run-tests.sh options],它“sets up a real cluster environment and then invokes run-tests.sh with your provided options”。
从 tests/integrationtest/run-tests-next-gen.sh 源码可见其机制:设置 TIDB_TEST_STORE_NAME=tikv 与 TIKV_PATH=127.0.0.1:2379 后,委托 tests/realtikvtest/scripts/next-gen/bootstrap-test-with-cluster.sh ./run-tests.sh "$@" 启动一个本地 3 PD + 3 TiKV + 1 TiKV-worker + MinIO 的 next-gen 集群(脚本头部注释列出了所需 TCP 端口:pd 2379/2380/2381/2383/2384、tikv 20160-20162/20180-20182、tikv-worker 19000),随后以 NEXT_GEN=1 调用 run-tests.sh。NEXT_GEN 环境变量在 run-tests.sh 的 start_tidb_server 中会被追加 -keyspace-name SYSTEM --tidb-service-scope dxf_service 启动参数。
因此录制/复核流程本身不变,只是后端从 unistore 换成了真实 TiKV:同样用 -r <TestName> 定向录制,同样要复核 r/ 下最小 diff;但要注意 next-gen 集群占用固定端口,且 docs/agents/testing-flow.md 的 RealTiKV 一节对真实集群的启动/清理纪律(启动、探活、测试、强制清理、端口不可达检查)仍应遵守。
回归验证与日常开发流程
技能文档聚焦“录制”,而录制的目的始终是让回归验证可信。tests/integrationtest/README.md 的 Typical Workflows 给出日常路径:
- 代码变更后的回归:
make dev或make integrationtest(构建并跑全量集成测试,用于发现计划变化); - 新增/更新用例:在
t/添加.test文件(或向既有文件追加查询)→./run-tests.sh -r <casename>生成期望结果 → 提交t/与r/两侧改动。
与本文主题直接相关的收尾纪律来自 docs/agents/testing-flow.md 的 “Related guidance” 一节:准备 PR 更新时,要把精确的测试命令写进 PR 描述(Tests 段),并遵循 AGENTS.md 的 Quick Decision Matrix 做回归政策判断。
小结
TiDB 集成测试录制工作流可以浓缩为四步:推导 TestName(t/ 相对路径去 .test)→ ./run-tests.sh -r <TestName> 定向录制 → 复核 r/ 下的 diff 是否每处变化都有预期行为解释 → 若手工编辑过结果文件则用只跑不录的模式二次验证。该流程的价值在于把“结果文件再生”约束在最小范围,使 tests/integrationtest/r/ 这一庞大回归基线始终保持干净、可审计;而底层脚本固定时区、固定统计基线(s.zip)、collation 双跑与数据竞争检查,共同保证了录制结果的确定性。技能文件刻意保持简短、把命令细节集中于 docs/agents/testing-flow.md,是 TiDB 面向 Agent 协作的文档分层(AGENTS.md 管策略、testing-flow.md 管命令、skills 管流程约束)的一个典型样本。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00