跟我学c++中级篇工具应用——gtest的事件

一、gtest的事件

gtest的事件机制其实是对单元测试的另外一种表现形式,它有两类基本的意义:
1、它可以在指定条件和场景前后处理相关数据
2、它可以提供指定条件和场景前后的结果通知
gtest中的事件分成基本的三个层次,即整个测试程序,相关测试的组或者说套件,最后是测试用例。因此,gtest中有三类基本的事件机制:
1、全局事件
在所有的Case执行前后动作,需要自定义一个测试类,继承testing::Environment类,实现使用的标记SetUp(),TearDown()两个虚函数,在所有测试开始前执行SetUp函数,测试结束后执行TearDown函数,这种事件是针对整个应用程序的,需要在main函数中调用testing::AddGlobalTestEnvironment(new MyEnvironment);。
2、组处理事件
在每组执行前后动作,需要定义一个类,继承testing::Test,实现应用标记TearDownTestCase()和SetUpTestCase()两个静态函数。它同样需要在组执行前执行这两个相关函数;它不需要像上面找全局事件需要注册,但是需要把TEST宏改为TEST_F宏。
3、Case事件
在每个案例Case执行前后动作,和组事件创建类似,它使用的标记是SetUp(),TearDown()两个函数,注意,非静态。需要在执行案例前调用这两个相关函数即可。
这个其实很好理解,无论是哪种工作,一定会有单个处理、批处理和所有处理这几大类别,它和现实是对应的。这样想,就明白了。

二、源码

看一下这些事件的源码:

class GTEST_API_ Test {
 public:
  friend class TestInfo;

  // The d'tor is virtual as we intend to inherit from Test.
  virtual ~Test();

  // Sets up the stuff shared by all tests in this test suite.
  //
  // Google Test will call Foo::SetUpTestSuite() before running the first
  // test in test suite Foo.  Hence a sub-class can define its own
  // SetUpTestSuite() method to shadow the one defined in the super
  // class.
  static void SetUpTestSuite() {}

  // Tears down the stuff shared by all tests in this test suite.
  //
  // Google Test will call Foo::TearDownTestSuite() after running the last
  // test in test suite Foo.  Hence a sub-class can define its own
  // TearDownTestSuite() method to shadow the one defined in the super
  // class.
  static void TearDownTestSuite() {}

  // Legacy API is deprecated but still available. Use SetUpTestSuite and
  // TearDownTestSuite instead.
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
  static void TearDownTestCase() {}
  static void SetUpTestCase() {}
#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_

  // Returns true if and only if the current test has a fatal failure.
  static bool HasFatalFailure();

  // Returns true if and only if the current test has a non-fatal failure.
  static bool HasNonfatalFailure();

  // Returns true if and only if the current test was skipped.
  static bool IsSkipped();

  // Returns true if and only if the current test has a (either fatal or
  // non-fatal) failure.
  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }

  // Logs a property for the current test, test suite, or for the entire
  // invocation of the test program when used outside of the context of a
  // test suite.  Only the last value for a given key is remembered.  These
  // are public static so they can be called from utility functions that are
  // not members of the test fixture.  Calls to RecordProperty made during
  // lifespan of the test (from the moment its constructor starts to the
  // moment its destructor finishes) will be output in XML as attributes of
  // the <testcase> element.  Properties recorded from fixture's
  // SetUpTestSuite or TearDownTestSuite are logged as attributes of the
  // corresponding <testsuite> element.  Calls to RecordProperty made in the
  // global context (before or after invocation of RUN_ALL_TESTS and from
  // SetUp/TearDown method of Environment objects registered with Google
  // Test) will be output as attributes of the <testsuites> element.
  static void RecordProperty(const std::string& key, const std::string& value);
  static void RecordProperty(const std::string& key, int value);

 protected:
  // Creates a Test object.
  Test();

  // Sets up the test fixture.
  virtual void SetUp();

  // Tears down the test fixture.
  virtual void TearDown();

 private:
  // Returns true if and only if the current test has the same fixture class
  // as the first test in the current test suite.
  static bool HasSameFixtureClass();

  // Runs the test after the test fixture has been set up.
  //
  // A sub-class must implement this to define the test logic.
  //
  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
  // Instead, use the TEST or TEST_F macro.
  virtual void TestBody() = 0;

  // Sets up, executes, and tears down the test.
  void Run();

  // Deletes self.  We deliberately pick an unusual name for this
  // internal method to avoid clashing with names used in user TESTs.
  void DeleteSelf_() { delete this; }

  const std::unique_ptr<GTEST_FLAG_SAVER_> gtest_flag_saver_;

  // Often a user misspells SetUp() as Setup() and spends a long time
  // wondering why it is never called by Google Test.  The declaration of
  // the following method is solely for catching such an error at
  // compile time:
  //
  //   - The return type is deliberately chosen to be not void, so it
  //   will be a conflict if void Setup() is declared in the user's
  //   test fixture.
  //
  //   - This method is private, so it will be another compiler error
  //   if the method is called from the user's test fixture.
  //
  // DO NOT OVERRIDE THIS FUNCTION.
  //
  // If you see an error about overriding the following function or
  // about it being private, you have mis-spelled SetUp() as Setup().
  struct Setup_should_be_spelled_SetUp {};
  virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }

  // We disallow copying Tests.
  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
};

注意区分全局和个例,名字相同的函数的性质不同。

三、事件例程

把gtest中的断言基本描述了一遍,下面看几个例子

#include <iostream>
#include <gtest/gtest.h>
#include <string>
#include <vector>
#include <iostream>

//注意看运行结果就明白了
//全局
class MyGlobalTest :public testing::Environment
{
public:
    virtual void SetUp()
    {
        std::cout << "Global test SetUp" << std::endl;
    }

    virtual void TearDown()
    {
        std::cout << "Global test TearDown" << std::endl;
    }

    std::vector<std::string> vec;
};

//组:SetUpTestCase()和TearDownTestCase()
class MyTestSuite :public testing::Test
{
public:
    static void SetUpTestCase()
    {
        std::cout << "Suite test SetUpTestCase()" << std::endl;
    }

    static void TearDownTestCase()
    {
        std::cout << "Suite test TearDownTestCase()" << std::endl;
    }

    void SetUp()
    {
        std::cout << "Suite test SetUp()" << std::endl;
        vec.emplace_back("aaa");
        vec.emplace_back("bbb");
        vec.emplace_back("ccc");
        vec.emplace_back("ddd");
    }

    void TearDown()
    {
        vec.clear();
        std::cout << "Suite test TearDown()" << std::endl;
    }

    std::vector<std::string> vec;
};

class MyTestCase :public testing::Test
{
public:
    void SetUp()
    {
        std::cout << "Case SetUp" << std::endl;
    }
    void TearDown()
    {
        std::cout << "Case TearDown" << std::endl;
    }
};

TEST_F(MyTestSuite, Find)
{
    std::vector<std::string>::iterator it = vec.begin()+1;
    ASSERT_NE(it, vec.end());
}

TEST_F(MyTestSuite, Size)
{
    ASSERT_EQ(6, vec.size());
}

TEST(MyGlobalTest, test0)
{
    EXPECT_EQ(6, 3);
}

TEST_F(MyTestCase, ZeroEqual)
{
    EXPECT_EQ(0, 0);
}

int main(int argc, char** argv)
{
    testing::InitGoogleTest(&argc, argv);
    testing::Environment* env = new MyGlobalTest();
    testing::AddGlobalTestEnvironment(env);
    return RUN_ALL_TESTS();
}

运行结果是:

[==========] Running 4 tests from 3 test suites.
[----------] Global test environment set-up.
Global test SetUp
[----------] 2 tests from MyTestSuite
Suite test SetUpTestCase()
[ RUN      ] MyTestSuite.Find
Suite test SetUp()
Suite test TearDown()
[       OK ] MyTestSuite.Find (0 ms)
[ RUN      ] MyTestSuite.Size
Suite test SetUp()
D:\vs2019_project\gtestSamples\gtestSamples.cpp(81): error: Expected equality of these values:
  6
  vec.size()
    Which is: 4
Suite test TearDown()
[  FAILED  ] MyTestSuite.Size (1 ms)
Suite test TearDownTestCase()
[----------] 2 tests from MyTestSuite (2 ms total)

[----------] 1 test from MyGlobalTest
[ RUN      ] MyGlobalTest.test0
D:\vs2019_project\gtestSamples\gtestSamples.cpp(86): error: Expected equality of these values:
  6
  3
[  FAILED  ] MyGlobalTest.test0 (0 ms)
[----------] 1 test from MyGlobalTest (0 ms total)

[----------] 1 test from MyTestCase
[ RUN      ] MyTestCase.ZeroEqual
Case SetUp
Case TearDown
[       OK ] MyTestCase.ZeroEqual (0 ms)
[----------] 1 test from MyTestCase (1 ms total)

[----------] Global test environment tear-down
Global test TearDown
[==========] 4 tests from 3 test suites ran. (6 ms total)
[  PASSED  ] 2 tests.
[  FAILED  ] 2 tests, listed below:
[  FAILED  ] MyTestSuite.Size
[  FAILED  ] MyGlobalTest.test0

 2 FAILED TESTS

对比着结果就可以很清楚的看到使用的效果。

三、总结

gtest的事件应用还有很多的情况,在实践中需要不断的总结和应用相关的技巧,只要不断的学习,就会有量变到质变的过程,坚持不懈,深入底层才能不断的把技术锤炼到更高的境界。
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值