当前位置: 美高梅集团手机版 > 美高梅集团 > 正文

此宏会将当前文件名、行号和给定消息添加到每

时间:2020-03-27 23:33来源:美高梅集团
1. 数据供给器 Google C++单元测试框架GoogleTest---AdvancedGuide(译文)下,advancediqtest 因为AdvancedGuide文档太长,分上下两部分,本文档接googletest--AdvancedGuide(译文)上:GoogleC++单元测试框架

1. 数据供给器

Google C++单元测试框架GoogleTest---AdvancedGuide(译文)下,advancediqtest

因为AdvancedGuide文档太长,分上下两部分,本文档接googletest--AdvancedGuide(译文)上:Google C++单元测试框架GoogleTest---AdvancedGuide(译文)上。

用来提供参数和结果,使用 @dataProvider 标注来指定使用哪个数据供给器方法。例如检测app升级数据是否符合预期,addProviderAppUpdateData()提供测试的参数和结果。testAppUpdateData返回的结果是否和给定的预期结果相等,即如果$appId='apple_3.3.2_117', $result=['status' => 0, 'isIOS' => false], 则$data中如果含有['status' => 0, 'isIOS' => false], 则断言成功。建议在数据提供器,逐个用字符串键名对其命名,这样在断言失败的时候将输出失败的名称,更容易定位问题

一、在子程序中使用断言(Using Assertions in Sub-routines)

1.1 将跟踪添加到断言

如果从几个地方调用测试子程序,当其中的断言失败时,可能很难判断失败来自哪个子程序的调用。 您可以使用额外的日志或自定义失败消息缓解这个问题,但通常会堵塞您的测试。 更好的解决方案是使用SCOPED_TRACE宏:

SCOPED_TRACE(message);

messsage可以是任何可以流入std::ostream的东西。此宏会将当前文件名、行号和给定消息添加到每个失败消息中。 当控件离开当前词法作用域时,效果将被撤消。

For example,

 void Sub1(int n) {
   EXPECT_EQ(1, Bar(n));
   EXPECT_EQ(2, Bar(n + 1));
 }

 TEST(FooTest, Bar) {
   {
     SCOPED_TRACE("A");  // This trace point will be included in
                         // every failure in this scope.
     Sub1(1);
   }//到这SCOPED_TRACE的作用域就结束。
   // Now it won't.
   Sub1(9);//都调用了子程序Sub1
 }

可能会导致这样的消息:

path/to/foo_test.cc:11: Failure
Value of: Bar(n)
Expected: 1
  Actual: 2
   Trace:
path/to/foo_test.cc:17: A

path/to/foo_test.cc:12: Failure
Value of: Bar(n + 1)
Expected: 2
  Actual: 3

没有跟踪,很难知道两个失败分别来自哪个Sub1()的调用。 (你可以在Sub1()中为每个断言添加一个额外的消息,以指示n的值,但这很乏味。)

关于使用SCOPED_TRACE的一些提示:

没有跟踪,很难知道两个失败分别来自哪个Sub1()的调用。 (你可以在Sub1()中为每个断言添加一个额外的消息,以指示n的值,但这很乏味。)

关于使用SCOPED_TRACE的一些提示:

  • 使用合适的消息,通常足以在子例程的开头使用SCOPED_TRACE,而不是在每个调用站点。
  • 当调用循环内的子例程时,使循环迭代器成为SCOPED_TRACE中的消息的一部分,以便您可以知道失败来自哪个迭代。
  • 有时,跟踪点的行号足以识别子例程的特定调用。在这种情况下,您不必为SCOPED_TRACE选择唯一的消息。你可以简单地使用“”。
  • 当外部作用域中有一个SCOPED_TRACE时,可以在内部作用域中使用SCOPED_TRACE。在这种情况下,所有活动跟踪点将按照遇到的相反顺序包含在失败消息中。
  • 跟踪转储是可以在Emacs的编译缓冲区中点击 - 命中返回行号,你会被带到源文件中的那一行!
appUpdateData(); $this->assertTrue(count(array_intersect_assoc == count; } public function addProviderAppUpdateData() { return [ 'null' => [null, ['status' => 0, 'isIOS' => false, 'latest_version' => 'V']], 'error app id' => ['sdas123123', ['status' => 0, 'isIOS' => false, 'latest_version' => 'V']], 'android force update' => ['bx7_3.3.5_120', ['status' => 0, 'isIOS' => false]], 'ios force update' => ['apple_3.3.2_117', ['status' => 1, 'isIOS' => true]], 'android soft update' => ['sanxing_3.3.2_117', ['status' => 2, 'isIOS' => false]], 'ios soft update' => ['apple_3.3.3_118', ['status' => 2, 'isIOS' => true]], 'android normal' => ['fhqd_3.3.6_121', ['status' => 1, 'isIOS' => false]], 'ios normal' => ['apple_3.3.5_120', ['status' => 1, 'isIOS' => true]], 'h5' => ['h5_3.3.3', ['status' => 1, 'isIOS' => false]] ]; } }

1.2 传播致命失败

使用ASSERT_ *和FAIL *时的常见陷阱认为当它们失败时,它们会中止整个测试。 例如,以下测试将会导致错误:

void Subroutine() {
  // Generates a fatal failure and aborts the current function.
  ASSERT_EQ(1, 2);//失败时只是终止当前函数
  // The following won't be executed.
  ...
}

TEST(FooTest, Bar) {
  Subroutine();
  // The intended behavior is for the fatal failure
  // in Subroutine() to abort the entire test.
  // The actual behavior: the function goes on after Subroutine() returns.
  //  实际行为:函数在Subroutine()返回后继续。
  int* p = NULL;
  *p = 3; // Segfault!产生一个错误
} 

由于我们不使用异常,因此在技术上不可能在这里实现预期的行为。 为了减轻这种情况,Google测试提供了两种解决方案。 您可以使用(ASSERT | EXPECT)_NO_FATAL_FAILURE断言或HasFatalFailure()函数。 它们在以下两个小节中描述。

2. 断言方法

1.3在子程序中的断言(Asserting on Subroutines)

美高梅集团手机版,如上所示,如果你的测试调用了一个有ASSERT_ *失败的子程序,测试将在子程序返回后继续。 这可能不是你想要的。

通常人们希望致命的失败传播像异常一样。 为此,Google测试提供以下宏:

Fatal assertion Nonfatal assertion Verifies
ASSERT_NO_FATAL_FAILURE(statement); EXPECT_NO_FATAL_FAILURE(statement); statement doesn't generate any new fatal failures in the current thread.

仅检查执行断言的线程中的失败,以确定这种类型的断言的结果。 如果语句创建新线程,这些线程中的失败将被忽略。

例如:

ASSERT_NO_FATAL_FAILURE(Foo());

int i;
EXPECT_NO_FATAL_FAILURE({
  i = Bar();
}); 

常用有assertTrue, assertNull, assertThat()。

1.4检查当前测试中的故障

  :: test :: Test类中的HasFatalFailure(): 如果当前测试中的断言遭遇致命故障,则返回true。 这允许函数捕获子例程中的致命故障并及早返回。

class Test {
 public:
  ...
  static bool HasFatalFailure();
};

 典型的用法,基本上模拟抛出的异常的行为是:

TEST(FooTest, Bar) {  
    Subroutine();  // Aborts if Subroutine() had a fatal failure. 
   if (HasFatalFailure())    
     return;  
   // The following won't be executed. 
   ...
}

HasFatalFailure如果在TEST(),TEST_F()或测试夹具之外使用,则必须添加:: testing :: Test ::前缀,如: 

if (::testing::Test::HasFatalFailure())
  return;

类似的,HasNonfatalFailure():如果当前测试至少有一个非致命失败,返回true。

HasFailure() :如果当前测试至少有一个失败,返回true。

assertThat、isTrue、isInstanceOf、logicalAnd()。例如检测返回的结果是否是null或ApiApp类。

二、记录其他信息Logging Additional Information

在测试代码中,可以调用RecordProperty(“key”,value)来记录附加信息,其中value可以是字符串或int。 如果指定一个键,则为键记录的最后一个值将发送到XML输出。

例如

TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
  RecordProperty("MaximumWidgets", ComputeMaxUsage());
  RecordProperty("MinimumWidgets", ComputeMinUsage());
}

will output XML like this:

...
  <testcase name="MinAndMaxWidgets" status="run" time="6" classname="WidgetUsageTest"
            MaximumWidgets="12"
            MinimumWidgets="9" />
...

注意:

  • RecordProperty()是Test类的静态成员。 因此,如果在TEST体和测试夹具类之外使用,则需要使用前缀:: testing :: Test ::
  • 键必须是有效的XML属性名称,且不能与Google Test(名称,状态,时间,类名,类型_参数和值_参数)已使用的键冲突。
  • 允许在测试的生命周期之外调用RecordProperty()。 如果它在测试之外调用,但在测试用例的SetUpTestCase()和TearDownTestCase()方法之间调用,它将被归因于测试用例的XML元素。 如果在所有测试用例之外调用(例如在测试环境中),它将被归因于顶级XML元素。
assertThat($result, $this->logicalOr, $this->isInstanceOf; } public function additionProviderGetLatestUpdateAppApi() { return [ 'apple' => [1], 'android' => [2], 'null' => [9999] ]; } }

三、在同一测试用例中的测试之间共享资源

Google Test为每个测试创建一个新的测试夹具对象,以使测试独立,更容易调试。 然而,有时测试使用昂贵的资源设置,使得单拷贝测试模型过于昂贵。

如果测试不更改资源,则它们在共享单个资源副本中没有任何危害。 因此,除了每次测试的set-up/tear-down,Google测试还支持每个测试用例的set-up/tear-down。 使用它:

  • 在你的测试夹具类(比如FooTest)中,定义一些成员变量来保存共享资源。
  • 在同一个测试夹具类中,定义一个静态void SetUpTestCase()函数(记住不要拼写它作为一个小u的SetupTestCase)来设置共享资源和静态void TearDownTestCase()函数来删除它们。

OK! 在运行FooTest测试用例中的第一个测试(即在创建第一个FooTest对象之前)之前,Google Test自动调用SetUpTestCase(),并在运行最后一个测试之后(即删除最后一个FooTest对象后)调用TearDownTestCase()。 在其间,测试可以使用共享资源。

记住测试顺序是未定义的,所以你的代码不能依赖于另一个之前或之后的测试。 此外,测试必须不能修改任何共享资源的状态,或者,如果它们修改状态,则它们必须在将控制传递给下一个测试之前将状态恢复到其原始值。

Here's an example of per-test-case set-up and tear-down:

class FooTest : public ::testing::Test {
 protected:
  // Per-test-case set-up.
  // Called before the first test in this test case.
  // Can be omitted if not needed.
  static void SetUpTestCase() {
    shared_resource_ = new ...;
  }

  // Per-test-case tear-down.
  // Called after the last test in this test case.
  // Can be omitted if not needed.
  static void TearDownTestCase() {
    delete shared_resource_;
    shared_resource_ = NULL;
  }

  // You can define per-test set-up and tear-down logic as usual.
  virtual void SetUp() { ... }
  virtual void TearDown() { ... }

  // Some expensive resource shared by all tests.
  static T* shared_resource_;
};

T* FooTest::shared_resource_ = NULL;

TEST_F(FooTest, Test1) {
  ... you can refer to shared_resource here ...
}
TEST_F(FooTest, Test2) {
  ... you can refer to shared_resource here ...
}

3. 对异常进行测试

四、Global Set-Up and Tear-Down

正如你可以在测试级别和测试用例级别设置和拆卸,您也可以在测试程序级别执行。

首先,你要继承:: testing :: Environment类来定义一个测试环境:

class Environment {
 public:
  virtual ~Environment() {}
  // Override this to define how to set up the environment.
  virtual void SetUp() {}
  // Override this to define how to tear down the environment.
  virtual void TearDown() {}
};

然后,通过调用:: testing :: Add Global Test Environment()函数,注册我们的环境类的实例:

Environment* AddGlobalTestEnvironment(Environment* env);

现在,当调用RUN_ALL_TESTS()时,它首先调用环境对象的SetUp()方法,然后如果没有致命失败则运行测试,最后调用环境对象的TearDown()。

注册多个环境对象是可以的。 在这种情况下,他们的SetUp()将按照它们注册的顺序被调用,并且它们的TearDown()将以相反的顺序被调用。

请注意,Google测试会对注册的环境对象拥有所有权。 因此,不要自己删除它们。

您应该在调用RUN_ALL_TESTS()之前调用AddGlobalTestEnvironment(),可能在main()中调用。 如果你使用gtest_main,你需要在main()启动之前调用它才能生效。 一种方法是定义一个全局变量,如下所示:

::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new FooEnvironment); 

但是,我们强烈建议您编写自己的main()并调用AddGlobalTestEnvironment(),因为依赖于全局变量的初始化使代码更难读取,并且可能会导致问题,当您从不同的转换单元注册多个环境, 它们之间的依赖性(记住编译器不保证来自不同转换单元的全局变量的初始化顺序)。

使用expectExceptionCode()对错误码进行检测,不建议对错误信息文案进行检测。例如检测设备被锁后是否抛出3026错误码。

 五、值参数化测试

//这个功能挺复杂,专门写在一个单独的文档解析:

 

expectExceptionCode; Cache::put('device-login-error-account-', '1,2,3,4,5', 300); UserSecurityService::$request = null; UserSecurityService::$udid = null; UserSecurityService::deviceCheck; } }

 六、类型测试

假设您有一个接口的多个实现,并希望确保所有这些都满足一些常见的要求。 或者,您可能定义了几个类型,它们应该符合相同的“概念”,并且您想要验证它。 在这两种情况下,您都希望为不同类型重复相同的测试逻辑。 

 虽然你可以为你想测试的每个类型写一个TEST或TEST_F(你甚至可以把测试逻辑放入你从TEST调用的函数模板),它是乏味的,不缩放:如果你想要m个测试 n类型,你最终会写m * n TESTs。

类型测试允许您在类型列表上重复相同的测试逻辑。 你只需要写一次测试逻辑,虽然在写类型测试时你必须知道类型列表。 以下是您的操作方法:

1. 定义一个fixture类模板。 它应该由一个类型参数化。 记住继承:: testing :: Test:

template <typename T>
class FooTest : public ::testing::Test {
 public:
  ...
  typedef std::list<T> List;
  static T shared_;
  T value_;
};

2. 将类型列表与测试用例相关联,这将针对列表中的每个类型重复:

typedef ::testing::Types<char, int, unsigned int> MyTypes;
TYPED_TEST_CASE(FooTest, MyTypes);

typedef对于TYPED_TEST_CASE宏正确解析是必要的。 否则编译器会认为类型列表中的每个逗号引入一个新的宏参数。

3. 使用TYPED_TEST()而不是TEST_F()为此测试用例定义一个类型测试。 您可以根据需要重复此操作次数:

TYPED_TEST(FooTest, DoesBlah) {
  // Inside a test, refer to the special name TypeParam to get the type
  // parameter.  Since we are inside a derived class template, C++ requires
  // us to visit the members of FooTest via 'this'.
  TypeParam n = this->value_;

  // To visit static members of the fixture, add the 'TestFixture::'
  // prefix.
  n += TestFixture::shared_;

  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
  // prefix.  The 'typename' is required to satisfy the compiler.
  typename TestFixture::List values;
  values.push_back(n);
  ...
}

TYPED_TEST(FooTest, HasPropertyA) { ... }

You can see samples/sample6_unittest.cc for a complete example.

4. 测试私有属性和私有方法使用反射机制

七、类型参数化测试

在不知道类型参数的情况下编写测试--- 这就是“类型参数化测试”。

类型参数化测试类似于类型测试,除了它们不需要预知类型列表。 相反,您可以首先定义测试逻辑,然后使用不同类型列表实例化它。 你甚至可以在同一个程序中多次实例化它。

如果您正在设计一个接口或概念,则可以定义一组类型参数化测试,以验证接口/概念的任何有效实现应具有的属性。 然后,每个实现的作者可以使用他的类型来实例化测试套件,以验证它符合需求,而不必重复地编写类似的测试。 这里有一个例子:

1. 定义一个fixture类模板,就像我们用类型测试一样:

First, define a fixture class template, as we did with typed tests:

template <typename T>
class FooTest : public ::testing::Test {
  ...
};

2. 声明你要定义的类型参数化测试用例:

TYPED_TEST_CASE_P(FooTest);

这个后缀P代表参数化或模式,随你怎么想。

  1. 使用TYPED_TEST_P()来定义类型参数化测试。您可以根据需要重复多次:

    TYPED_TEST_P(FooTest, DoesBlah) { // Inside a test, refer to TypeParam to get the type parameter. TypeParam n = 0; ... }

    TYPED_TEST_P(FooTest, HasPropertyA) { ... }

现在棘手的部分:您需要使用REGISTER_TYPED_TEST_CASE_P宏注册所有测试模式,然后才能实例化它们。

宏的第一个参数是测试用例名称; 其余的是在这个测试用例中的测试的名称

REGISTER_TYPED_TEST_CASE_P(FooTest,
                           DoesBlah, HasPropertyA);

最后,你可以用你想要的类型来实例化模式。 如果你把上面的代码放在头文件中,你可以在多个C ++源文件#include它,并实例化多次。

typedef ::testing::Types<char, int, unsigned int> MyTypes;
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);

为了区分模式的不同实例,INSTANTIATE_TYPED_TEST_CASE_P宏的第一个参数是将添加到实际测试用例名称中的前缀。 请记住为不同实例选择唯一前缀

在类型列表只包含一个类型的特殊情况下,您可以直接编写该类型,而不使用:: testing :: Types <...>,如下所示:

INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);

ou can see samples/sample6_unittest.cc for a complete example.

**类型测试与类型参数化的区别:

1. 类型测试是你知道所有的类型,把所有类型注册,实例化测试。

2. 类型参数化是你是接口的定义者,知道每个接口函数的基本功能,而它的具体实现可以在将来被   人实现,你可以提前定义好测试用例,然后把所有的测试注册。

如果只测试私有方法可使用ReflectionMethod()反射方法,使用setAccessible设置方法可访问,并使用invokeArgs调用方法。例如检测IP是否在白名单中。

八、测试private修饰的代码

如果您更改软件的内部实现,只要用户不能观察到这种变化,您的测试就不会中断。 因此,根据黑盒测试原则,大多数时候你应该通过其公共接口测试你的代码。

如果你仍然发现自己需要测试内部实现代码,考虑是否有一个更好的设计,不需要你这样做。 如果你必须测试非公共接口代码。 有两种情况需要考虑:

  •  静态函数(不同于静态成员函数!)或未命名的命名空间
  •  私人或受保护的类成员
namespace AppFacadesServices; /** * Class WebDefender */ class WebDefenderService extends BaseService { //ip白名单 private $ipWhiteList = [ '10.*', '172.18.*', '127.0.0.1' ]; /** * ip是否在白名单中 * * @param string $ip * * @return bool */ private function checkIPWhiteList { if (!$this->ipWhiteList || !is_array { return false; } foreach ($this->ipWhiteList as $item) { if (preg_match { return true; } } return false; } }

setAccessible; $this->assertEquals($result, $checkIPWhiteList->invokeArgs(new WebDefenderService; } public function additionProviderIp() { return [ '10 ip' => ['10.1.1.7', true], '172 ip' => ['172.18.2.5', true], '127 ip' => ['127.0.0.1', true], '192 ip' => ['192.168.0.1', false] ]; } }

 1. 静态函数

未命名的命名空间中的静态函数和定义/声明仅在同一转变单元中可见。要测试它们,您可以在你的* _test.cc文件中include 要测试的整个.cc文件。 (#include .cc文件不是重用代码的好方法 - 你不应该在生产代码中这样做!)

然而,更好的方法是将私有代码移动到foo :: internal命名空间中,其中foo是你项目通常使用的命名空间,并将私有声明放在* -internal.h文件中。允许您的生产.cc文件和测试包括此内部标头,但是您的客户端不包括。这样,您可以完全测试您的内部实现,而不会泄漏到您的客户端。

测试私有属性可使用ReflectionClass(), 获取属性用getProperty(), 设置属性的值用setValue(), 获取方法用getMethod(), 设置属性和方法可被访问使用setAccessible。例如检测白名单路径。

2. 私有类成员

私人class成员只能从班class或友元类那里接触。要访问类的私有成员,可以将测试夹具声明为类的朋友,并在夹具中定义访问器。使用夹具的测试,可以通过夹具中的访问器访问您的生产类的私有成员。注意,即使你的夹具是你的生产类的朋友,你的测试不是它的友元类,因为他们技术上是定义在夹具的子类中。

另一种测试私有成员的方法是将它们重构为一个实现类,然后在* -internal.h文件中声明它。您的客户端不允许包括此标题,但您的测试可以。这种称为Pimpl(私有实现)习语。

或者,您可以通过在类主体中添加以下行,将个别测试声明为class的友元类:

FRIEND_TEST(TestCaseName, TestName);

  For example,

// foo.h
#include "gtest/gtest_prod.h"

// Defines FRIEND_TEST.
class Foo {
  ...
 private:
  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
  Foo foo;
  EXPECT_EQ(0, foo.Bar(NULL));
  // Uses Foo's private member Bar().
}

当你的类在命名空间中定义时,需要特别注意,因为你应该在同一个命名空间中定义你的测试夹具和测试,如果你想他们是你的class的友元。 例如,如果要测试的代码如下所示:

namespace my_namespace {

class Foo {
  friend class FooTest;
  FRIEND_TEST(FooTest, Bar);
  FRIEND_TEST(FooTest, Baz);
  ...
  definition of the class Foo
  ...
};

}  // namespace my_namespace

Your test code should be something like:

namespace my_namespace {
class FooTest : public ::testing::Test {
 protected:
  ...
};

TEST_F(FooTest, Bar) { ... }
TEST_F(FooTest, Baz) { ... }

}  // namespace my_namespace
getPathInfo; if (!$path || !$this->pathWhiteList || !is_array) { return false; } foreach ($this->pathWhiteList as $item) { if (preg_match { return true; } } return false; } }

getProperty; $reflectedPathWhiteList->setAccessible; $reflectedPathWhiteList->setValue($webDefenderService, $pathProperty); $reflectedRequest = $reflectedClass->getProperty; $reflectedRequest->setAccessible; $reflectedRequest->setValue; $reflectedMethod = $reflectedClass->getMethod; $reflectedMethod->setAccessible; $this->assertEquals($result, $reflectedMethod->invoke; } public function additionProviderPathWhiteList() { $allPath = ['.*']; $checkPath = ['^auth/']; $authSendSmsRequest = new Request([], [], [], [], [], ['HTTP_HOST' => 'api.dev.com', 'REQUEST_URI' => '/auth/sendSms']); $indexRequest = new Request([], [], [], [], [], ['HTTP_HOST' => 'api.dev.com', 'REQUEST_URI' => '/']); $noMatchRequest = new Request([], [], [], [], [], ['HTTP_HOST' => 'api.dev.com', 'REQUEST_URI' => '/product/sendSms']); return [ 'index' => [[], $authSendSmsRequest, false], 'no request' => [$allPath, $indexRequest, false], 'all request' => [$allPath, $authSendSmsRequest, true], 'check auth sms' => [$checkPath, $authSendSmsRequest, true], 'check path no match' => [$checkPath, $noMatchRequest, false] ]; } }

九、Catching Failures

如果您要在Google测试之上构建测试实用程序,则需要测试您的实用程序。 你将使用什么框架来测试它? Google测试,当然。

挑战是验证您的测试实用程序是否正确报告故障。 在框架中通过抛出异常报告失败,您可以捕获异常并断言。 但是Google Test不会使用异常,那么我们如何测试一段代码是否会产生预期的失败呢?

“gtest / gtest-spi.h”包含一些构造来做到这一点。 #include 它,然后可以使用

EXPECT_FATAL_FAILURE(statement, substring);​

to assert that statement generates a fatal (e.g. ASSERT_*) failure whose message contains the given substring, or use

EXPECT_NONFATAL_FAILURE(statement, substring);​

if you are expecting a non-fatal (e.g. EXPECT_*) failure.

。。。。。//需要时再看

5. 代码覆盖率

十、Getting the Current Test's Name

   有时一个函数可能需要知道当前运行的测试的名称。 例如,您可以使用测试夹具的SetUp()方法根据正在运行的测试设置黄金文件名。 :: testing :: TestInfo类具有以下信息:

namespace testing {

class TestInfo {
 public:
  // Returns the test case name and the test name, respectively.
  //
  // Do NOT delete or free the return value - it's managed by the
  // TestInfo class.
  const char* test_case_name() const;
  const char* name() const;
};

}  // namespace testing

To obtain a TestInfo object for the currently running test, call current_test_info() on the UnitTest singleton object:

// Gets information about the currently running test.
// Do NOT delete the returned object - it's managed by the UnitTest class.
const ::testing::TestInfo* const test_info =
  ::testing::UnitTest::GetInstance()->current_test_info();
printf("We are in test %s of test case %s.n",
       test_info->name(), test_info->test_case_name());

如果没有运行测试,current_test_info()返回一个空指针。 特别是,你不能在TestCaseSetUp(),TestCaseTearDown()中找到测试用例名称(在那里你知道测试用例名称),或者从它们调用的函数。

编辑:美高梅集团 本文来源:此宏会将当前文件名、行号和给定消息添加到每

关键词: