22、CDash持续集成:如何将CTest结果上传到CDash仪表盘,实现跨平台的构建与测试监控。
说实话,CTest 跑完测试只是第一步。你想想看,团队里五个人,分别在 Windows、macOS、Linux 上开发,每个人跑完测试都说「我这边过了」,结果合到一起就崩。这种事我遇到过太多次了。
CDash 就是来解决这个问题的。它把 CTest 的结果收集起来,展示在一个网页仪表盘上。谁在什么平台上跑了什么测试,通过了多少、失败了多少,一目了然。说白了,它就是 CTest 的「可视化报告中心」。
22.1 CDash 是什么?为什么需要它?
CDash 是一个开源的 Web 应用,专门用来接收和展示 CTest 提交的测试结果。它支持:
- 跨平台测试汇总:Windows、Linux、macOS 的结果集中展示
- 历史趋势分析:看看测试通过率是上升还是下降
- 构建失败定位:哪个文件、哪个测试用例挂了,点进去就能看到日志
- 团队协作:每个人都能看到最新的构建状态
我个人习惯是把 CDash 作为 CI 流程的「最后一公里」。CI 跑完测试,CTest 把结果推送到 CDash,然后整个团队打开浏览器就能看到状态。比翻 Jenkins 日志舒服多了。
22.2 搭建 CDash 服务器
CDash 可以自己部署,也可以用 Kitware 提供的托管服务。自己部署的话,我建议用 Docker,省心。
这里是一个简单的 docker-compose 配置:
version: '3'
services:
cdash:
image: kitware/cdash:latest
ports:
- "8080:80"
environment:
- CDASH_DB_HOST=mysql
- CDASH_DB_NAME=cdash
- CDASH_DB_USER=cdash
- CDASH_DB_PASS=cdash_secret
volumes:
- ./cdash-backup:/var/lib/cdash/backup
depends_on:
- mysql
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=root_secret
- MYSQL_DATABASE=cdash
- MYSQL_USER=cdash
- MYSQL_PASSWORD=cdash_secret
volumes:
- ./mysql-data:/var/lib/mysql
启动之后,访问 http://localhost:8080 就能看到 CDash 的界面了。第一次访问需要创建管理员账号,然后创建一个项目。项目创建好之后,会得到一个 项目 ID 和 提交令牌,这两个东西后面要用。
22.3 配置 CTest 提交到 CDash
要让 CTest 把结果推送到 CDash,需要在 CMake 中配置几个变量。嗯,这里要注意,这些变量必须在 enable_testing() 之前设置。
# CMakeLists.txt 中配置 CDash 提交
set(CTEST_PROJECT_NAME "MyProject")
set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC")
# CDash 服务器地址
set(CTEST_DROP_SITE "my-cdash-server.com")
set(CTEST_DROP_SITE_USER "anonymous")
set(CTEST_DROP_SITE_PASSWORD "")
set(CTEST_DROP_SITE_METHOD "http")
set(CTEST_DROP_SITE_CDASH TRUE)
# 或者使用 CDash 的提交 API(推荐)
set(CTEST_SUBMIT_URL "http://my-cdash-server.com/submit.php?project=MyProject")
enable_testing()
add_test(NAME my_test COMMAND my_test_executable)
配置好之后,在构建目录中运行:
ctest -D Experimental # 提交一次实验性构建
ctest -D Nightly # 提交夜间构建
ctest -D Continuous # 提交持续构建
CTest 会自动执行测试,然后把结果打包成 XML,通过 HTTP POST 提交到 CDash。
CTEST_DROP_SITE_USER 和 CTEST_DROP_SITE_PASSWORD 中填写正确的凭据。我曾经因为忘了配密码,折腾了半天才发现是认证问题。
22.4 使用 CTest 脚本实现自动化提交
手动敲 ctest -D Experimental 不是长久之计。我建议写一个 CTest 脚本,把配置、构建、测试、提交全部自动化。
创建一个 ctest_script.cmake 文件:
# ctest_script.cmake
cmake_minimum_required(VERSION 3.20)
# 项目配置
set(CTEST_PROJECT_NAME "MyProject")
set(CTEST_SOURCE_DIRECTORY "/path/to/source")
set(CTEST_BINARY_DIRECTORY "/path/to/build")
# CDash 配置
set(CTEST_DROP_SITE "my-cdash-server.com")
set(CTEST_DROP_SITE_USER "anonymous")
set(CTEST_DROP_SITE_PASSWORD "")
set(CTEST_DROP_SITE_METHOD "http")
set(CTEST_DROP_SITE_CDASH TRUE)
# 开始构建
ctest_start("Experimental")
# 配置
ctest_configure()
# 构建
ctest_build()
# 测试
ctest_test()
# 提交结果
ctest_submit()
然后运行:
ctest -S ctest_script.cmake
这个脚本可以放在 CI 流水线中,每次代码提交后自动执行。我个人习惯把它放在 GitHub Actions 或 GitLab CI 中,配合 cron 定时触发夜间构建。
22.5 CDash 仪表盘解读
提交成功后,打开 CDash 页面,你会看到类似这样的仪表盘:
仪表盘主要分几个区域:
- 统计概览:总测试数、通过数、失败数、通过率
- 平台状态:每个平台的构建和测试结果
- 失败详情:点击可以查看具体的测试日志和错误信息
- 历史趋势:通过率随时间的变化曲线
我最常用的是「失败详情」功能。点进去能看到完整的测试输出,包括标准输出、标准错误、以及 CTest 捕获的异常信息。定位问题非常方便。
22.6 跨平台构建与测试监控实战
假设你的项目需要在三个平台上构建:Linux、Windows、macOS。每个平台有不同的编译器、不同的依赖库。CDash 可以把这些结果统一展示。
下面是一个完整的 CI 配置示例(以 GitHub Actions 为例):
# .github/workflows/cdash.yml
name: CDash CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 2 * * *' # 每天凌晨2点执行夜间构建
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
config: [Debug, Release]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Configure
run: |
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.config }} \
-DCTEST_PROJECT_NAME="MyProject" \
-DCTEST_DROP_SITE="my-cdash-server.com" \
-DCTEST_SUBMIT_URL="http://my-cdash-server.com/submit.php?project=MyProject"
- name: Build
run: cmake --build build --config ${{ matrix.config }}
- name: Test and Submit
run: ctest --test-dir build -D Experimental --output-on-failure
这个配置会:
- 在三个操作系统上分别构建 Debug 和 Release 版本
- 运行所有测试
- 把结果提交到 CDash
在 CDash 上,你会看到 6 个构建条目(3 个系统 × 2 种配置)。每个条目都可以展开查看详细的测试结果。
22.7 避坑指南
我在使用 CDash 的过程中踩过不少坑,分享几个典型的:
- 提交失败:检查 CDash 服务器地址和项目名称是否正确。我曾经把项目名写成了大小写不一致,结果提交了但 CDash 上不显示。
- 测试超时:CTest 默认超时时间是 10 分钟。如果测试用例跑得久,记得在
add_test()中设置TIMEOUT参数。 - XML 格式错误:CTest 生成的 XML 如果不符合 CDash 的要求,提交会失败。通常是因为测试输出中包含了特殊字符。可以在 CTest 脚本中设置
CTEST_SUBMIT_RETRY_COUNT和CTEST_SUBMIT_RETRY_DELAY来自动重试。 - 磁盘空间不足:CDash 会保存历史构建数据,时间长了会占用大量磁盘。建议定期清理旧数据,或者配置数据保留策略。
22.8 总结
CDash 让 CTest 的测试结果变得可视化、可追溯。它解决了跨平台测试监控的痛点——你不用再登录不同的 CI 平台去翻日志,打开 CDash 就能看到全局状态。
配置起来其实不复杂:部署 CDash 服务器、配置 CTest 提交、写一个自动化脚本、集成到 CI 流水线。做完这些,你的项目就有了一个专业的测试监控中心。
嗯,最后说一句:CDash 和 CTest 是天生一对。如果你已经在用 CTest,那 CDash 绝对是值得投入的下一站。
公众号:蓝海资料掘金营,微信deep3321