- 人工智能
- AI Agent
- 多模态
- 语音
- AI 应用
【免费下载链接】ten-framework
Open-source framework for conversational voice AI agents
<输出文章>
Catch2 命令行完全指南:过滤、报告、分片与基准选项实战详解
本文以当前仓库中随附的 Catch2(v3 系)官方文档
command-line.md为骨架,系统讲解 Catch2 测试二进制支持的全部命令行选项——从测试过滤、Reporter 选择、输出控制,到执行顺序、随机种子、测试分片与基准统计。同时结合本仓库内 Catch2 源码(catch_commandline.cpp)与 clingo 项目中的实际用法,给出可复制、可运行的真实示例。读完本文,你将能够熟练编写 Catch2 命令行,精准筛选测试、定制报告输出、控制失败中止策略、实现跨进程测试分片,并深入理解底层参数解析机制。
一、背景:Catch2 在仓库中的位置
Catch2 是一个 C++ 测试框架,以"只需一个头文件即可集成"和"BDD 风格、丰富的断言宏"著称。在本仓库中,Catch2 以第三方依赖的形式被 clingo(Answer Set Programming 求解器)及其子项目 clasp、libpotassco 使用:
- 测试入口通过
#define CATCH_CONFIG_MAIN让 Catch2 自动生成main(),例如clasp/libpotassco/tests/main.cpp中的注释就明确写道:"This tells Catch to provide a main() - only do this in one cpp file"; - 命令行参数的实际解析逻辑位于
catch_commandline.cpp,本文每讲解一个选项,都会指出其在源码中的对应注册位置。
因此,本文所有命令示例中的./tests可以替换为任何链接了 Catch2 的测试可执行文件(如 clingo 的测试二进制)。
二、指定要运行的测试(Test Spec 过滤)
Catch2 完全不传命令行参数也能正常工作:此时会运行所有非隐藏测试用例。一个测试用例被视为隐藏,当且仅当它带有[!benchmark]标签,或带有以点开头的标签(如[.]、[.foo])。
测试规格(test spec)由三种基本形式组合而成:
| 基本形式 | 示例 | 匹配规则 |
|---|---|---|
| 完整测试名 | "Test 1" | 仅匹配名为 "Test 1" 的用例 |
| 通配测试名 | "*Test"、"Test*"、"*Test*" | 匹配以、开头、或中间包含 "Test" 的用例;通配符只能出现在开头或结尾 |
| 标签名 | [some-tag] | 匹配带[some-tag]标签的所有用例 |
三种基本规格可以组合成更复杂的过滤条件:
- 串联(AND):
[some-tag][other-tag]匹配同时具有两个标签的用例,只带其中一个标签的不通过; - 逗号连接(OR):
[some-tag],[other-tag]匹配任一标签的用例,同时带两个标签的当然也通过。注意逗号的优先级高于简单串联,[a][b],[c]等价于"同时带 a 和 b"或"带 c"; - 取反(NOT):在规格前加
~,如~[some-tag]拒绝所有带该标签的用例。取反只作用于紧随其后的那个基本规格,因此~[foo][bar]只否定[foo],不否定[bar]。
Catch2 的筛选决策顺序是:先检查用例是否命中任何否定过滤,命中即拒绝;之后若不存在肯定过滤,则运行所有剩余非隐藏用例;若存在肯定过滤,则只运行命中的用例。
特殊字符可以用反斜杠转义:名为"Do A, then B"的测试可用规格"Do A\, then B"匹配,反斜杠本身也可以转义自身(\\)。
过滤示例对照表
假设有以下测试用例:
TEST_CASE("Test 1") {} TEST_CASE("Test 2", "[.foo]") {} TEST_CASE("Test 3", "[.bar]") {} TEST_CASE("Test 4", "[.][foo][bar]") {}各过滤器的结果如下(./tests为测试可执行文件名):
./tests # 只选中第一个测试,其余都是隐藏的 ./tests "Test 1" # 只选中第一个测试,其他名称不匹配 ./tests ~"Test 1" # 一个都不选:Test 1 被拒绝,其余是隐藏的 ./tests "Test *" # 选中全部测试 ./tests [bar] # 选中测试 3 和 4 ./tests ~[foo] # 选中测试 1(唯一没有 [foo] 标签的非隐藏测试) ./tests [foo][bar] # 选中测试 4 ./tests [foo],[bar] # 选中测试 2、3、4 ./tests ~[foo][bar] # 选中测试 3(2 和 4 因带 [foo] 被拒绝) ./tests ~"Test 2"[foo] # 选中测试 4(测试 2 被显式拒绝) ./tests [foo][bar],"Test 1" # 选中测试 1 和 4 ./tests "Test 1*" # 选中测试 1(通配符可匹配零个字符)实战提醒:命令行中的裸星号(
*)可能被 shell 展开。务必确保星号传给 Catch2 而不是被 shell 解释,建议给规格加引号,如./tests "*Test*"。
在源码层面,测试规格被当作位置参数(Arg( config.testsOrTags, "test name|pattern|tags" ))注册在catch_commandline.cpp,可以出现多次并参与上述组合逻辑。
三、选择 Reporter(输出格式)
-r, --reporter <reporter[::key=value]*>Reporter 决定了 Catch2 输出(断言结果、测试与基准的统计等)的格式与写入方式。默认 reporter 名为console,提供相对详细且对人类友好的输出。
Reporter 支持独立配置:在 reporter 规格后追加::key=value即可,可多次追加,例如:
--reporter xml::out=someFile.xml --reporter custom::colour-mode=ansi::Xoption=2配置键有两类:
- 以
X前缀开头的键,Catch2 不做解析,原样下传给 reporter(reporter 仍可能校验其合法性并抛错); - Catch2 硬编码的内置键,目前只有两个:
out(即-o)和colour-mode。
reporter 的
::key=value参数传递支持是 Catch2 3.0.1 引入的。
内置 reporter 有多个,可用--list-reporters查看它们的说明;需要自定义格式时,可参考 reporter 文档的"编写你自己的 reporter"章节。
该选项可以多次传递以同时使用多个不同的 reporter(Catch2 3.0.1 起支持)。注意:同时最多只有一个 reporter 可以不指定输出文件,未指定输出文件的 reporter 会使用默认输出目标(由-o, --out决定)。另外,当前 reporter 规格中无法转义::,因此 reporter 名称及配置键值中不能包含::。
从源码看,reporter 解析由setReporterlambda 完成(catch_commandline.cpp):先调用parseReporterSpec解析规格,再从注册表getRegistryHub().getReporterRegistry().getFactories()中查找工厂;找不到会报Unrecognized reporter并提示用--list-reporters查看;同时会检查"未指定输出文件的 reporter 最多一个"这一约束。
四、失败时进入调试器
-b, --break在大多数调试器下,Catch2 能自动在测试失败处中断,让开发者直接查看失败瞬间的测试状态。源码中对应config.shouldDebugBreak("-b"["--break"],见catch_commandline.cpp)。
五、显示成功测试的结果
-s, --success默认只报告失败测试。当你怀疑"刚加的测试第一次就跑通了"时,可以用本选项查看全部输出。注意每个 reporter 对此选项的处理可能不同——例如 Junit reporter 本来就会记录所有结果。
六、达到一定失败数后中止
-a, --abort -x, --abortx [<failure threshold>]Catch2 的断言行为:REQUIRE失败会中止当前测试用例,但后续用例仍会继续;CHECK失败甚至不会中止当前用例。这有时会导致失败消息刷屏,而你只想看到前几个。
- 单独使用
-a或--abort:在任意断言第一次失败时中止整个测试运行; - 使用
-x或--abortx并跟一个数字:在该数量的断言失败后中止。
源码实现中-a把config.abortAfter设为 1,-x则把参数值赋给abortAfter(见catch_commandline.cpp)。
七、列出可用的测试、标签与 Reporter
--list-tests --list-tags --list-reporters --list-listeners--list-tests:列出所有匹配指定测试规格的已注册测试。通常还附带标签,根据 verbosity 和 reporter 设计还可能包含源码位置等信息;--list-tags:列出所有标签,通常附带匹配的测试用例数量;--list-reporters:列出所有可用 reporter 及其描述;--list-listeners:列出所有已注册的 listener 及其描述(Catch2 3.0.1 新增)。
--list*系列选项自 Catch2 3.0.1 起可通过 reporter 定制。
--verbosity会改变默认--list*输出的详细程度:
| 选项 | normal(默认) | quiet | high |
|---|---|---|---|
--list-tests | 测试名和标签 | 仅测试名 | 同 normal,另加源码行号 |
--list-tags | 标签和数量 | 同 normal | 同 normal |
--list-reporters | Reporter 名和描述 | 仅 Reporter 名 | 同 normal |
--list-listeners | Listener 名和描述 | 同 normal | 同 normal |
八、输出到文件
-o, --out <filename>将全部输出写到文件而非 stdout。可以用-作为文件名显式输出到 stdout(例如配合多 reporter 时使用;-支持在 Catch2 3.0.1 引入)。
以%(百分号)开头的文件名被 Catch2 保留用于元流(meta stream),例如%debug作为文件名会打开写入平台特定调试/日志机制的流。Catch2 目前识别 3 个元流:
| 元流 | 写入目标 |
|---|---|
%debug | 平台特定的调试/日志输出 |
%stdout | stdout |
%stderr | stderr |
%stdout与%stderr在 Catch2 3.0.1 引入。
九、命名一次测试运行
-n, --name <name for test run>为本次测试运行指定名称,reporter 会把它用作整体标题。这在输出到文件、需要区分不同运行(不同 Catch 可执行文件,或同一可执行文件的不同参数组合)时很有用。未指定时默认使用可执行文件名。
十、跳过预期抛异常的断言
-e, --nothrow跳过所有测试"是否抛出异常"的断言,例如REQUIRE_THROWS。在某些调试环境中,异常抛出(即使是已捕获的)会触发断点,此选项可以避免干扰。此外,如果代码在非断言处也会抛出异常(如被测代码内部抛了又捕获),可以用[!throws]标签标记整个测试用例,在-e模式下跳过整个用例。注意:此选项会改变后续测试的行为,使用需谨慎。
十一、让空白字符可见
-i, --invisibles当字符串比较因空白差异(尤其是首尾空白)失败时,肉眼很难看出问题。此选项会在打印时将制表符和换行符分别转换为\t和\n显示。
十二、警告(Warnings)
-w, --warn <warning name>可以把 Catch2 的警告理解为 C++ 编译器-Werror(/WX)的测试版:把一些可疑情况(如没有断言的 SECTION)从"提醒"升级为错误。因为这类情况可能是刻意为之,警告默认不开启,由用户显式启用,且可同时启用多个。目前实现的两个警告:
NoAssertions // 若测试用例/叶子 SECTION 中没有任何断言(如 REQUIRE),则判失败 UnmatchedTestSpec // 若某个 CLI 测试规格没有匹配到任何测试,则本次运行判失败
UnmatchedTestSpec在 Catch2 3.0.1 引入。NoAssertions对排查"空测试"非常有效,可在 CI 中配合-w NoAssertions防止无效测试悄悄通过。
十三、报告耗时(Timings)
-d, --durations <yes/no> -D, --min-duration <value>-d yes:报告每个测试用例的耗时,单位为秒、精确到毫秒,无论通过还是失败都会报告。注意某些 reporter(如 Junit)无论是否设置本选项都会报告耗时;-D, --min-duration <value>(Catch2 2.13.0 引入):只报告耗时超过<value>秒的用例。该选项会被-d yes和-d no覆盖——即设置后要么全部报告、要么全部不报告。
源码中-d直接映射为ShowDurations::Always/Never,-D写入config.minDuration(见catch_commandline.cpp)。
十四、从文件加载要运行的测试
-f, --input-file <filename>指定一个包含测试用例名列表的文件,每行一个,空行会被跳过。生成该文件初始内容的便捷方式:先用--list-tests配合--verbosity quiet输出纯测试名,再用测试规格过滤出目标子集。
十五、指定测试用例的执行顺序
--order <decl|lex|rand>三种顺序:
decl(默认):声明顺序。同一翻译单元内的测试按声明顺序排序,不同翻译单元之间按实现(链接)相关的顺序;lex:字典序,按测试名排序,忽略标签;rand:随机顺序。顺序取决于 Catch2 的随机种子(见下节--rng-seed),且具备子集不变性(subset invariant):只要随机种子固定,只运行部分测试(如按标签过滤)不会改变它们的相对顺序。
子集稳定性自 Catch2 v2.12.0 引入。自此版本起,官方承诺:给定相同随机种子,只要针对相同版本的 Catch2 编译,不同平台上测试顺序一致;Catch2 不同版本之间允许改变相对顺序,但这不常发生。
十六、指定随机数生成器的种子
--rng-seed <'time'|'random-device'|number>设置 Catch2 使用的随机数生成器种子,例如用户要求随机顺序(--order rand)时的洗牌种子。三种取值:
time:通过std::time(nullptr)生成种子。随机性很弱,若两次运行时间接近可能得到相同种子;random-device:使用std::random_device。只要实现提供了可用的std::random_device就应优先于time;- 数字:直接指定整数种子,可复现特定随机顺序,是 CI 上复现随机失败的首选方式(把失败运行的种子固定下来再重跑)。
默认值:Catch2 默认使用
std::random_device。
十七、按 libIdentify 标准标识框架与版本
--libidentify按 LibIdentify 标准 输出框架名称与版本信息,便于外部工具识别运行的是哪个测试框架、什么版本。对应源码注册为config.libIdentify(见catch_commandline.cpp)。
十八、等待按键后再继续
--wait-for-keypress <never|start|exit|both>让可执行文件打印一条消息并等待回车键:start表示运行任何测试之前等待,exit表示运行完所有测试之后等待,both表示两者都要,never不等待。适合在交互式终端里观察输出流。源码中由setWaitForKeypress解析为WaitForKeypress枚举的四种取值(见catch_commandline.cpp)。
十九、基准测试(Benchmark)相关选项
Catch2 内置基准测试支持,以下选项用于控制采样与统计分析。
跳过所有基准
--skip-benchmarks跳过运行所有基准(Catch2 3.0.1 引入)。注意:这里的"基准"指BENCHMARK和BENCHMARK_ADVANCED宏中的代码块,不包括带[!benchmark]标签的测试用例。
采样数量
--benchmark-samples <# of samples>运行基准时会收集若干"样本(samples)",这是后续统计分析的基础数据。每个样本内部会运行依赖时钟分辨率的若干次迭代(与样本数无关)。默认 100(Catch2 2.9.0 引入)。
自助法(bootstrapping)重采样数量
--benchmark-resamples <# of resamples>测量完成后,会对样本执行统计自助法。重采样数量可配置,默认 100000(Catch2 2.9.0 引入)。通过自助法可以给出均值与标准差的估计,并附带上下界和置信区间(置信区间可配置,默认 95%)。
置信区间
--benchmark-confidence-interval <confidence-interval>用于自助法统计、计算均值与标准差上下界的置信区间,取值必须介于 0 和 1 之间,默认 0.95(Catch2 2.9.0 引入)。
关闭统计分析
--benchmark-no-analysis指定后不做任何自助法或统计分析,只测量用户代码并报告样本的朴素均值(Catch2 2.9.0 引入)。适合只想快速看吞吐、不关心置信区间的场景。
预热时间
--benchmark-warmup-time <毫秒>配置每个测试的预热时间,单位毫秒,默认 100(Catch2 2.11.2 引入)。
以上选项在源码中集中注册于catch_commandline.cpp,其帮助文本直接标明了默认值:samples 默认 100、resamples 默认 100000、confidence interval 默认 0.95、warmup time 默认 100ms。
二十、显示帮助
-h, -?, --help将全部命令行参数打印到 stdout。
二十一、指定要运行的 SECTION
-c, --section <section name>把执行范围限制到测试用例内的特定 SECTION,可多次使用;后续每次指定都会深入一层嵌套。例如:
TEST_CASE( "Test" ) { SECTION( "sa" ) { SECTION( "sb" ) { /*...*/ } SECTION( "sc" ) { /*...*/ } } SECTION( "sd" ) { /*...*/ } }- 只运行
sb:./MyExe Test -c sa -c sb - 只运行
sd:./MyExe Test -c sd - 运行
sa全部(含sb和sc):./MyExe Test -c sa
需要注意的局限:
- SECTION 之外的代码仍会执行——例如
TEST_CASE中第一个 SECTION 之前的任何 setup 代码不会被跳过; - 当前 SECTION 名不支持通配符;
- 如果未先用测试名收窄范围,则所有测试用例都会执行(但各自只跑匹配的 SECTION)。
二十二、文件名作为标签
-#, --filenames-as-tags给所有测试用例额外加一个标签:#加上测试用例定义所在的非限定文件名,并去掉最后一个扩展名。例如tests\SelfTest\UsageTests\BDD.tests.cpp中的测试会被加上[#BDD.tests]标签。由此可以按源文件批量筛选测试,例如:
./tests [#BDD.tests]二十三、覆盖输出颜色
--colour-mode <ansi|win32|none|default>Catch2 支持两种终端着色方式,默认会自动猜测用哪种实现、以及是否该用(例如写入文件时会避免输出颜色码)。--colour-mode允许显式指定:
ansi:总是使用 ANSI 颜色码,即使写入文件也如此;win32:使用基于 Win32 终端 API 的颜色实现;none:完全禁用颜色;default:交给 Catch2 自行判断,也是默认设置。
--colour-mode在 Catch2 3.0.1 中取代了旧的--colour选项。源码中由setDefaultColourMode解析并写入config.defaultColourMode(见catch_commandline.cpp)。
二十四、测试分片(Test Sharding)
--shard-count <#number of shards>, --shard-index <#shard index to run>当指定--shard-count <N>时,待执行的测试会被均匀分成 N 组,组编号从 0 开始;--shard-index <i>指定本次运行第 i 组。默认shard-count为 1,默认shard-index为 0。
- 约束:
shard-index必须小于shard-count,因为它被当作要运行的分片索引; - 用途:把测试执行拆分到多个进程并行,这与 Bazel 的测试分片模式类似。
分片功能在 Catch2 3.0.1 引入。源码中对--shard-count做了严格校验:解析失败或为 0 都会报错("Shard count must be positive"),见catch_commandline.cpp。
CI 中的典型用法(例如 4 个并行 worker):
# worker 0 ./tests --shard-count 4 --shard-index 0 # worker 1 ./tests --shard-count 4 --shard-index 1 # worker 2 ./tests --shard-count 4 --shard-index 2 # worker 3 ./tests --shard-count 4 --shard-index 3二十五、允许在没有任何测试时以成功退出
--allow-running-no-tests默认情况下,如果没有运行任何测试(例如二进制未编译进测试、测试规格未匹配到任何用例,或所有测试在运行时被跳过),Catch2 测试二进制会返回非 0 退出码。本选项(Catch2 3.0.1 引入)覆盖此行为,使"无测试"的运行也返回 0。对应源码为config.allowZeroTests(见catch_commandline.cpp)。在 CI 流水线中,若想容忍"暂时没有匹配测试"的阶段,可考虑使用此选项,但更推荐配合-w UnmatchedTestSpec把"规格没匹配"显式暴露出来。
二十六、输出详细程度(Verbosity)
-v, --verbosity <quiet|normal|high>改变 reporter 输出的细节量。但请把改变 verbosity 视为一种建议:并非所有 reporter 都支持所有级别(例如有些 reporter 的格式无法有意义地变化),此时该设置会被忽略。默认值为normal。
源码中setVerbosity把quiet、normal、high映射为Verbosity::Quiet/Normal/High,无法识别的值会直接报错(见catch_commandline.cpp)。
二十七、选项速查表
| 选项 | 短选项 | 作用 | 默认值/说明 |
|---|---|---|---|
<test-spec> ... | — | 按名称/通配/标签过滤测试 | 不传则运行全部非隐藏用例 |
--help | -h, -? | 打印帮助 | — |
--success | -s | 也显示成功测试结果 | 默认只显示失败 |
--break | -b | 失败时进入调试器 | — |
--nothrow | -e | 跳过异常断言 | 配合[!throws]标签 |
--invisibles | -i | 显示制表符/换行为\t/\n | — |
--out <file> | -o | 输出到文件 | 支持-、%debug、%stdout、%stderr |
--reporter <spec> | -r | 选择 reporter | 默认 console;可多 reporter |
--name <name> | -n | 命名本次运行 | 默认可执行文件名 |
--abort | -a | 首次失败即中止 | — |
--abortx <n> | -x | 失败 n 次后中止 | — |
--warn <name> | -w | 启用警告 | NoAssertions、UnmatchedTestSpec |
--durations <yes/no> | -d | 报告每个用例耗时 | — |
--min-duration <sec> | -D | 只报告超过阈值的耗时 | 2.13.0 引入 |
--input-file <file> | -f | 从文件加载测试名列表 | 每行一个 |
--order <decl/lex/rand> | — | 执行顺序 | 默认 decl |
--rng-seed <seed> | — | 随机种子 | 默认random-device |
--libidentify | — | 按 libIdentify 标准输出标识 | — |
--wait-for-keypress <mode> | — | 等待按键 | never/start/exit/both |
--skip-benchmarks | — | 跳过全部基准 | 3.0.1 引入 |
--benchmark-samples <n> | — | 采样数量 | 默认 100 |
--benchmark-resamples <n> | — | 自助法重采样数 | 默认 100000 |
--benchmark-confidence-interval <v> | — | 置信区间 | 0~1,默认 0.95 |
--benchmark-no-analysis | — | 关闭统计分析 | 只报朴素均值 |
--benchmark-warmup-time <ms> | — | 预热时间 | 默认 100ms |
--section <name> | -c | 只运行指定 SECTION | 可多次、逐层深入 |
--filenames-as-tags | -# | 文件名作为标签 | 如[#BDD.tests] |
--colour-mode <mode> | — | 覆盖着色方式 | ansi/win32/none/default |
--shard-count <n> | — | 分片总数 | 默认 1 |
--shard-index <i> | — | 运行第 i 片 | 默认 0;必须小于 shard-count |
--allow-running-no-tests | — | 无测试也返回 0 | 3.0.1 引入 |
--verbosity <level> | -v | 输出详细程度 | quiet/normal/high,默认 normal |
二十八、在仓库中继续深入
- 本文主体文档:
third_party/clingo-sys/clingo/third_party/catch/docs/command-line.md - 命令行解析源码:
third_party/clingo-sys/clingo/third_party/catch/src/catch2/internal/catch_commandline.cpp - 自定义 reporter 指南:
third_party/clingo-sys/clingo/third_party/catch/docs/reporters.md - 运行时跳过/通过/失败机制:
third_party/clingo-sys/clingo/third_party/catch/docs/skipping-passing-failing.md - clingo 项目中 Catch2 的实际测试入口:
third_party/clingo-sys/clingo/clasp/libpotassco/tests/main.cpp - 分片相关 CMake 辅助脚本:
third_party/clingo-sys/clingo/third_party/catch/extras/CatchShardTests.cmake
结合本仓库内的源码阅读上述实现,你会发现:所有选项最终都汇聚到catch_commandline.cpp中基于 Clara 库构建的cli表达式(ExeName | Help | Opt(...) | Arg(...)),通过parseUInt、toLower等工具做严格的输入校验。掌握这一入口文件,就等于掌握了 Catch2 命令行行为的全部底层逻辑。
- 人工智能
- AI Agent
- 多模态
- 语音
- AI 应用
【免费下载链接】ten-framework
Open-source framework for conversational voice AI agents
相关推荐
TEN Framework tman 依赖解析实战:用 Clingo 求解器优选“最高根版本”的 highest_root_resolved 测试用例剖析
TEN Framework tman 依赖解析实战:用 Clingo 求解器优选“最高根版本”的 highest_root_resolved 测试用例剖析 本文
人工智能AI Agent多模态语音AI 应用深度解析LibreHardwareMonitor:如何通过开源技术实现全面的硬件监控
深度解析LibreHardwareMonitor:如何通过开源技术实现全面的硬件监控 在现代计算机系统中,硬件监控已经从简单的温度检测演变为复杂的系统健康管理体
指标监控Chaos Genius异常检测模型对比:Prophet、EWMA、Neural Prophet等5种模型深度评测
Chaos Genius异常检测模型对比:Prophet、EWMA、Neural Prophet等5种模型深度评测 在当今数据驱动的时代,异常检测已成为企业监控
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考