GoogleTest 常见问题解答
为什么测试套件名称和测试名称不应包含下划线?
注意:除了以下理由外,GoogleTest 保留下划线 (_
) 用于特殊用途的关键字,例如 DISABLED_
前缀。
下划线 (_
) 很特殊,因为 C++ 保留以下内容供编译器和标准库使用
- 任何以下划线 (
_
) 后跟大写字母开头的标识符,以及 - 任何名称中任何位置包含两个连续下划线(即
__
)的标识符。
禁止用户代码使用此类标识符。
现在让我们看看这对 TEST
和 TEST_F
意味着什么。
目前 TEST(TestSuiteName, TestName)
生成一个名为 TestSuiteName_TestName_Test
的类。如果 TestSuiteName
或 TestName
包含 _
会发生什么?
- 如果
TestSuiteName
以下划线 (_
) 后跟大写字母开头(例如,_Foo
),我们将得到_Foo_TestName_Test
,这是保留的,因此无效。 - 如果
TestSuiteName
以_
结尾(例如,Foo_
),我们将得到Foo__TestName_Test
,这是无效的。 - 如果
TestName
以下划线 (_
) 开头(例如,_Bar
),我们将得到TestSuiteName__Bar_Test
,这是无效的。 - 如果
TestName
以_
结尾(例如,Bar_
),我们将得到TestSuiteName_Bar__Test
,这是无效的。
所以很明显 TestSuiteName
和 TestName
不能以 _
开头或结尾(实际上,TestSuiteName
可以以 _
开头——只要 _
后面没有大写字母。但这变得复杂了。所以为了简单起见,我们只是说它不能以 _
开头。)。
对于 TestSuiteName
和 TestName
在中间包含 _
似乎没问题。但是,考虑一下这个
TEST(Time, Flies_Like_An_Arrow) { ... }
TEST(Time_Flies, Like_An_Arrow) { ... }
现在,这两个 TEST
将生成相同的类(Time_Flies_Like_An_Arrow_Test
)。这不好。
因此,为了简单起见,我们只是要求用户避免在 TestSuiteName
和 TestName
中使用 _
。该规则比必要的更严格,但它简单且易于记住。它还为 GoogleTest 提供了一些回旋余地,以防其实现将来需要更改。
如果您违反该规则,可能不会立即产生后果,但您的测试可能会(仅仅可能)在使用新编译器(或您正在使用的新版本的编译器)或使用新版本的 GoogleTest 时崩溃。因此,最好遵循该规则。
为什么 GoogleTest 支持 EXPECT_EQ(NULL, ptr)
和 ASSERT_EQ(NULL, ptr)
,但不支持 EXPECT_NE(NULL, ptr)
和 ASSERT_NE(NULL, ptr)
?
首先,您可以将 nullptr
与这些宏中的每一个一起使用,例如 EXPECT_EQ(ptr, nullptr)
、EXPECT_NE(ptr, nullptr)
、ASSERT_EQ(ptr, nullptr)
、ASSERT_NE(ptr, nullptr)
。这是样式指南中的首选语法,因为 nullptr
没有 NULL
存在的类型问题。
由于 C++ 的一些特殊性,它需要一些重要的模板元编程技巧来支持使用 NULL
作为 EXPECT_XX()
和 ASSERT_XX()
宏的参数。因此,我们只在最需要的地方这样做(否则我们会使 GoogleTest 的实现更难维护并且更容易出错,而不是必要的)。
从历史上看,EXPECT_EQ()
宏将期望值作为其第一个参数,将实际值作为第二个参数,尽管现在不鼓励这种参数顺序。有人希望编写 EXPECT_EQ(NULL, some_expression)
是合理的,并且确实多次被要求。因此,我们实现了它。
对 EXPECT_NE(NULL, ptr)
的需求并没有那么强烈。当断言失败时,您已经知道 ptr
必须是 NULL
,因此在这种情况下打印 ptr
不会添加任何信息。这意味着 EXPECT_TRUE(ptr != NULL)
也能很好地工作。
如果我们支持 EXPECT_NE(NULL, ptr)
,为了保持一致性,我们还必须支持 EXPECT_NE(ptr, NULL)
。这意味着在实现中使用模板元编程技巧两次,使其更难理解和维护。我们认为收益不值得付出代价。
最后,随着 gMock 匹配器库的增长,我们鼓励人们在测试中更频繁地使用统一的 EXPECT_THAT(value, matcher)
语法。匹配器方法的一个显着优势是,可以轻松组合匹配器以形成新的匹配器,而 EXPECT_NE
等宏则无法轻松组合。因此,我们希望在匹配器上投入更多精力,而不是在 EXPECT_XX()
宏上投入更多精力。
我需要测试接口的不同实现是否满足一些共同的要求。我应该使用类型测试还是值参数化测试?
对于测试同一接口的各种实现,类型测试或值参数化测试都可以完成。这实际上取决于您用户来决定哪种方法对您来说更方便,具体取决于您的特定情况。一些粗略的指导原则
- 如果可以通过相同的方式创建不同实现的实例(模类型),则类型测试更容易编写。例如,如果所有这些实现都有一个公共默认构造函数(这样您就可以编写
new TypeParam
),或者如果它们的工厂函数具有相同的形式(例如CreateInstance<TypeParam>()
)。 - 如果您需要不同的代码模式来创建不同实现的实例,例如
new Foo
vsnew Bar(5)
,则值参数化测试更容易编写。为了适应这些差异,您可以编写工厂函数包装器,并将这些函数指针作为参数传递给测试。 - 当类型测试失败时,默认输出包括类型的名称,这可以帮助您快速识别哪个实现是错误的。默认情况下,值参数化测试仅显示失败的迭代次数。您需要定义一个返回迭代名称的函数,并将其作为第三个参数传递给 INSTANTIATE_TEST_SUITE_P 以获得更有用的输出。
- 使用类型测试时,您需要确保您正在针对接口类型进行测试,而不是针对具体类型(换句话说,您需要确保
implicit_cast<MyInterface*>(my_concrete_impl)
有效,而不仅仅是my_concrete_impl
有效)。使用值参数化测试时,在这种情况下不太可能出错。
我希望我没有让您更加困惑。 :-) 如果您不介意,我建议您尝试这两种方法。实践是掌握这两种工具之间细微差别的更好方法。一旦您获得了一些具体的经验,您就可以更轻松地决定下次使用哪一种。
我的死亡测试修改了一些状态,但死亡测试完成后,更改似乎丢失了。为什么?
死亡测试(EXPECT_DEATH
等)在子进程中执行,这样预期的崩溃就不会杀死测试程序(即父进程)。因此,它们产生的任何内存中的副作用都可以在它们各自的子进程中观察到,但在父进程中观察不到。您可以将它们视为或多或少在平行宇宙中运行。
特别是,如果您使用模拟并且死亡测试语句调用了一些模拟方法,则父进程会认为从未发生过这些调用。因此,您可能希望将您的 EXPECT_CALL
语句移动到 EXPECT_DEATH
宏中。
EXPECT_EQ(htonl(blah), blah_blah) 在优化模式下会生成奇怪的编译器错误。这是 GoogleTest 的 bug 吗?
实际上,bug 在于 htonl()
。
根据 'man htonl'
,htonl()
是一个函数,这意味着使用 htonl
作为函数指针是有效的。然而,在优化模式下,htonl()
被定义为一个宏,这破坏了这种用法。
更糟糕的是,htonl()
的宏定义使用了 gcc
扩展,并且不是标准 C++。这种 hack 的实现有一些特别的限制。特别是,它阻止你编写 Foo<sizeof(htonl(x))>()
,其中 Foo
是一个具有整数参数的模板。
EXPECT_EQ(a, b)
的实现使用 sizeof(... a ...)
在模板参数内部,因此当 a
包含对 htonl()
的调用时,在优化模式下无法编译。很难使 EXPECT_EQ
绕过 htonl()
的 bug,因为解决方案必须适用于各种平台上的不同编译器。
编译器抱怨某些静态 const 成员变量的“未定义的引用”,但我确实在类体中定义了它们。怎么回事?
如果你的类有一个静态数据成员
// foo.h
class Foo {
...
static const int kBar = 100;
};
你还需要在类体之外的 foo.cc
中定义它
const int Foo::kBar; // No initializer here.
否则你的代码是无效的 C++,并且可能会以意想不到的方式崩溃。特别是,在 GoogleTest 比较断言(EXPECT_EQ
等)中使用它将生成“未定义的引用”链接器错误。“它以前有效”并不意味着它是有效的。这仅仅意味着你很幸运。 :-)
如果静态数据成员的声明是 constexpr
,那么它隐式地是一个 inline
定义,并且不需要在 foo.cc
中进行单独的定义
// foo.h
class Foo {
...
static constexpr int kBar = 100; // Defines kBar, no need to do it in foo.cc.
};
我可以从另一个测试夹具派生一个测试夹具吗?
可以。
每个测试夹具都有一个对应的同名测试套件。这意味着只有一个测试套件可以使用特定的夹具。然而,有时多个测试用例可能想要使用相同或略有不同的夹具。例如,你可能想要确保 GUI 库的所有测试套件都不会泄漏重要的系统资源,如字体和画笔。
在 GoogleTest 中,你通过将共享逻辑放在一个基础测试夹具中,然后为每个想要使用此公共逻辑的测试套件从该基础派生一个单独的夹具,从而在测试套件之间共享一个夹具。然后,你使用 TEST_F()
来编写使用每个派生夹具的测试。
通常,你的代码看起来像这样
// Defines a base test fixture.
class BaseTest : public ::testing::Test {
protected:
...
};
// Derives a fixture FooTest from BaseTest.
class FooTest : public BaseTest {
protected:
void SetUp() override {
BaseTest::SetUp(); // Sets up the base fixture first.
... additional set-up work ...
}
void TearDown() override {
... clean-up work for FooTest ...
BaseTest::TearDown(); // Remember to tear down the base fixture
// after cleaning up FooTest!
}
... functions and variables for FooTest ...
};
// Tests that use the fixture FooTest.
TEST_F(FooTest, Bar) { ... }
TEST_F(FooTest, Baz) { ... }
... additional fixtures derived from BaseTest ...
如果需要,你可以继续从派生夹具派生测试夹具。GoogleTest 对层次结构的深度没有限制。
有关使用派生测试夹具的完整示例,请参阅 sample5_unittest.cc。
我的编译器抱怨“void value not ignored as it ought to be”。这意味着什么?
你可能正在一个不返回 void
的函数中使用 ASSERT_*()
。ASSERT_*()
只能在 void
函数中使用,因为我们的构建系统禁用了异常。请在此处查看更多详细信息 here。
我的死亡测试挂起(或段错误)。我该如何修复它?
在 GoogleTest 中,死亡测试在子进程中运行,它们的工作方式很微妙。要编写死亡测试,你真正需要了解它们的工作方式——请参阅断言参考中的 死亡断言中的详细信息。
特别是,死亡测试不喜欢父进程中有多个线程。因此,你可以尝试的第一件事是消除在 EXPECT_DEATH()
之外创建线程。例如,你可能想要在测试中使用模拟或伪对象而不是真实对象。
有时这是不可能的,因为你必须使用的某些库可能在甚至到达 main()
之前就创建了线程。在这种情况下,你可以尝试通过将尽可能多的活动移到 EXPECT_DEATH()
内部(在极端情况下,你想要将所有内容都移到内部),或在其中留下尽可能少的东西来尽量减少冲突的可能性。此外,你可以尝试将死亡测试样式设置为 "threadsafe"
,它更安全但更慢,看看是否有帮助。
如果你选择线程安全的死亡测试,请记住它们会在子进程中从头开始重新运行测试程序。因此,请确保你的程序可以与自身并排运行并且是确定性的。
最后,这归结为良好的并发编程。你必须确保你的程序中没有竞争条件或死锁。没有灵丹妙药 - 对不起!
我应该使用测试夹具的构造函数/析构函数还是 SetUp()/TearDown()?
首先要记住的是,GoogleTest 不会在多个测试中重用同一个测试夹具对象。对于每个 TEST_F
,GoogleTest 将创建一个新的测试夹具对象,立即调用 SetUp()
,运行测试主体,调用 TearDown()
,然后删除测试夹具对象。
当你需要编写每个测试的设置和拆卸逻辑时,你可以选择使用测试夹具构造函数/析构函数或 SetUp()
/TearDown()
。前者通常是首选,因为它具有以下优点
- 通过在构造函数中初始化成员变量,我们可以选择将其设为
const
,这有助于防止意外更改其值,并使测试更明显地正确。 - 如果我们需要对测试夹具类进行子类化,则保证子类的构造函数首先调用基类的构造函数,并且保证子类的析构函数之后调用基类的析构函数。对于
SetUp()/TearDown()
,子类可能会犯忘记调用基类的SetUp()/TearDown()
或在错误的时间调用它们的错误。
在以下情况下,你可能仍然想要使用 SetUp()/TearDown()
- C++ 不允许在构造函数和析构函数中调用虚函数。你可以调用声明为 virtual 的方法,但它不会使用动态调度。它将使用当前正在执行构造函数的类中的定义。这是因为在派生类构造函数有机会运行之前调用虚方法是非常危险的 - 虚方法可能会对未初始化的数据进行操作。因此,如果你需要调用将在派生类中重写的方法,则必须使用
SetUp()/TearDown()
。 - 在构造函数(或析构函数)的主体中,不可能使用
ASSERT_xx
宏。因此,如果设置操作可能导致应该阻止测试运行的致命测试失败,则有必要使用abort
并中止整个测试可执行文件,或者使用SetUp()
而不是构造函数。 - 如果拆卸操作可能会引发异常,你必须使用
TearDown()
而不是析构函数,因为在析构函数中引发异常会导致未定义的行为,并且通常会立即终止你的程序。请注意,许多标准库(如 STL)可能会在编译器的异常启用时引发异常。因此,如果你想编写可以在有或没有异常的情况下工作的可移植测试,你应该更喜欢TearDown()
。 - GoogleTest 团队正在考虑在启用异常的平台(例如 Windows、Mac OS 和 Linux 客户端)上使断言宏抛出异常,这将消除用户将故障从子程序传播到其调用者的需要。因此,如果你的代码可能在这样的平台上运行,则不应在析构函数中使用 GoogleTest 断言。
当我使用 ASSERT_PRED*
时,编译器抱怨“no matching function to call”。我该如何修复它?
有关详细信息,请参阅断言参考中的 EXPECT_PRED*
。
当我调用 RUN_ALL_TESTS() 时,我的编译器抱怨“ignoring return value”。为什么?
有些人一直忽略 RUN_ALL_TESTS()
的返回值。也就是说,不是
return RUN_ALL_TESTS();
他们写
RUN_ALL_TESTS();
这是错误且危险的。测试服务需要查看 RUN_ALL_TESTS()
的返回值,以便确定测试是否通过。如果你的 main()
函数忽略它,即使它有 GoogleTest 断言失败,你的测试也会被认为是成功的。非常糟糕。
我们已决定解决此问题(感谢 Michael Chastain 的想法)。现在,当使用 gcc
编译时,你的代码将不再能够忽略 RUN_ALL_TESTS()
。如果你这样做,你将收到一个编译器错误。
如果你看到编译器抱怨你忽略了 RUN_ALL_TESTS()
的返回值,则修复很简单:只需确保其值用作 main()
的返回值即可。
但是我们如何引入一个破坏现有测试的更改呢?好吧,在这种情况下,代码首先就坏了,所以我们没有破坏它。 :-)
我的编译器抱怨构造函数(或析构函数)无法返回值。发生了什么?
由于 C++ 的一个特性,为了支持将消息流式传输到 ASSERT_*
的语法,例如
ASSERT_EQ(1, Foo()) << "blah blah" << foo;
我们不得不放弃在构造函数和析构函数中使用 ASSERT*
和 FAIL*
(但不是 EXPECT*
和 ADD_FAILURE*
)。解决方法是将构造函数/析构函数的内容移动到私有 void 成员函数,或者切换到 EXPECT_*()
(如果有效)。用户指南中的这个部分对此进行了解释。
我的 SetUp() 函数未被调用。为什么?
C++ 区分大小写。你是否将其拼写为 Setup()
?
同样,有时人们将 SetUpTestSuite()
拼写为 SetupTestSuite()
,并想知道为什么它从未被调用。
我有几个测试套件共享相同的测试夹具逻辑;我是否必须为每个测试套件定义一个新的测试夹具类?这似乎很乏味。
你不必这样做。而不是
class FooTest : public BaseTest {};
TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }
class BarTest : public BaseTest {};
TEST_F(BarTest, Abc) { ... }
TEST_F(BarTest, Def) { ... }
你可以简单地 typedef
测试夹具
typedef BaseTest FooTest;
TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }
typedef BaseTest BarTest;
TEST_F(BarTest, Abc) { ... }
TEST_F(BarTest, Def) { ... }
GoogleTest 的输出被埋没在一堆 LOG 信息中。我该怎么办?
GoogleTest 的输出应该是简洁且对人友好的报告。如果你的测试本身生成了文本输出,它将与 GoogleTest 的输出混合在一起,使得难以阅读。然而,有一个简单的解决方案。
由于 LOG
信息会输出到 stderr,我们决定让 GoogleTest 输出到 stdout。这样,你可以使用重定向轻松地将两者分开。例如:
$ ./my_test > gtest_output.txt
为什么我应该优先选择测试夹具而不是全局变量?
有几个很好的理由:
- 你的测试很可能需要更改全局变量的状态。这使得难以避免副作用从一个测试逃逸并污染其他测试,从而导致调试困难。通过使用夹具,每个测试都有一组全新的变量(但具有相同的名称)。因此,测试之间保持相互独立。
- 全局变量会污染全局命名空间。
- 测试夹具可以通过子类化进行重用,而全局变量则不容易做到这一点。如果许多测试套件都有共同之处,这将非常有用。
ASSERT_DEATH()
中的 statement 参数可以是哪些内容?
ASSERT_DEATH(statement, matcher)
(或任何 death assertion 宏)可以在 statement
有效的任何地方使用。因此,基本上 statement
可以是当前上下文中任何有意义的 C++ 语句。特别是,它可以引用全局和/或局部变量,并且可以是:
- 一个简单的函数调用(通常情况);
- 一个复杂的表达式;或
- 一个复合语句。
以下是一些示例:
// A death test can be a simple function call.
TEST(MyDeathTest, FunctionCall) {
ASSERT_DEATH(Xyz(5), "Xyz failed");
}
// Or a complex expression that references variables and functions.
TEST(MyDeathTest, ComplexExpression) {
const bool c = Condition();
ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
"(Func1|Method) failed");
}
// Death assertions can be used anywhere in a function. In
// particular, they can be inside a loop.
TEST(MyDeathTest, InsideLoop) {
// Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
for (int i = 0; i < 5; i++) {
EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
::testing::Message() << "where i is " << i);
}
}
// A death assertion can contain a compound statement.
TEST(MyDeathTest, CompoundStatement) {
// Verifies that at lease one of Bar(0), Bar(1), ..., and
// Bar(4) dies.
ASSERT_DEATH({
for (int i = 0; i < 5; i++) {
Bar(i);
}
},
"Bar has \\d+ errors");
}
我有一个夹具类 FooTest
,但 TEST_F(FooTest, Bar)
给我报错 "no matching function for call to `FooTest::FooTest()'"
。为什么?
GoogleTest 需要能够创建你的测试夹具类的对象,因此它必须具有默认构造函数。通常编译器会为你定义一个。但是,在某些情况下你必须自己定义:
- 如果你显式地为类
FooTest
声明了一个非默认构造函数(DISALLOW_EVIL_CONSTRUCTORS()
会这样做),那么你需要定义一个默认构造函数,即使它是空的。 - 如果
FooTest
有一个 const 非静态数据成员,那么你必须定义默认构造函数并且在构造函数的初始化列表中初始化该 const 成员。(早期版本的gcc
不会强制你初始化 const 成员。这是在gcc 4
中已修复的错误。)
为什么 GoogleTest 要求整个测试套件(而不是单个测试)在使用 ASSERT_DEATH
时命名为 *DeathTest
?
GoogleTest 不会交错来自不同测试套件的测试。也就是说,它首先运行一个测试套件中的所有测试,然后运行下一个测试套件中的所有测试,依此类推。GoogleTest 这样做是因为它需要在运行测试套件中的第一个测试之前设置它,然后在之后将其拆除。拆分测试用例将需要多个设置和拆除过程,这是低效的并且使得语义不干净。
如果我们根据测试名称而不是测试用例名称来确定测试顺序,那么我们会遇到以下情况:
TEST_F(FooTest, AbcDeathTest) { ... }
TEST_F(FooTest, Uvw) { ... }
TEST_F(BarTest, DefDeathTest) { ... }
TEST_F(BarTest, Xyz) { ... }
由于 FooTest.AbcDeathTest
需要在 BarTest.Xyz
之前运行,并且我们不交错来自不同测试套件的测试,我们需要在运行 BarTest
用例中的任何测试之前运行 FooTest
用例中的所有测试。这与在 FooTest.Uvw
之前运行 BarTest.DefDeathTest
的要求相矛盾。
但是我不喜欢在我的整个测试套件中调用 *DeathTest
,因为它同时包含 death 测试和非 death 测试。我该怎么办?
你不必这样做,但如果你喜欢,你可以将测试套件拆分为 FooTest
和 FooDeathTest
,其中的名称清楚地表明它们是相关的。
class FooTest : public ::testing::Test { ... };
TEST_F(FooTest, Abc) { ... }
TEST_F(FooTest, Def) { ... }
using FooDeathTest = FooTest;
TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
GoogleTest 仅在 death 测试失败时才打印 death 测试子进程中的 LOG 信息。如何在 death 测试成功时看到 LOG 信息?
打印 EXPECT_DEATH()
中语句生成的 LOG 信息会使在父进程的日志中搜索真正的问题变得更加困难。因此,GoogleTest 仅在 death 测试失败时才打印它们。
如果你真的需要看到这些 LOG 信息,一种解决方法是暂时破坏 death 测试(例如,通过更改它期望匹配的正则表达式模式)。诚然,这是一种 hack。在实现 fork-and-exec 样式的 death 测试后,我们将考虑一个更永久的解决方案。
当我使用断言时,编译器抱怨 no match for 'operator<<'
。这是怎么回事?
如果你在断言中使用用户定义的类型 FooType
,你必须确保定义了一个 std::ostream& operator<<(std::ostream&, const FooType&)
函数,以便我们可以打印 FooType
的值。
此外,如果 FooType
在命名空间中声明,则 <<
运算符也需要在相同的命名空间中定义。有关详细信息,请参阅 Tip of the Week #49。
如何禁止 Windows 上的内存泄漏消息?
由于静态初始化的 GoogleTest 单例需要在堆上分配内存,因此 Visual C++ 内存泄漏检测器将在程序运行结束时报告内存泄漏。避免这种情况的最简单方法是使用 _CrtMemCheckpoint
和 _CrtMemDumpAllObjectsSince
调用来不报告任何静态初始化的堆对象。有关更多详细信息和其他堆检查/调试例程,请参阅 MSDN。
我的代码如何检测它是否正在测试中运行?
如果你编写的代码会嗅探它是否正在测试中运行并相应地执行不同的操作,那么你正在将仅测试逻辑泄漏到生产代码中,并且没有简单的方法来确保仅测试代码路径不会在生产中被错误地运行。这种聪明也导致了 Heisenbugs。因此,我们强烈建议不要这样做,并且 GoogleTest 不提供执行此操作的方法。
一般来说,推荐的导致代码在测试下表现不同的方式是 依赖注入。你可以从测试和生产代码中注入不同的功能。由于你的生产代码根本不链接到用于测试的逻辑(BUILD 目标的 testonly
属性有助于确保这一点),因此没有意外运行它的危险。
但是,如果你真的、真的、真的别无选择,并且如果你遵循以 _test
结尾测试程序名称的规则,你可以使用嗅探可执行文件名(main()
中的 argv[0]
)的可怕的 hack 来了解代码是否正在测试中运行。
如何临时禁用测试?
如果你有一个无法立即修复的损坏的测试,你可以将 DISABLED_
前缀添加到其名称中。这将使其从执行中排除。这比注释掉代码或使用 #if 0
更好,因为禁用的测试仍然会被编译(因此不会腐烂)。
要将禁用的测试包含在测试执行中,只需使用 --gtest_also_run_disabled_tests
标志调用测试程序。
如果我在不同的命名空间中定义了两个单独的 TEST(Foo, Bar)
测试方法,可以吗?
可以。
规则是同一测试套件中的所有测试方法必须使用相同的夹具类。这意味着以下内容是允许的,因为两个测试都使用相同的夹具类(::testing::Test
)。
namespace foo {
TEST(CoolTest, DoSomething) {
SUCCEED();
}
} // namespace foo
namespace bar {
TEST(CoolTest, DoSomething) {
SUCCEED();
}
} // namespace bar
但是,以下代码是不允许的,并且会产生来自 GoogleTest 的运行时错误,因为测试方法正在使用具有相同测试套件名称的不同测试夹具类。
namespace foo {
class CoolTest : public ::testing::Test {}; // Fixture foo::CoolTest
TEST_F(CoolTest, DoSomething) {
SUCCEED();
}
} // namespace foo
namespace bar {
class CoolTest : public ::testing::Test {}; // Fixture: bar::CoolTest
TEST_F(CoolTest, DoSomething) {
SUCCEED();
}
} // namespace bar