GTest¶
GTest (googletest) 是 Google 用于在各种平台(Linux、Mac OS X、Windows 等)上编写 C++ 测试的框架。基于 xUnit 架构,它支持自动测试发现、丰富的断言集、用户定义断言、死亡测试、致命和非致命错误、值和类型参数化测试、各种运行测试的选项以及 XML 测试报告生成。
集成¶
GTest 在 Win/Mac/Linux 和 Android 上作为标准测试任务运行,在 treeherder 中使用符号“GTest”。
运行测试¶
只要您在 mozconfig 中不禁用测试,Firefox 构建过程就会在受支持的平台上构建 GTest。但是,只有在需要测试以节省昂贵的二次链接过程时,才会构建 xul-gtest。
要运行单元测试,在调用 Gecko 时使用“mach gtest”。
运行选定的测试¶
可以使用 mach 选择测试。您还可以使用 GTest 支持的环境变量。有关更多详细信息,请参阅 运行测试程序:运行测试子集。
mach gtest Moz2D.*
配置 GTest¶
可以通过其他环境变量控制 GTest。有关更多详细信息,请参阅 运行测试程序:高级选项。
调试 GTest 单元测试¶
要调试 gtest,请将 –debug 传递给正常命令。
./mach gtest --debug [ Prefix.Test ]
如果这不起作用,您可以尝试在调试器下运行 firefox 二进制文件,并将 MOZ_RUN_GTEST 环境变量设置为 1。
MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb]
警告
使用 MOZ_RUN_GTEST 时,请勿忘记构建 + 运行“mach gtest”以重新链接,因为它不是顶级构建的一部分。
请注意,这将加载一个备用 libxul - 其中内置了测试代码的那个,它位于 objdir 的 gtest/子目录中。此启用 gtest 的 libxul 不是作为常规构建的一部分构建的,因此您必须确保在运行上述命令之前构建它。一个简单的办法是运行“mach gtest”,它将重新构建 libxul 并运行测试。您还可以从 mach 中提取仅重新构建该 libxul 所需的命令并直接运行它们。最后,请注意,您可能必须运行测试一次才能使 gdb 加载所有相关库并使断点符号正确解析。
请注意,您可以通过使用 GTEST_FILTER 环境变量来调试测试子集(包括单个测试)
GTEST_FILTER='AsyncPanZoom*' MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb]
使用 Xcode 调试¶
请参阅 在 macOS 上调试 以了解初始设置。您可能希望创建一个单独的方案来运行 GTest(“产品”>“方案”>“新建方案...”)。除了 GTEST_FILTER 之外,请设置以下环境变量
MOZ_XRE_DIR=/path-to-object-directory/obj-ff-dbg/dist/bin
MOZ_RUN_GTEST=True
并在方案的“选项”选项卡下,将工作目录设置为
☑️ Use custom working directory: /path-to-object-directory/obj-ff-dbg/_tests/gtest
使用 Visual Studio Code 调试¶
将如下配置添加到您的 launch.json 文件中(您可以通过“运行”/“打开配置”进行编辑)
{
"name": "(gdb) Launch gtest",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/dist/bin/firefox",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/_tests/gtest",
"environment": [{"name": "MOZ_RUN_GTEST", "value": "True"},
{"name": "GTEST_FILTER", "value": "AsyncPanZoom*"}],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
编写 GTest 单元测试¶
大多数 GTest 文档 都适用于此。建议阅读 GTest 入门指南。
警告
GTest 将并行运行测试。不要添加非线程安全的单元测试,例如需要焦点或使用特定套接字的测试。
警告
GTest 将在不初始化 mozilla 服务的情况下运行。在您的测试夹具中初始化和拆除任何依赖项。避免编写集成测试,并专注于测试单个单元。
请参阅 https://hg.mozilla.org/mozilla-central/rev/ed612eec41a44867a,了解如何添加简单测试的示例。
如果您要将现有的 C++ 单元测试转换为 GTest,此提交 可以作为有用的参考。
为测试设置首选项¶
如果测试涵盖默认情况下禁用的功能,则必须在单个测试中更改相关首选项
bool oldPref = Preferences::GetBool(prefKey);
Preferences::SetBool(prefKey, true);
… // test code
Preferences::SetBool(prefKey, oldPref);
或者,如果它适用范围更广,则可以将其应用于整个夹具(请参阅 GTest 文档,或 AutoInitializeImageLib 作为示例)。
将测试添加到构建系统¶
找到适合模块的 gtest 目录。如果不存在,请使用以下约定创建目录:“<子模块>/tests/gtest”。创建一个 moz.build 文件(在新创建的目录中),其中包含模块声明,将 gfxtest 替换为唯一名称,并将 UNIFIED_SOURCES 设置为包含所有测试文件名。
我们在这里所做的是创建一个源文件列表,这些文件将仅针对 gtest 版本的 libxul 进行编译和链接。这将允许这些源文件调用内部 xul 符号,而无需将它们作为我们交付给用户的二进制文件的一部分。
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
Library('gfxtest')
UNIFIED_SOURCES = [
<ListTestFiles>,
]
FINAL_LIBRARY = 'xul-gtest'
更新父目录中的“<子模块>/moz.build”以在
TEST_DIRS += [
"gtest",
]
将测试添加到现有的 moz.build 文件时(它具有 FINAL_LIBRARY = ‘xul-gtest’),请添加以下内容。就是这样 - 不需要测试清单。您的测试将使用静态构造函数自动注册。
UNIFIED_SOURCES = [
'TestFoo.cpp',
]
备注¶
您正在测试的类的包含文件可能不需要全局导出,但它确实需要可用于您正在编写的单元测试。在这种情况下,在测试目录内的 Makefile.in 中添加如下内容。
LOCAL_INCLUDES += [
'/gfx/2d',
'/gfx/2d/unittest',
'/gfx/layers',
]
如果您想验证您的测试是否有效,Gtest 目前在 Treeherder 上的 GTest 符号下从测试包运行。以前它们在 B 符号下运行,在 `make check` 期间运行。
MozGTestBench¶
Mozilla GTest Microbench 只是一个将测试持续时间报告给 perfherder 的 GTest。这是一种添加低级性能测试的简单方法。请记住,监控性能测试会产生非零成本,因此请谨慎使用。您仍然可以执行测试断言。
编写 Microbench GTest¶
使用“MOZ_GTEST_BENCH”而不是“TEST”来计时测试的执行。示例
#include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH
...
MOZ_GTEST_BENCH(GfxBench, TEST_NAME, []{
// Test to time the execution
});
确保使用上述说明将此文件注册到文件系统。如果一切正常,您应该在对应测试的 GTest 日志中看到以下内容
PERFHERDER_DATA: {"framework": {"name": "platform_microbench"}, "suites": [{"name": "GfxBench", "subtests": [{"name": "CompositorSimpleTree", "value": 252674, "lowerIsBetter": true}]}]}
负责人策略¶
Microbench 测试衡量非常具体的操作的速度。微基准测试的回归可能不会导致用户可见的回归,不应像 Talos 回归那样严格对待。当代码被直接修改时,也会预期微基准分数发生较大变化,如果开发人员打算更改该代码,则应接受这些变化。但是,微基准测试为平台代码添加性能测试和性能修复的回归测试提供了一个框架。它们将捕获代码中意外的回归,并且当与 Talos 回归相关联时,可能会指示回归的来源。