ClickHouse 集成测试完全指南:从本地复现 CI 作业到分布式故障注入调试

发布时间:2026/9/20 6:17:46
ClickHouse 集成测试完全指南:从本地复现 CI 作业到分布式故障注入调试 数据库OLAP列式数据库大数据实时分析数据分析【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址https://gitcode.com/GitHub_Trending/cli/ClickHouse点击查看免费下载导读集成测试是 ClickHouse 保证分布式行为健壮性与外部系统兼容性的关键防线。本文基于仓库内 tests/integration/README.md 展开完整讲解如何在本地用ci.praktika一键复现 CI 集成测试作业、如何原生运行 pytest 集成测试、如何新增测试用例、如何结合pdb与nnd调试器进行故障排查。读完本文你将掌握一套可在个人开发机上直接运行的分布式测试方法论并能对照 helpers 源码理解容器编排、网络故障注入与 TSV 结果比对的底层实现。集成测试目录能做什么tests/integration/目录下存放的是 ClickHouse 的集成测试Integration Tests与单元测试不同它们涉及多实例部署、自定义配置、ZooKeeper/Keeper 协调服务以及与外部系统MySQL、PostgreSQL、Kafka、MinIO、S3、Redis、MongoDB、HDFS 等的互操作。其目的是在接近真实生产的环境里验证多副本、多分片集群的复制、分片、分布式 DDL 行为Keeper/ZooKeeper 协调下的故障切换与数据一致性备份恢复test_backup_restore_*、字典test_dictionaries_*、磁盘类型test_merge_tree_azure_blob_storage等高级特性与外部生态系统的兼容性test_kafka_*、test_mysql_*、test_iceberg_*等。从目录命名即可窥见覆盖面目前仓库中已有test_backup_restore、test_keeper_*数十个与 Keeper 相关的用例、test_distributed_*、test_lightweight_updates等数百个测试模块。每个test_name/目录都是一个独立的测试用例模块包含test.py与可选的配置文件。方式一以 CI 作业的方式本地复现推荐CI 上运行的集成测试会切分成多个 batch 作业如Integration tests (amd_binary, 4/5)。仓库提供了ci.praktika这一与 CI 完全一致的任务编排框架让你在本地获得与 CI 报告一一对应的复现能力。前置条件运行前只需三样东西Python 3仅依赖标准库无需额外安装 pytest 等DockerClickHouse server 二进制运行器按以下顺序搜索并取第一个命中的路径./ci/tmp/clickhouse./build/programs/clickhouse./clickhouse也就是说只要把构建产物放到上述任一位置即可直接复用 CI 的编排逻辑。运行一个 CI 作业python -m ci.praktika run JOB_NAME⚠️ 作业名必须原样引用CI 报告中的名称可能包含空格和逗号例如python -m ci.praktika run Integration tests (amd_asan, 1/5)作业名的格式隐含了构建类型与 batch 信息如amd_binary表示 amd64 二进制构建1/5表示第 1 个 batchci.praktika会根据它选择正确的测试配置。在作业内运行指定测试python -m ci.praktika run Integration tests (amd_binary, 4/5) \ --test test_named_collections使用--test时作业名里的 batch 序号如4/5在本地已无意义——但作业名本身必须匹配一个真实存在的 CI 作业以选中正确的配置。可以一次传入多个测试选择器python -m ci.praktika run Integration tests (amd_binary, 4/5) \ --test test_named_collections/test.py::test_default_access test_multiple_disks选择器支持到具体的测试函数级别test_named_collections/test.py::test_default_access也支持直接给测试目录名test_multiple_disks。使用integration别名简化本地运行本地调试时batch 序号与构建风味build flavor并非必需可以改用别名integrationpython -m ci.praktika run integration --test selectors此时ci.praktika会自动为单个测试挑选合适的作业配置。需要注意的是使用旧 analyzer 或分布式计划distributed plan的作业仍然要求填写完整、精确的 CI 作业名——这类测试的行为依赖特定的开关组合不能由别名推断。其它自定义选项选项作用说明--count N每个测试重复 N 次对应向 pytest 传递--repeat-scopefunctionpytest-repeat常用于排查 flaky 测试--debug异常时进入 Python 调试控制台对应向 pytest 传递--pdb--path PATH自定义 ClickHouse server 二进制路径当二进制不在上述默认位置时使用--path_1 PATH自定义 server 配置目录默认是./programs/server/config/--workers N覆盖并行 pytest worker 数的自动计算底层透传给 pytest-xdist 的-n N资源紧张时调低CPU 核多时可调高--param KEYVALUE[,KEYVALUE...]注入自定义环境变量给 pytest逗号分隔的键值对如--param PYTEST_ADDOPTS-vv,CUSTOM_FLAG1--workers的实现与 CI 的并行策略相关ci/jobs/scripts/integration_tests_configs.py中的get_optimal_test_batch等逻辑负责在 CI 侧计算最优 batch 与并发度本地覆盖时需结合机器资源权衡。方式二原生运行无需 CI 框架如果你已经装好了完整依赖也可以直接使用pytest在本地跑集成测试适合快速迭代单条用例。前置条件Ubuntu 20.04 (Focal) 或更高版本DockerAPI 版本 ≥ 1.25可用docker version检查务必使用 官方文档 安装的最新 Docker不要使用系统软件源的版本pip与libpq-devsudo apt-get install python3-pip libpq-dev zlib1g-dev libcrypto-dev libssl-dev libkrb5-dev python3-dev openjdk-17-jdk requests urllib3pytest 测试框架sudo -H pip install pytestdocker compose 与测试所需的 Python 库sudo -H pip install \ PyMySQL avro cassandra-driver confluent-kafka dicttoxml docker grpcio grpcio-tools kafka-python kazoo minio lz4 protobuf psycopg2-binary pymongo pytz pytest pytest-timeout redis tzlocal2.1 urllib3 requests-kerberos dict2xml hypothesis pika nats-py pandas numpy jinja2 pytest-xdist2.4.0 pyspark azure-storage-blob delta paramiko psycopg pyarrow boto3 deltalake snappy pyiceberg python-snappy thrift pyhdfs说明这些库覆盖了各外部系统客户端Kafka、MySQL、MongoDB、Redis、MinIO、S3、Spark 等。注意 helpers/cluster.py 中对外部依赖采用惰性导入策略——特定测试专属的模块如psycopg2、pymongo、nats、cassandra只在导入失败时给出警告而不是阻塞整个测试套件这保证了大部分测试无需安装全部依赖即可运行。Spark 测试需要安装 Spark 并把其bin目录加入PATH详见ci/docker/integration/runner/Dockerfile并设置JAVA_PATH指向 Java 二进制路径以非特权用户运行将当前用户加入docker组并重新登录sudo usermod -aG docker $USER # 重新登录或重启机器 docker ps # 验证 Docker 访问权限运行测试的基本命令pytest tests_or_paths \ [-k expr] \ [-n numprocesses --distloadfile] \ [--count count --repeat-scopefunction]-n numprocesses并行进程数CI 对可并行测试用 4其它用 1。并行时建议配--distloadfile保证同一个文件内的测试落在同一个 worker 上见 pytest-xdist 文档--count count配合--repeat-scopefunction重复执行测试见 pytest-repeat-k expr按表达式过滤测试名称。相关默认行为可以在 tests/integration/pytest.ini 中看到python_files test_*/test*.py约束了测试文件的匹配规则session_timeout 7200、timeout 900提供了会话级与用例级的超时保护addopts默认排除标记为long_run和e2e的用例filterwarnings屏蔽了 Cassandra 驱动与 paramiko 库的已知弃用警告。通过环境变量覆盖路径默认情况下测试在仓库根目录查找 server 二进制、在./programs/server/查找配置。可用以下环境变量覆盖环境变量作用CLICKHOUSE_TESTS_SERVER_BIN_PATHClickHouse server 二进制路径CLICKHOUSE_TESTS_ODBC_BRIDGE_BIN_PATHclickhouse-odbc-bridge二进制路径CLICKHOUSE_TESTS_CLIENT_BIN_PATHClickHouse client 二进制路径CLICKHOUSE_TESTS_BASE_CONFIG_DIRconfig.xml与users.xml所在目录路径查找逻辑对应 helpers/cluster.py 中的find_default_config_path()它依次检查环境变量指定的目录、仓库内programs/server、以及/etc/clickhouse-server/找不到时抛出明确的错误提示。关于单独构建的说明如果使用分离构建ENABLE_CLICKHOUSE_ALLOFF需要显式开启并构建所有依赖组件例如 Keeper 相关测试需要ENABLE_CLICKHOUSE_KEEPERON。直接使用ENABLE_CLICKHOUSE_ALLON会更省事一次构建即可覆盖所有集成测试所需组件。新增一个集成测试新增测试非常简单遵循约定即可tests/integration/test_foo/ ├── __init__.py # 空文件标识这是一个 Python 包 └── test.py # 测试主体__init__.py必须是空文件test.py中所有以test开头的函数都会被 pytest 识别为测试用例。conftest.py 提供了三个全局 session 级 fixturepdb_history在--pdb模式下保存/恢复调试历史、tune_local_port_range把本地端口范围放宽到 55000–65535避免 HDFS、MinIO 等服务端口冲突导致的EADDRINUSE/EADDRNOTAVAIL、cleanup_environment测试开始前清理残留容器与 Docker 网络可通过PYTEST_CLEANUP_CONTAINERS1开启自动清理。helpers 工具箱tests/integration/helpers/目录是集成测试的公共设施核心模块包括cluster.py定义了ClickHouseCluster类helpers/cluster.py负责在 Docker 容器中启动 ClickHouse 集群带或不带 ZooKeeper/Keeper向实例发送查询模拟网络故障例如切断实例之间的链路。 常用方法包括add_instancecluster.py、startcluster.py、restart_instance_with_ip_changecluster.py以及stop_clickhousecluster.py等test_tools.py提供TSV结果比较工具与exec_query_with_retry重试封装network.py网络故障注入client.py查询客户端封装含Client类与QueryRuntimeExceptionexternal_sources.py 与 s3_tools.py外部系统与 S3 相关辅助设施。TSV 结果比较比较两个 TSV 结果时把内容包进TSV类再使用assertassert TSV(result) TSV(reference)失败时 pytest 会输出简洁的 diff。TSV类的实现helpers/test_tools.py接受文件句柄、字符串或列表三种输入内部按行strip后逐行比对并提供基于difflib.unified_diff的diff()方法生成可读差异。也就是说行首尾空白与空行不会影响比较结果这避免了分布式查询结果中常见的缩进干扰。使用 pdb 在断言处中断想在断言失败时停下来交互式调试直接加--pdb开关pytest --pdb tests and optionsconftest.py中的pdb_historyfixture 会在--pdb模式下自动保存/加载.pdb_history文件conftest.py让调试历史跨运行保留。调试模式附加底层调试器到容器内 server当需要调试 ClickHouse server 进程本身而非仅仅 Python 测试逻辑时可以使用调试模式把低级调试器附加到集成测试容器内部的 server 上。整体流程为放调试器 → 打 breakpoint → 通过 praktika 运行 → 触发 pdb → 用辅助脚本进容器查询/调试。步骤一放置静态链接调试器下载一个静态链接的调试器二进制推荐nnd仅支持 x86_64到仓库根目录curl -L -o nnd https://github.com/al13n321/nnd/releases/latest/download/nnd chmod x nnd步骤二在测试代码中打断点在测试的test.py中合适位置加入breakpoint()测试执行到此处会暂停。步骤三通过 praktika 运行指定测试用ci.praktika运行该测试交互式调试请使用真实 TTY例如python -m ci.praktika run integration --test test_foo --debug步骤四触发 pdb测试运行到breakpoint()时会进入 Python 的 pdb 提示符可以在这里查看 Python 侧状态。步骤五第二个终端进入容器另开一个终端source 辅助脚本并调用其提供的函数source /path/to/ClickHouse/tests/integration/runner-env.sh # USAGE: # runner-client - Run clickhouse client inside an integration test # runner-bash - Open shell on a node inside an integration test # runner-nnd - Attach nnd debugger to a clickhouse server on a node inside an integration test这三个函数定义在 runner-env.sh 中它们基于docker ps找到运行中的 praktika runner 容器与其中的节点容器然后通过嵌套docker exec进入目标节点。步骤六选择节点并查询用容器 ID 或名称连接节点辅助脚本会列出运行中的容器并给出默认值runner-client CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 867c67cc9957 clickhouse/integration-test:latest ... 2s ago Up 1s rootteststoragedelta-node1-1 ... Enter ClickHouse Node CONTAINER ID or NAME (default: 867c67cc9957):选定节点后即可直接查询node1 :) SELECT 1; ┌─1─┐ │ 1 │ └───┘runner-nnd会找到节点内的clickhouse server进程 PID并把nnd附加到该进程调试输出写到容器的/debug目录从而在 server 崩溃或卡死时获取底层堆栈信息。常见问题排查Troubleshooting莫名失败先重置 Docker如果测试以莫名其妙的方式失败可能是历史残留容器或镜像数据损坏重置 Docker 存储sudo service docker stop sudo bash -c rm -rf /var/lib/docker/* sudo service docker startiptables-nft 问题在 Ubuntu 20.10 的 host 网络模式下嵌套容器可能因 legacy/nftables 规则同步问题而互不可见修复方式sudo iptables -P FORWARD ACCEPT网络慢预下载所有依赖镜像为了提前下载全部依赖可设置以下环境变量后统一拉取所有 compose 文件引用的镜像export KERBERIZED_KAFKA_DIR/tmp export KERBERIZED_KAFKA_EXTERNAL_PORT8080 export MYSQL_ROOT_HOST% export MYSQL_DOCKER_USERroot export KERBEROS_KDC_DIR/tmp export AZURITE_PORT10000 export KAFKA_EXTERNAL_PORT8080 export SCHEMA_REGISTRY_EXTERNAL_PORT8080 export SCHEMA_REGISTRY_AUTH_EXTERNAL_PORT8080 export NGINX_EXTERNAL_PORT8080 export COREDNS_CONFIG_DIR/tmp/stub export MYSQL_CLUSTER_DOCKER_USERstub export MYSQL_CLUSTER_ROOT_HOST% export MINIO_CERTS_DIR/tmp/stub export MYSQL8_ROOT_HOST% export MYSQL8_DOCKER_USERroot export ZOO_SECURE_CLIENT_PORT2281 export RABBITMQ_COOKIE_FILE/tmp/stub export MONGO_SECURE_CONFIG_DIR/tmp/stub export PROMETHEUS_WRITER_PORT8080 export PROMETHEUS_REMOTE_WRITE_HANDLERS/stub export PROMETHEUS_REMOTE_READ_HANDLERS/stub export PROMETHEUS_READER_PORT8080 export PROMETHEUS_RECEIVER_PORT8080 docker compose $(find ${HOME}/ClickHouse/tests/integration -name *compose*yml -exec echo --file {} \; ) pull这些端口环境变量对应helpers中各类外部服务Kafka、Schema Registry、NGINX、MinIO、ZooKeeper、RabbitMQ、Prometheus 等在测试容器中的暴露端口约定预拉取后测试启动会明显提速。IPv6 问题如果访问 Docker Hub 等资源有网络问题可以禁用 Docker 的 IPv6sudo vim /etc/docker/daemon.json # 添加: { ipv6: false }仓库权限被 Docker 改动原生运行集成测试后Docker 可能改变 ClickHouse 代码仓库的文件权限导致后续clickhouse-test报Permission denied。修复方法是把所有权改回当前用户sudo chown -R user:group ClickHouse/深入理解集成测试的编排机制CI 作业与本地运行的关系ci/jobs/integration_test_job.py是 CI 侧真正的驱动脚本它负责从仓库中收集所有test_*/test.py模块依据构建类型与机器资源把测试切分为多个 batch即Integration tests (amd_binary, N/M)中的 N/M并处理 OOM 检测通过扫描 dmesg 中的oom-kill:等标记、flaky 检查、并行拉取镜像等逻辑。python -m ci.praktika run在本地复刻的正是这套编排——因此作业名中的 batch 信息本质上对应着 integration_tests_configs.py 中的切分配置。理解这一点有助于解释为什么用--test指定单条测试时 batch 序号无关紧要本地只需要选出正确的构建/开关组合即可。Docker 编排与配置注入每个测试模块通过ClickHouseCluster使用 Docker 容器启动多个 ClickHouse 节点。helpers目录下的多个 XML 模板如 0_common_instance_config.xml、0_common_instance_users.xml、0_common_enable_distributed_plan.xml会在容器启动时被注入到节点的/etc/clickhouse-server/下用于统一控制基础配置、用户权限、分布式计划开关等。Keeper 相关测试则使用 keeper_config1.xml 等模板启动多节点 Keeper 集群。值得留意的是 cluster.py 中的DEFAULT_THREAD_FUZZER_SETTINGS它默认对每个实例注入线程模糊器thread fuzzer配置通过随机睡眠与互斥锁迁移概率制造竞态从而放大并发缺陷——这正是集成测试能发现普通功能测试发现不了的问题的原因之一。小结本文完整覆盖了 ClickHouse 集成测试的两条运行路径ci.praktika复现 CI 作业适合对齐 CI 环境、跑精确的 batch与原生 pytest适合快速迭代单条用例以及测试编写约定test_foo/目录、TSV断言、helpers工具箱、调试手段--pdb与nnd低层调试器和常见环境问题处理。结合 tests/integration/README.md、helpers/cluster.py 与 ci/jobs/integration_test_job.py 继续深入即可掌握这套分布式测试体系的全貌。赞分享数据库OLAP列式数据库大数据实时分析数据分析【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址https://gitcode.com/GitHub_Trending/cli/ClickHouse点击查看免费下载相关推荐notebooklm-py 本地故障注入测试框架ADR-0038从决策到可复现的 Socket 级故障回归测试notebooklm py 本地故障注入测试框架ADR 0038从决策到可复现的 Socket 级故障回归测试 本文基于 ADR 0038: LocalAI 应用MCP 服务AI 技能.NET MCP 服务端测试与本地调试完全指南从 MCP Inspector 到内存集成测试与 CI.NET MCP 服务端测试与本地调试完全指南从 MCP Inspector 到内存集成测试与 CI 导读 构建 Model Context Protocol文档知识库AI 技能/插件Rancher 集成测试完全指南从 make ci 全量验证到本地调试tests/v2/integration 深度解析Rancher 集成测试完全指南从 make ci 全量验证到本地调试tests/v2/integration 深度解析 导读 本文围绕 Rancher云原生容器编排集群管理后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询