单元测试

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_OPTIONSUBSAN_OPTIONSMSAN_OPTIONS 设置为在检测到违规时启用中止并提供回溯。此功能可以在 test() 中讨论,并可以禁用。

覆盖率

如果通过向 Meson 提供命令行标志 -Db_coverage=true 来启用覆盖率测量,则可以在运行测试后生成覆盖率报告(需要运行测试才能收集被调用的函数列表)。Meson 会自动检测您安装了哪些覆盖率生成工具,并生成相应的目标。这些目标是 coverage-xmlcoverage-text,它们都由 Gcovr(版本 3.3 或更高版本)提供;coverage-sonarqubeGcovr(版本 4.2 或更高版本)提供;coverage-html 需要 lcovGenHTMLGcovr。为了方便起见,还会生成一个高级 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 版本新增

搜索结果如下