TiDB Lightning 集成测试指南:从环境准备到测试用例编写(lightning/tests)
【免费下载链接】tidbTiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vector search. No data silos. No noisy neighbors. No infrastructure ceiling.项目地址: https://gitcode.com/GitHub_Trending/ti/tidb
导读
本文基于 TiDB 仓库中 lightning/tests/README.md 编写,系统讲解 TiDB Lightning 集成测试套件的完整知识:如何准备依赖集群二进制、如何构建被测程序、如何运行全部或部分测试用例、以及如何编写一个全新的lightning_*测试用例。读完本文,你将掌握这套依赖真实 TiDB/TiKV/PD/TiFlash 外部进程的集成测试体系的运行机制与扩展方法,并能借助仓库中的测试工具函数快速开发自己的集成测试。
TiDB Lightning 是 TiDB 生态中的高速数据导入工具(其主体代码位于 pkg/lightning),本套集成测试则从“端到端”视角验证其真实导入行为——因此它要求先拉起一整套 TiDB 集群。
一、测试体系总览:什么是 lightning 集成测试
lightning/tests目录下存放的全部依赖外部进程(如 TiDB、TiKV、PD、TiFlash)的测试,它们与不依赖外部进程的单元测试(*_test.go)区分开:集成测试用真实的集群环境验证 TiDB Lightning 在导入 CSV、SQL、Parquet 等数据源时的完整行为,覆盖从配置解析、数据导入、重复数据处理、到日志输出与错误处理的方方面面。
从目录结构看,每个测试用例是lightning/tests/TEST_NAME/下的一个子目录,核心文件包括:
run.sh:用例的执行脚本,是判定一个用例是否存在的标志;config.toml:该用例专用的 TiDB Lightning 配置;data/:导入用的数据文件(如 CSV、SQL);- 可选的 SQL 断言脚本等辅助文件。
从 lightning/tests/run.sh 的代码可以看到,整个测试框架的运行骨架是:
source $UTILS_DIR/run_services # 引入服务启动/停止工具 generate_certs &> /dev/null # 生成 TLS 证书 start_services $@ # 启动 PD / TiKV ×3 / TiDB / TiFlash run_case "$casename" "$script" # 逐个执行选中的用例脚本 trap stop_services EXIT # 退出时统一清理也就是说,无论你运行全部还是单个用例,框架都会先拉起一整套集群,再依次执行用例脚本。
二、运行前的环境准备
2.1 准备集群二进制文件
以下可执行文件必须被复制或软链接到仓库根目录下的bin/目录中:
| 可执行文件 | 用途 | 是否必须 |
|---|---|---|
bin/tidb-server | TiDB 计算节点 | 必须 |
bin/tikv-server | TiKV 存储节点 | 必须 |
bin/pd-server | PD 调度中心 | 必须 |
bin/tiflash | TiFlash 列存节点 | 必须 |
bin/minio | 对象存储模拟服务(S3 兼容) | 仅部分用例 |
bin/mc | MinIO 客户端工具 | 仅部分用例 |
版本要求:二进制版本必须 ≥ 2.1.0。其中minio/mc仅lightning_gcs、lightning_s3等涉及对象存储的用例需要,可到官方站点下载,不需要时可跳过。
官方推荐的二进制获取方式是通过tiup安装对应版本的 TiDB 集群组件,再链接到bin目录:
cluster_version=v8.1.0 # 换成你需要的版本 tiup install tidb:$cluster_version tikv:$cluster_version pd:$cluster_version tiflash:$cluster_version ln -s ~/.tiup/components/tidb/$cluster_version/tidb-server bin/tidb-server ln -s ~/.tiup/components/tikv/$cluster_version/tikv-server bin/tikv-server ln -s ~/.tiup/components/pd/$cluster_version/pd-server bin/pd-server ln -s ~/.tiup/components/tiflash/$cluster_version/tiflash/tiflash bin/tiflash2.2 构建被测程序
运行集成测试前需要先构建 TiDB Lightning 的测试二进制:
make build_for_lightning_integration_test如果你的测试用例依赖最新的 TiDB server 行为,还需要执行make server构建最新的 TiDB server。
2.3 安装主机依赖程序
测试运行主机上必须安装以下命令行工具:
mysql(MySQL CLI 客户端,用于执行 SQL 断言)curl(健康检查与 API 调用)openssl(TLS 证书生成)wgetlsof(端口/进程检查)
这些工具被测试框架的辅助脚本直接调用。例如run_sql使用mysql -uroot -h127.0.0.1 -P4000 ... -E -e "$SQL"连接 TiDB 并输出结果,run_services使用lsof -n -P -i :2379 ...检查端口占用情况。
2.4 目录权限要求
执行测试的用户必须拥有创建/tmp/lightning_test目录的权限——所有测试产物(日志、SQL 结果、集群数据、证书等)都会写入该目录。测试框架在每次运行时都会重置该目录:
rm -rf $TEST_DIR && mkdir -p $TEST_DIR三、运行测试:全量、子集与调试模式
3.1 运行全部测试
执行 make 目标即可运行所有集成测试:
make lightning_integration_test- 日志会写入
/tmp/lightning_test目录。
从 lightning/tests/run.sh 可以看到,当不指定TEST_NAME环境变量时,框架会通过find tests -mindepth 2 -maxdepth 2 -name run.sh自动发现所有包含run.sh的用例目录并按字典序执行,每个用例以run_case "$casename" "$script"的方式在隔离的环境变量(TEST_DIR、PD_ADDR、TIDB_ADDR、TIKV_ADDR等)下运行。
3.2 运行部分测试
只运行指定用例时,用空格分隔的用例名列表作为TEST_NAME:
TEST_NAME="lightning_gcs lightning_view" lightning/tests/run.sh3.3 调试模式
tests/run.sh --debug--debug模式下,框架在所有服务器启动完成后立即暂停,输出提示信息并等待你按回车继续:
if [ "${1-}" = '--debug' ]; then echo 'You may now debug from another terminal. Press [ENTER] to continue.' read line fi你可以在另一个终端连接/tmp/lightning_test下的日志或直接访问 TiDB(127.0.0.1:4000)进行人工排查,这非常适合定位用例失败原因。
3.4 集群服务的启动细节
框架通过 tests/_utils/run_services 完成集群编排,关键行为如下:
- 默认地址约定:PD 监听
127.0.0.1:2379(peer 端口2380),TiDB 监听4000(状态端口10080),3 个 TiKV 分别监听20161/20162/20163(状态端口20181/20182/20183),TiFlash HTTP 端口20292; - 启动顺序:
start_pd→ 依次start_tikv→ensure_tikv(等待集群初始化)→start_tidb→start_tiflash,每个服务启动后都会通过 HTTP/HTTPS 健康检查轮询确认就绪; - 启动参数:服务使用 lightning/tests/config 下的 TOML 配置(
pd.toml、tikv.toml、tidb.toml),也支持通过--tidb-cfg <file>、--no-tiflash、--no-tidb等参数覆盖; - 失败重试:
start_services最多重试 3 次,每次失败后等待 30/60/90 秒再尝试,避免资源抢占导致的偶发失败; - TLS 默认开启:服务间默认使用 HTTPS,证书由
generate_certs基于 openssl 现场生成到/tmp/lightning_test/certs/(CA 有效期 2 天,节点证书有效期 1 天),因此测试环境中curl、mysql等客户端调用均带有--ssl-ca/--ssl-cert/--ssl-key参数。
此外,框架还会通过 PD API 读取当前集群版本号并写入$TEST_DIR/cluster_version.txt,供用例脚本判断“当前集群是否满足某个特性的版本要求”。
四、编写新的集成测试用例
4.1 用例的基本形态
在
lightning/tests/下新建目录tests/TEST_NAME/,其中:TEST_NAME必须以lightning_开头;- 用例主体是 shell 脚本
run.sh; - 用例失败时脚本必须以非零退出码退出(框架依赖退出码判断用例成功与否,
run_case中bash "$script" && echo "*===== TEST: [$case] success! =====*")。
将
TEST_NAME加入 run_group_lightning_tests.sh 中已有的分组(推荐),或为它新建一个分组。如果新建了分组,新组名必须同步加入 CI 的
lightning-integration-test流水线(见run_group_lightning_tests.sh头部注释中引用的pull_lightning_integration_test.groovy),否则该组用例不会在 CI 中被执行。
4.2 用例分组的并行机制
lightning/tests/run_group_lightning_tests.sh 将全部用例划分为G00~G08共 9 个分组以支持并行执行,例如:
G00:lightning_auto_random_default lightning_bom_file lightning_character_sets lightning_check_partial_imported lightning_checkpoint ...(checkpoint 系列)G01:lightning_checkpoint_engines lightning_checkpoint_engines_order ... lightning_compress lightning_concurrent-restoreG02:lightning_config_max_error lightning_config_skip_csv_header lightning_csv ... lightning_duplicate_detection*(CSV 与重复检测系列)G03/G04:lightning_duplicate_resolution_*(重复数据解析系列)G05:lightning_fail_fast* lightning_file_routing lightning_foreign_key lightning_gcs ...G06:lightning_multi_valued_index lightning_new_collation lightning_no_schema lightning_parquet ... lightning_s3G07:lightning_shard_rowid lightning_source_linkfile lightning_sqlmode lightning_tidb_duplicate_data ...G08:lightning_pd_leader_switch lightning_tool_* lightning_ttl lightning_unused_config_keys lightning_various_types lightning_view* lightning_write_* ...
分组原则是让每组耗时尽量均衡,从而压缩 CI 整体等待时间:把多个轻量用例放在一组、重量级用例单独成组。脚本还提供了一个“兜底检查”:任何未加入分组但以lightning_开头的用例,在执行others组时会报错提示补录,避免用例被遗漏。
4.3 便捷测试工具函数
测试框架在 tests/_utils 中提供了一组开箱即用的 shell 函数,每个用例脚本都可以直接调用:
| 函数 | 作用 | 实现要点 |
|---|---|---|
run_sql <SQL> | 在 TiDB 上执行 SQL 查询 | 通过mysql -uroot -h127.0.0.1 -P4000 ... -E -e "$SQL"执行,结果同时写入$TEST_DIR/sql_res.$TEST_NAME.txt |
run_lightning [CONFIG] | 使用tests/TEST_NAME/CONFIG.toml启动tidb-lightning | 运行tidb-lightning.test,携带 TLS 证书、--tidb-port 4000、--pd-urls 127.0.0.1:2379、-d data、--sorted-kv-dir、--enable-checkpoint=0等固定参数,并生成覆盖率文件 |
check_contains <TEXT> | 断言上一条run_sql结果包含指定文本 | 对sql_res.$TEST_NAME.txt做grep -F(固定字符串匹配);可传第二参数指定结果文件 |
check_not_contains <TEXT> | 断言上一条run_sql结果不包含指定文本 | 逻辑与上相反 |
check_lightning_log_contains <TEXT> | 断言当前 lightning 日志包含指定文本 | 对$TEST_DIR/lightning.log做grep -F;可传第二参数指定日志文件 |
以run_sql+check_contains为例,一个典型的断言片段是:
run_sql "SELECT COUNT(*) AS cnt FROM db.tbl;" check_contains "cnt: 100"由于run_sql使用mysql -E(垂直输出)格式,check_contains中的断言文本通常写作列名: 值的形式。所有检查函数在断言失败时都会打印完整结果/日志内容并以非零码退出,从而让用例失败信息一目了然。
run_lightning的实现还揭示了测试二进制的一个细节:它执行的是tidb-lightning.test(带测试覆盖率收集的二进制),并通过-test.coverprofile="$COV_DIR/cov.$TEST_NAME.$$.out"把每个用例的覆盖率单独落盘,支持后续的覆盖率聚合统计。
其他辅助函数还包括:run_sql_file(执行 SQL 文件)、run_curl(HTTPS API 调用)、check_cluster_version <major> <minor> <revision>(集群版本门控,不满足要求时跳过用例)、generate_certs(TLS 证书生成)、make_tiflash_config(生成 TiFlash 配置)等。
4.4 版本门控:让用例适配不同集群版本
check_cluster_version允许用例声明自身的最低集群版本要求:
check_cluster_version 5 0 0 "my_feature" || exit 0其实现读取框架注入的CLUSTER_VERSION_MAJOR/MINOR/REVISION环境变量(来源见run.sh中对 PD/pd/api/v1/version的解析),当当前集群版本低于要求时打印 "Skipping test" 并以码 1 退出——用例脚本配合|| exit 0即可优雅跳过。
五、从仓库中的真实用例看编写范式
仓库中大量真实用例可以当作模板参考,例如 lightning_character_sets、lightning_duplicate_detection、lightning_parquet 等。它们共同遵循的范式是:
- 在
config.toml中声明本次导入的[mydumper](数据源目录)、[tidb](目标库连接)、[tikv-importer](后端模式)等关键配置; - 在
data/下放置 CSV/SQL 数据文件(文件名遵循db.table.csv或db.table.sql约定,TiDB Lightning 据此推断目标库表); - 在
run.sh中依次执行:#!/bin/bash set -eu run_lightning # 执行导入 run_sql "SELECT * FROM db.tbl;" check_contains "期望值" check_lightning_log_contains "期望日志" - 以非零码退出即代表失败,由框架捕获并报告。
编写完用例后,先单跑验证:
TEST_NAME="lightning_my_case" lightning/tests/run.sh确认通过后,再加入run_group_lightning_tests.sh的对应分组,便完成了从编写到接入 CI 的全流程。
六、常见问题与排查思路
Failed to start services:优先检查bin/下二进制是否存在且版本 ≥ 2.1.0、/tmp/lightning_test是否可写;框架自带最多 3 次重试,可结合/tmp/lightning_test/*.log(pd.log、tikv*.log、tidb.log)定位具体失败服务。- 用例失败但原因不明:使用
tests/run.sh --debug在集群就绪后暂停,手动连接 TiDB(mysql -h127.0.0.1 -P4000 -uroot)或查看$TEST_DIR/lightning.log排查。 check_contains意外失败:注意断言的是mysql -E垂直输出格式下的文本(如cnt: 100),并确认run_sql与check_contains之间的$TEST_NAME环境变量一致(结果文件按$TEST_NAME隔离)。- 用例未被执行:确认目录名以
lightning_开头且存在run.sh;全量运行依赖find发现机制,漏写run.sh的用例不会被发现。 - 依赖对象存储的用例失败:
lightning_gcs、lightning_s3等需要minio/mc二进制就位,且运行环境需能访问对应服务端口。
七、总结
TiDB Lightning 集成测试是一套“真实集群 + 真实导入”的端到端验证体系,其设计可以概括为三点:
- 环境确定性:统一约定端口、配置与
/tmp/lightning_test产物目录,通过 TLS 证书与版本门控保证不同环境下的行为一致; - 用例隔离性:每个
lightning_*用例是自包含的run.sh+config.toml+data/组合,通过TEST_NAME与独立日志/结果文件实现互不干扰,并支持分组并行以压缩 CI 时间; - 断言友好性:
run_sql/check_contains/check_lightning_log_contains等工具函数让用例脚本可以用极少的代码完成“执行 SQL → 校验结果 → 校验日志”的闭环。
掌握这套体系后,你既可以运行与调试存量用例,也可以按照lightning_前缀约定快速新增覆盖新特性的集成测试。相关入口文件汇总:
- 测试总说明:lightning/tests/README.md
- 用例调度入口:lightning/tests/run.sh
- 分组并行脚本:lightning/tests/run_group_lightning_tests.sh
- 服务编排与工具函数:tests/_utils/run_services、tests/_utils/run_lightning、tests/_utils/run_sql、tests/_utils/check_contains、tests/_utils/check_not_contains、tests/_utils/check_lightning_log_contains、tests/_utils/check_cluster_version
- 集群配置样例:lightning/tests/config
【免费下载链接】tidbTiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vector search. No data silos. No noisy neighbors. No infrastructure ceiling.项目地址: https://gitcode.com/GitHub_Trending/ti/tidb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考