GoogleTest FAQ 中文译文

GoogleTest FAQ

为什么测试套件名称和测试名称不包含下划线?


下划线('_')是特殊的符号,因为C ++保留以下内容供编译器和标准库使用:

  1. 任何以_开头且后跟大写字母的标识符
  2. 在其名称中的任意位置包含两个连续下划线(即__)的任何标识符.

禁止用户代码使用此类标识符。

再来看这对'TEST'和'TEST_F'意味着什么。

TEST(TestSuiteName,TestName)生成一个名为TestSuite Name_TestName_Test的类。 如果TestSuiteNameTestName包含_会发生什么?

  1. 如果TestSuiteName_开头,后跟一个大写字母(例如_Foo),则以_Foo_TestName_Test结尾,这是C++保留的,所以是无效的。
  2. 如果TestSuiteName_结尾(例如Foo_),将会得到Foo__TestName_Test,这同样是无效的
  3. 如果TestName以一个_开头(比如说_Bar),将会得到`TestSuiteName__Bar_Test,是无效的
  4. 如果TestName_结尾(例如,Bar_),将得到TestSuiteName_Bar__Test,这是无效的

显然TestSuiteNameTestName不能以_作为开始和结尾(事实上,TestSuiteName可以用_作为开头,只要后面不跟着大写字母,但是这会变得复杂,所以直接规定不能以_作为开头或结尾)。

看起来可以在TestSuiteNameTestName中间使用_,但是考虑一下情况:

TEST(Time, Flies_Like_An_Arrow) { ... }
TEST(Time_Flies, Like_An_Arrow) { ... }

这两个TEST会生成同样的类名(Time_Flies_Like_An_Arrow_Test),这是不好的行为。

所以,GTEST直接简单的要求用户在TestSuiteNameTestName中避免使用_。这条规定有点过于严格,但是非常好记。还为googletest提供了一些变动的空间,以防将来需要更改其实现

如果违反该规则,则可能不会立即产生后果,但是测试可能(仅仅是可能)会因新的编译器(或您正在使用的新版本的编译器)或新版本的googletest而中断。 因此,最好遵循该规则。

为什么googletest支持EXPECT_EQ(NULL,ptr)ASSERT_EQ(NULL,ptr)但不支持EXPECT_NE(NULL,ptr)ASSERT_NE(NULL,ptr)


首先,应当使用EXPECT_NE(nullptr, ptr)ASSERT_NE(nullptr, ptr),这是样式指南中的首选语法,因为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),与EXPECT_EQ不同,在EXPECT_NE的两个参数的顺序上没有约定。这意味着在实现中需要使用两次模板元编程技巧,使它变得更加难以理解和维护,这样做的收益和成本是不合理的。

最后,随着gMock匹配器库的增长,我们鼓励人们在测试中更频繁地使用统一的EXPECT_THAT(value,matcher)语法。匹配器方法的一个重要优点是,可以轻松地将匹配器组合起来以形成新的匹配器,而EXPECT_NE等宏则无法轻松地组合。因此,要对匹配器而不是对EXPECT_XX()宏进行更多的投资。

需要测试接口的不同实现是否满足一些通用要求,应该使用类型测试还是值参数化测试

为了测试同一接口的各种实现,无论是类型测试还是值参数化测试都可以完成它。实际上,这取决于具体情况,用户可以自行决定哪种方法更为方便。这是一些粗略的准则:

  • 如果可以使用相同的方式(模板类型)创建不同实现的实例,则类型化测试更容易编写。例如,如果所有这些实现都有一个公共的默认构造函数(例如,new TypeParam),或者它们的工厂函数具有相同的形式(例如CreateInstance ())。
  • 如果需要不同的代码模式来创建不同的实现实例,则编写值参数化测试更为简单。例如new Foonew Bar(5)。为了适应差异,可以编写工厂函数包装并将这些函数指针作为其参数传递给测试。
  • 当类型化测试失败时,默认输出将包括类型名称,这可以帮助用户快速确定哪个实现是错误的。 值参数化测试默认情况下仅显示失败的迭代次数。需要定义一个函数,该函数返回迭代名称并将其作为第三个参数传递给INSTANTIATE_TEST_SUITE_P,以获得更多有用的输出。
  • 使用类型化测试时,需要确保针对接口类型进行测试,而不是针对具体类型进行测试(换句话说,要确保implicit_cast (my_concrete_impl)有效,而不仅仅是my_concrete_impl有效)。 使用值参数化的测试时,在这一方面犯错误的可能性较小。

希望我不要再让您感到困惑,如果不介意,建议尝试两种方法。练习是掌握两种工具之间细微差异的更好方法。一旦有了一些具体的经验,就可以轻松地决定下一次使用哪个。

使用ProtocolMessageEquals时,出现一些有关无效原型描述符的运行时错误。

注意:不推荐使用ProtocolMessageEqualsProtocolMessageEquiv。请改用EqualsProto等。

最近重新定义了ProtocolMessageEqualsProtocolMessageEquiv,现在对无效的协议缓冲区定义的容忍度较低。特别是,如果foo.proto不能完全限定其引用的协议消息的类型(例如message ,应为message ),则现在会出现运行时错误,例如:

... descriptor.cc:...] Invalid proto descriptor for file "path/to/foo.proto":
... descriptor.cc:...]  blah.MyMessage.my_field: ".Bar" is not defined.

如果看到此消息,则说明.proto文件已损坏,需要通过使类型完全合格来修复。ProtocolMessageEqualsProtocolMessageEquiv的新定义恰好揭示了这个错误。

死亡测试修改了某些状态,但是在死亡测试完成后,更改似乎丢失了。为什么?

死亡测试(EXPECT_DEATH等)在子过程中执行,预期的崩溃不会终止测试程序(即父进程)。结果,它们引起的任何内存中副作用都可以在其各自的子过程中观察到,但在父过程中却无法观察到。 可以将它们视为在平行宇宙中运行。

特别是,如果使用mock并且死亡测试语句调用了一些mock方法,则父进程将认为调用从未发生。 因此,可能需要在EXPECT_DEATH宏内移动EXPECT_CALL语句。

EXPECT_EQ(htonl(blah),blah_blah)在opt模式下生成奇怪的编译器错误。这是googletest错误吗?

事实上,是htonl()的错误。

根据'man htonl'的说法,htonl()是一个函数,这意味着将htonl用作函数指针是有效的。但是,在opt模式下,htonl()被定义为宏,这破坏了这种用法。

更糟糕的是,htonl()的宏定义使用gcc扩展,而不是标准的C++。这种骇人听闻的实现有一些特殊的限制。 特别是,它阻止编写Foo (),其中Foo是具有一个必要的参数的模板。

EXPECT_EQ(a,b)的实现在模板参数中使用sizeof(... a ...),因此当a包含对htonl()的调用时,不会在opt模式下编译。很难使EXPECT_EQ绕过htonl()错误,因为该解决方案必须与各种平台上的不同编译器一起使用。

htonl()还有其他问题,如//util/endian/endian.h中所述,该文件定义了ghtonl()来替换它。ghtonl()所做的事情与htonl()相同,只是没有htonl的问题。所以建议在测试和生产代码中都使用ghtonl()而不是htonl()

//util/endian/endian.h还定义了ghtons(),它解决了htons()中的类似问题。

不要忘记将//util/endian添加到ghtonl()ghtons()使用的BUILD文件中的依赖项列表中。该库仅包含一个头文件,不会使二进制文件体积增大。

编译器抱怨某些静态const成员变量的“未定义引用”,但我确实在类主体中定义了它们。发生了什么?

如果类有一个静态数据成员:

// foo.h
class Foo {
  ...
  static const int kBar = 100;
};

还需要在foo.cc的类主体之外定义这个成员。

const int Foo::kBar;  // No initializer here.

否则代码就是不合法的C++,并且会以意想不到的方式停止。特别是,在googletest比较断言(EXPECT_EQ等)中使用它会生成“未定义引用”链接器错误。“它曾经起作用”的事实并不意味着它是有效的。这只是意味着上次很幸运。

可以从一个test fixture派生出另一个test fixture吗?

是的。

每个test fixture都有一个对应的相同的命名测试套件。这意味着只有一个测试套件可以使用特定的fixture。有时多个测试可能希望使用相同或略有不同的fixture。例如,可能要确保所有GUI库的测试套件都不会泄漏重要的系统资源,像是字体和画笔。

在googletest中,可以通过将共享逻辑放在基本test fixture中来在测试套件之间共享fixture,然后从父类中为每个要使用此通用逻辑的测试套件派出单独的fixture。 然后,就可以使用TEST_F()使用每个派生的fixture编写测试。

例如:

// 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 ...

如果有必要,还可以从派生出来的test fixture中继续派生出test fixture。Gtest对继承的层数没有限制。

编译器会提示“void值没有被忽略”。这是什么意思

可能在一个返回值不是void的函数中使用了ASSERT_*()ASSERT_*()仅可在void函数中使用,因为构建系统已禁用了异常。

死亡测试挂起(或段错误)。如何解决它?

在googletest中,死亡测试是在子进程中运行的,并且它们的工作方式很精细。要编写死亡测试,确实需要了解它们如何工作。

死亡测试不提倡父进程中具有多个线程。因此,可以尝试做的第一件事是不在EXPECT_DEATH()之外创建线程。例如,可能想在测试中使用模拟或伪造的对象,而不是真实的对象。

有时这是不可能的,因为必须使用的某些库可能在到达main()之前创建线程。在这种情况下,可以尝试通过移动尽可能多的活动到EXPECT_DEATH()内(在极端情况下,将所有内容移动到内部)或在其中保留尽可能少的内容来最大程度地减少冲突的机会。另外,可以尝试将死亡测试类型设置为 “threadsafe”,这比较安全但速度会降低。

如果使用线程安全的死亡测试,请记住它们从子进程的开头重新运行测试程序。因此,请确保程序可以与自身并行,并且具有确定性。

最后,要编写良好的并发编程,必须确保程序中没有争用条件或死锁。

应该使用Test Fixture的构造函数/析构函数还是SetUp()/TearDown()?

要记住的第一件事是,googletest不会在多个测试中重用同一test fixture对象。对于每个TEST_F,googletest将创建一个新的test fixture对象,调用SetUp(),运行测试主体,调用TearDown(),最后删除test fixture对象。

当需要编写每个测试的set_uptear_down逻辑时,可以选择使用test fixture构造器/析构器或者SetUp()/ TearDown()。通常首选前者,因为它具有以下优点:

  • 通过在构造函数中初始化成员变量,我们可以选择使其为const,这有助于防止对其值进行意外更改并使测试更明显正确。
  • 如果需要对test fixture类进行子类化,则可以保证子类的构造函数首先调用基类的构造函数,而子类的析构函数则可以保证随后调用基类的析构函数。如果使用SetUp()/TearDown(),子类可能会忘记调用基类的SetUp()/ TearDown()或在错误的时间调用它们。

在以下情况下,可能仍要使用SetUp()/ TearDown()

  • C ++不允许在构造函数和析构函数中调用虚函数。你可以调用一个声明为virtual的方法,但它不会使用动态分配,而是使用当前正在执行其构造函数的类中的定义。这是因为在派生类构造函数运行之前调用虚方法非常危险---虚方法可能会对未初始化的数据进行操作。因此,如果需要调用将在派生类中重写的方法,则必须使用SetUp()/ TearDown()
  • 在构造函数(或析构函数)的主体中,无法使用ASSERT_xx宏。因此,如果set-up操作可能导致致命失败,从而导致测试无法运行,则必须使用abort并中止整个测试可执行文件,或者使用SetUp()代替构造函数。
  • 如果tear-down操作可能引发异常,则必须使用TearDown()而不是析构函数,因为抛出析构函数会导致未定义的行为,通常会立即终止程序。请注意,在编译器中启用异常时,可能会引发许多标准库(如STL)抛出异常。因此,如果要编写可在有或没有异常的情况下运行的可移植测试,则应首选TearDown()
  • googletest小组正在考虑使断言宏在启用了异常的平台(例如Windows,Mac OS和Linux客户端)上抛出异常,这将消除用户将故障从子例程传播到调用者的需求。如果代码可以在这样的平台上运行,则不应在析构函数中使用googletest断言。

当使用ASSERT_PRED*时,编译器会报错“no matching function to call”。

如果在ASSERT_PRED*EXPECT_PRED*中使用的谓词函数已重载或是一个模板,那么编译器将难以确定应使用哪个重载版本。使用ASSERT_PRED_FORMAT*EXPECT_PRED_FORMAT*则没有此问题。

如果看到此错误,则可能要切换到(ASSERT|EXPECT)_PRED_FORMAT*,这样也会输出更丰富的失败消息。如果不能选择使用上述的宏,则可以通过明确告诉编译器选择哪个版本来解决该问题。

例如:

bool IsPositive(int n) {
  return n > 0;
}

bool IsPositive(double x) {
  return x > 0;
}

如果你如下编写代码将会出现一个编译错误:

EXPECT_PRED1(IsPositive, 5);

但是像下面这样写就会正常工作:

EXPECT_PRED1(static_cast(IsPositive), 5);

static_cast运算符的尖括号内的内容是IsPositive()int版本的函数指针的类型。

另外一个例子,如果有一个模板函数:

template 
bool IsNegative(T x) {
  return x < 0;
}

可以在谓词断言中使用它:

ASSERT_PRED1(IsNegative, -5);

有趣的是,如果你的模板多余一个参数,那么下面的代码将不会编译:

ASSERT_PRED2(GreaterThan, 5, 0);

因为C++预处理认为给ASSERT_PRED2传递了4个参数,超出了宏的期望。解决方法就是将谓词函数用括号括起来:

ASSERT_PRED2((GreaterThan), 5, 0);

当调用RUN_ALL_TESTS()的时候,编译器报错"ignoring return value"

有些人忽视了RUN_ALL_TESTS的返回值,将:

return RUN_ALL_TESTS();

写作:

RUN_ALL_TESTS();

这样做是错误且危险的,测试服务需要获取RUN_ALL_TESTS()的返回值来确定测试是否通过。如果main()忽视了它,就算是googletest断言失败了,测试也会认为测试成功了,这是非常严重的错误。

现在,当使用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(),这也会导致它不会被调用。

我有几个共享相同test fixture逻辑的测试套件,是否必须为每个套件定义一个新的test fixture类?

不需要,可以使用:

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

为什么相比于全局变量,应该优先使用test fixture

有以下几点好处:

  1. 测试可能需要更改其全局变量的状态。这使得该测试产生的副作用污染其他测试变得不可避免,从而导致调试困难。通过使用fixture,每个测试都有一组不同的新变量(但名称相同),测试保持彼此独立。
  2. 全局变量污染全局命名空间
  3. Test fixture可以通过子类重用,而全局变量却不行。这在许多测试套件都有相似点的时候十分有用。

ASSERT_DEATH()宏里面的statement参数可以使什么

ASSERT_DEATH(statement, matcher)或者其他的死亡测试宏可以使用任意合法的statementstatement可以是任意在当前上下文有意义的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 any where 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");
}

已经存在一个fixture类FooTest,但是TEST_F(FooTest,Bar)报了一个错"no matching function for call to 'FooTest::FooTest()'"

GoogleTest需要能够创建test fixture的对象,所以该类需要有一个默认构造器。通常编译器会定义一个,但是也有以下情况需要自己定义:

  • 如果为类FooTest显式声明了一个非默认构造函数(DISALLOW_EVIL_CONSTRUCTORS()会执行此操作),那么则即使为空,也需要定义一个默认构造函数。
  • 如果FooTest具有const非静态数据成员,则必须定义默认构造函数,并在构造函数的初始值设定项列表中初始化const成员。(早期版本的gcc不会强制初始化const成员。这是gcc4中修复的错误。)

为什么ASSERT_DEATH会提示已有先前加入的线程

使用Linux pthread库,一旦从单线程过渡到多线程,就再也没有回头路了。第一次创建线程时,还会另外创建一个管理器线程,因此将获得3个线程,而不是2个线程。稍后,当创建的线程加入主线程时,线程计数将减少1,但是管理器线程将永远不会被杀死,因此仍然拥有2个线程,这意味着无法安全地运行死亡测试。新的NPTL线程库不会遇到此问题,因为它不会创建管理器线程。

在使用ASSERT_DEATH时,为什么GTEST需要将整个测试套件都命名成*DeathTest

googletest不会交替运行不同测试套件中的测试。也就是说,它首先在一个测试套件中运行所有测试,然后在下一测试套件中运行所有测试,依此类推。googletest之所以这样做,是因为它需要在运行第一个测试之前先建立一个测试套件,然后将其拆掉。拆分测试用例将需要多个set-up和tear-down的过程,这使得效率低下并且语义不清晰。

如果要根据测试名称而不是测试用例名称来确定测试的顺序,那么以下情况将有问题:

TEST_F(FooTest, AbcDeathTest) { ... }
TEST_F(FooTest, Uvw) { ... }

TEST_F(BarTest, DefDeathTest) { ... }
TEST_F(BarTest, Xyz) { ... }

由于FooTest.AbcDeathTest需要在BarTest.Xyz之前运行,并且不会交替运行来自不同测试套件的测试,因此需要在FooTest案例中运行所有测试,然后再在BarTest案例中运行任何测试。这与在FooTest.Uvw之前运行BarTest.DefDeathTest的要求相矛盾。

当测试套件中既含有死亡测试也含有非死亡测试时,不希望将测试套件命名为*DeathTest怎么办

可以将测试套件分成FooTestFooDeathTest两部分:

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(...) ... }

GTEST仅在死亡测试失败时在子进程中打印log信息,如何在死亡成功时查看log信息

打印由EXPECT_DEATH()内部的语句生成的LOG消息将使得在父级日志中搜索实际问题变得更加困难。因此googletest仅在死亡测试失败时才打印它们。

如果确实需要查看此类LOG消息,一种解决方法是暂时终止死亡测试(例如,通过更改预期匹配的正则表达式模式)。在执行fork-and-exec式死亡测试之后,我们将考虑一个更永久的解决方案。

当使用断言是,编译器报错"no matching for 'operator<<",是什么意思

如果在断言中使用了一个用户定义的类型FooType,那么必须确它有一个std::ostream& operator<<(std::ostream&, const FooType&)函数来打印FooType的值。

如果FooType在一个命名空间里面声明,<<操作符也需要在相同的命名空间里定义。

如何禁止Windows上的内存泄露信息

由于静态初始化的googletest单例需要在堆上进行分配,因此Visual C ++内存泄漏检测器将在程序运行结束时报告内存泄漏。避免这种情况的最简单方法是使用_CrtMemCheckpoint_CrtMemDumpAllObjectsSince调用以不报告任何静态初始化的堆对象。

如何编写代码检测一个测试是否正在运行

如果编写的代码会嗅探它是否正在测试中运行,并相应地执行其他操作,那么会将测试逻辑泄漏到生产代码中,并且没有简单的方法来确保纯测试代码路径不会在生产中错误地运行。这种机灵也导致了Heisenbugs。因此强烈建议不要采取这种做法,而googletest则没有提供这样做的方法。

通常,推荐的导致代码在测试中表现不同的方法是依赖注入。可以从测试和生产代码中注入不同的功能。由于生产代码根本没有链接到for-test逻辑中(BUILD目标的testonly属性有助于确保这一点),因此意外运行它不会有危险。

如果真的别无选择,并且遵循以_test结束测试程序名称的规则,则可以使用可怕的方法嗅探可执行文件名称(main()中的argv [0])来知道代码是否正在测试中。

如何暂时的禁止一个测试

如果您有无法立即修复的损坏测试,则可以在其名称中添加DISABLED_前缀。这会将其从执行中排除。这比注释掉代码或使用#if 0更好,因为仍会编译禁用的测试。

要将禁用的测试包括在测试执行中,只需使用--gtest_also_run_disabled_tests标志调用测试程序。

在两个不同的命名空间中定义两个不同的TEST(Foo,Bar)方法是否可行

规则是同一测试套件中的所有测试方法必须使用相同的test fixture类。这意味着允许进行以下操作,因为两个测试都使用相同的fixture类(:: testing :: Test)。

namespace foo {
TEST(CoolTest, DoSomething) {
  SUCCEED();
}
}  // namespace foo

namespace bar {
TEST(CoolTest, DoSomething) {
  SUCCEED();
}
}  // namespace bar

但是,以下代码是不允许的,并且会由于googletest产生运行时错误,因为测试方法使用具有相同测试套件名称的不同test fixture类。

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

你可能感兴趣的:(GoogleTest FAQ 中文译文)