单元测试
Meson 带有一个功能完备的单元测试系统。要使用它,只需构建一个可执行文件,然后在测试中使用它。
e = executable('prog', 'testprog.c')
test('name of test', e)
您可以添加任意数量的测试。它们通过命令 meson test
运行。
Meson 会捕获所有测试的输出并将其写入日志文件 meson-logs/testlog.txt
。
测试参数
某些测试需要使用命令行参数或环境变量。这些定义起来很简单。
test('command line test', exe, args : ['first', 'second'])
test('envvar test', exe2, env : ['key1=value1', 'key2=value2'])
注意,您需要将多个值指定为数组。
MALLOC_PERTURB_
默认情况下,环境变量 MALLOC_PERTURB_
设置为 1..255 之间的随机值。这有助于在使用 glibc 的配置中找到内存泄漏,包括使用非 GCC 编译器的情况。此功能可以在 test()
中讨论,并可以禁用。
ASAN_OPTIONS、UBSAN_OPTIONS 和 MSAN_OPTIONS
默认情况下,环境变量 ASAN_OPTIONS
、UBSAN_OPTIONS
和 MSAN_OPTIONS
设置为在检测到违规时启用中止并提供回溯。此功能可以在 test()
中讨论,并可以禁用。
覆盖率
如果通过向 Meson 提供命令行标志 -Db_coverage=true
来启用覆盖率测量,则可以在运行测试后生成覆盖率报告(需要运行测试才能收集被调用的函数列表)。Meson 会自动检测您安装了哪些覆盖率生成工具,并生成相应的目标。这些目标是 coverage-xml
和 coverage-text
,它们都由 Gcovr(版本 3.3 或更高版本)提供;coverage-sonarqube
由 Gcovr(版本 4.2 或更高版本)提供;coverage-html
需要 lcov 和 GenHTML 或 Gcovr。为了方便起见,还会生成一个高级 coverage
目标,该目标会在可能的情况下生成所有 3 种覆盖率报告类型。
这些命令的输出将写入构建目录中的日志目录 meson-logs
。
并行性
为了减少测试时间,Meson 默认情况下会并行运行多个单元测试。通常情况下,某些测试无法并行运行,因为它们需要独占某些资源,例如文件或 D-Bus 名称。您必须使用关键字参数指定这些测试。
test('unique test', t, is_parallel : false)
然后,Meson 会确保没有其他单元测试在同一时间运行。非并行测试的运行时间更长,因此建议您尽可能地编写可并行执行的单元测试。
默认情况下,Meson 使用与测试机器上的核心数量一样多的并发进程。您可以使用环境变量 MESON_TESTTHREADS
覆盖它,如下所示。
$ MESON_TESTTHREADS=5 meson test
将 MESON_TESTTHREADS
设置为 0 将启用默认行为(核心数量),而设置无效值会导致将作业数量设置为 1。
优先级
(在 0.52.0 版本中添加)
可以为测试分配优先级,以确定何时开始测试。优先级较高的测试会先开始,优先级较低的测试会后开始。默认优先级为 0,Meson 不保证优先级相同的测试的顺序。
test('started second', t, priority : 0)
test('started third', t, priority : -50)
test('started first', t, priority : 1000)
请注意,测试优先级仅影响测试的启动顺序,后续测试会受到先前测试完成所需时间的影響。因此,当运行时间较短的优先级较低的测试完成时,优先级较高的测试可能仍在运行。
跳过的测试和硬错误
有时,测试只能在运行时确定它是否无法运行。
对于默认的 exitcode
测试协议,在这种情况下,GNU 标准方法是使用错误代码 77 退出程序。Meson 将检测到这一点,并报告这些测试被跳过而不是失败。此行为是在 0.37.0 版本中添加的。
对于基于 TAP 的测试,跳过的测试应打印以 1..0 # SKIP
开头的单行。
此外,有时测试会失败设置,因此即使它被标记为预期失败,它也应该失败。在这种情况下,GNU 标准方法是使用错误代码 99 退出程序。同样,Meson 将检测到这一点,并报告这些测试为 ERROR
,忽略 should_fail
的设置。此行为是在 0.50.0 版本中添加的。
测试工具
Meson 测试工具的目标是提供一种简单的方法来以各种不同方式运行测试。该工具的设计目的是在构建目录中运行。
最简单的方法就是运行所有测试。
$ meson test
运行测试子集
为了清楚起见,请考虑包含以下内容的 meson.build:
test('A', ..., suite: 'foo')
test('B', ..., suite: ['foo', 'bar'])
test('C', ..., suite: 'bar')
test('D', ..., suite: 'baz')
按名称指定测试,例如
$ meson test A D
您可以运行来自特定(子)项目的测试
$ meson test (sub)project_name:
或特定项目中的特定测试
$ meson test (sub)project_name:test_name
从 1.2.0 版本开始,您可以在项目和测试名称中使用通配符。例如,要运行所有以“foo”开头的测试和所有来自以“bar”开头的项目的测试
$ meson test "foo*" "bar*:"
属于套件 suite
的测试可以按如下方式运行
$ meson test --suite (sub)project_name:suite
从 0.46 版本开始,如果它是顶级项目,则可以省略 (sub)project_name
。
多个套件的指定方式如下
$ meson test --suite foo --suite bar
注意:如果您选择同时指定套件和特定测试名称,则测试名称必须包含在套件中。然而,这是多余的——指定特定测试名称或套件更有用。
其他测试选项
有时您需要多次运行测试,方法如下
$ meson test --repeat=10
Meson 会将 MESON_TEST_ITERATION
环境变量设置为测试的当前迭代次数(1.5.0 版本添加)。
使用帮助程序可执行文件(例如 Valgrind)调用测试可以使用 --wrap
参数完成
$ meson test --wrap=valgrind testname
传递给包装程序二进制文件的参数可以像这样给出
$ meson test --wrap='valgrind --tool=helgrind' testname
Meson 还支持在 GDB 下运行测试。只需执行以下操作
$ meson test --gdb testname
Meson 将启动 gdb
并将其设置为运行测试。只需在 GDB 命令提示符中键入 run
即可启动程序。
第二个用例是一个很少出现段错误的测试。在这种情况下,您可以调用以下命令
$ meson test --gdb --repeat=10000 testname
这会在 GDB 下自动运行测试最多 10 000 次。如果程序崩溃,GDB 将停止,用户可以调试应用程序。请注意,在这种情况下,测试超时被禁用,因此 meson test
不会在开发人员仍在调试时杀死 gdb
。缺点是,如果测试二进制文件冻结,测试运行程序将永远等待。
有时,GDB 二进制文件不在 PATH 变量中,或者用户希望使用 GDB 替代品。因此,可以指定调用的 GDB 程序(0.52.0 版本添加)
$ meson test --gdb --gdb-path /path/to/gdb testname
$ meson test --print-errorlogs
可以使用 --interactive
选项交互式地运行测试。meson test --interactive
会调用测试,并将 stdout、stdin 和 stderr 直接连接到调用终端。如果您的测试是运行在容器或虚拟机中的集成测试,并且在失败时会生成调试 shell,这将非常有用(1.5.0 版本添加)
$ meson test --interactive testname
Meson 会报告失败测试产生的输出以及其他有用信息,例如环境变量。例如,当您在 Travis-CI、Jenkins 等上运行测试时,这很有用。
默认情况下,来自测试的输出将限制为最后 100 行。可以使用 --max-lines
选项配置要显示的最大行数(1.5.0 版本添加)
$ meson test --max-lines=1000 testname
超时
在测试用例选项中,timeout
选项以秒数指定。
要禁用测试用例中的超时,请添加 timeout: 0
或负值,以允许测试用例无限期地完成。
对于运行测试,您也可以指定一个命令行参数来覆盖超时
$ meson test --timeout-multiplier 0
有关更多信息,请运行 meson test -h
查看 Meson 的命令行帮助。
旧版说明
如果您发现 meson test
不起作用,那么您可能使用的是旧版本的 Meson。在这种情况下,您应该改用 mesontest
。如果 mesontest
也不起作用,那么您使用的版本非常旧(早于 0.37.0),您应该升级。
测试输出
Meson 将写入几个不同的文件,其中包含运行测试的详细结果。这些文件将写入 $builddir/meson-logs/
testlog.json
这不是一个真正的 json 文件,而是一个包含每行一个有效 json 对象的文件。此文件的设计目的是让每行在每个测试运行时都流出,以便在测试运行程序运行时可以将其作为流读取
testlog.junit.xml
这是一个有效的 JUnit XML 描述,其中包含所有运行的测试。它不会流出,并且只在所有测试完成运行后才会写入一次。
当测试使用 tap
协议时,每个测试将被记录为测试套件容器,每个用例都以结果编号命名。
当测试使用 gtest
协议时,Meson 将注入参数到测试中,以生成自己的 JUnit XML,Meson 将将其包含在此 XML 文件中。
0.55.0 版本新增
搜索结果如下