16、CTest仪表板与CDash:CDash是什么?配置CTest上传结果、查看历史趋势
说实话,我第一次接触CDash的时候,心里想的是:「这不就是个网页版测试报告吗?」后来在团队里真正用起来,才发现这东西远不止「报告」那么简单。
咱们先理清一个概念:CTest负责跑测试、收集结果,CDash负责展示、归档、对比。两者配合,才能形成完整的持续测试闭环。
CDash到底是什么?
CDash是一个开源的Web仪表板系统。它专门用来聚合、展示、分析CTest上传的测试结果。你可以把它理解成「测试数据的中央仓库」。
我个人习惯把CDash比作「测试界的GitHub」——你提交代码到GitHub,别人能看到你的代码变更;你上传测试结果到CDash,团队就能看到你的测试状态变化。
CDash能做什么?
- 聚合多平台结果:Windows、Linux、macOS的测试结果可以汇总到同一个仪表板
- 历史对比:查看任意测试在过去N次提交中的状态变化
- 失败分析:自动归类相似的测试失败,帮你定位是代码变更还是环境问题
- 覆盖率追踪:配合gcov/lcov,展示代码覆盖率的趋势曲线
- 性能回归检测:记录测试执行时间,发现性能退化
嗯,这里要注意:CDash不是CI系统。它不负责触发构建和测试,只负责「收数据、展示数据」。CI系统(比如Jenkins、GitLab CI)负责跑CTest,CTest再把结果推给CDash。
配置CTest上传结果到CDash
配置过程其实不复杂,但有几个坑。我曾经在一个项目里折腾了整整一下午,就是因为漏了一个环境变量。
第一步:准备CDash服务器
你可以自己搭建CDash,也可以用Kitware官方提供的公共CDash(用于开源项目)。自己搭建的话,需要PHP和MySQL/PostgreSQL支持。我个人建议先用Docker快速跑起来:
docker run -d -p 80:80 \
-e CDASH_DB_HOST=mysql \
-e CDASH_DB_NAME=cdash \
-e CDASH_DB_USER=cdash \
-e CDASH_DB_PASS=cdash_pass \
kitware/cdash:latest
启动后访问 http://localhost ,按向导完成初始化配置。你会得到一个CDash项目的URL,比如 http://cdash.example.com/submit.php?project=MyProject。
第二步:在CMakeLists.txt中配置CTest
你需要告诉CTest:测试结果要往哪里传。在项目的顶层CMakeLists.txt里加上:
# 启用测试
enable_testing()
# 设置CDash服务器地址
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "cdash.example.com")
set(CTEST_DROP_LOCATION "/submit.php?project=MyProject")
set(CTEST_DROP_SITE_CDASH TRUE)
# 可选:设置构建名称和站点名称
set(CTEST_BUILD_NAME "Linux-GCC-Release")
set(CTEST_SITE "build-server-01")
第三步:编写CTest配置脚本
我建议单独写一个 CTestConfig.cmake 文件,放在项目根目录:
# CTestConfig.cmake
set(CTEST_PROJECT_NAME "MyProject")
set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "cdash.example.com")
set(CTEST_DROP_LOCATION "/submit.php?project=MyProject")
set(CTEST_DROP_SITE_CDASH TRUE)
然后在运行CTest时,用 -S 参数指定一个驱动脚本。比如 dashboard.cmake:
# dashboard.cmake
cmake_minimum_required(VERSION 3.20)
# 包含项目配置
include("${CTEST_SCRIPT_DIRECTORY}/CTestConfig.cmake")
# 设置源码和构建目录
set(CTEST_SOURCE_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}")
set(CTEST_BINARY_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}/build")
# 开始仪表板测试
ctest_start("Experimental")
ctest_configure()
ctest_build()
ctest_test()
ctest_submit()
第四步:运行并上传
ctest -S dashboard.cmake -V
-V 参数会输出详细日志。你会看到类似这样的信息:
Submit files (using http)
Submit URL: http://cdash.example.com/submit.php?project=MyProject
Submit file: /path/to/Testing/20250320-1234/Build.xml
Uploaded: Build.xml
Submit file: /path/to/Testing/20250320-1234/Test.xml
Uploaded: Test.xml
Submission successful
看到「Submission successful」就说明上传成功了。去CDash网页上刷新,就能看到测试结果。
http_proxy 环境变量。另外,CDash服务器的时间要和构建机器同步,否则时间戳错乱会导致仪表板显示异常。
查看历史趋势
数据上传到CDash之后,怎么用?我挑几个最常用的功能说说。
测试通过率趋势图
CDash会自动生成测试通过率的折线图。横轴是时间/构建次数,纵轴是通过率百分比。你能直观看到:
- 某次提交后通过率突然下降——说明引入了回归
- 通过率长期在90%徘徊——说明有顽固的失败测试需要处理
测试耗时变化
每个测试的执行时间都会被记录。如果某个测试从1秒突然变成10秒,CDash会标红。我遇到过几次,都是因为测试代码里不小心加了死循环或者大数据量操作。
覆盖率趋势
如果你在CTest中配置了覆盖率收集,CDash会展示行覆盖率、函数覆盖率、分支覆盖率的趋势。我个人习惯每周看一次覆盖率曲线——如果连续两周下降,就该补测试了。
SVG:CDash与CTest协作流程
CDash的几种测试模式
| 模式 | 用途 | 我常用的场景 |
|---|---|---|
| Experimental | 开发中的实验性测试 | 本地调试,不想影响主线 |
| Nightly | 每日定时构建测试 | 团队每日集成检查 |
| Continuous | 每次提交触发 | CI流水线中自动运行 |
| Coverage | 覆盖率收集 | 每周覆盖率趋势分析 |
在 ctest_start() 中指定模式:
ctest_start("Experimental") # 实验模式
ctest_start("Nightly") # 每日构建
ctest_start("Continuous") # 持续集成
避坑指南
最后分享几个我踩过的坑:
- XML文件过大:如果测试用例特别多(上千个),生成的XML可能几十MB。CDash默认限制上传大小,需要在服务器端调整
upload_max_filesize和post_max_size。 - 重复提交:同一个构建ID重复提交,CDash会覆盖旧数据。如果你在CI中不小心循环调用了
ctest_submit(),历史数据就乱了。我建议在脚本里加个锁或者状态检查。 - 时区问题:CDash的「每日构建」按UTC 00:00切分。如果你的构建在UTC 23:59跑完,上传后会被归到当天;如果00:01跑完,就归到第二天。这个边界情况容易让人困惑。
好了,CDash的基本用法就这些。说白了,它就是帮你把零散的测试结果变成可视化的历史趋势。配置一次,后面就省心了。
公众号:蓝海资料掘金营,微信deep3321