Learn from me the application of c + + intermediate tools -- the event of gtest

1, gtest events

The event mechanism of gtest is actually another form of unit testing. It has two basic meanings:
1. It can process relevant data before and after specifying conditions and scenes
2. It can provide notification of results before and after specified conditions and scenarios
The events in gtest are divided into three basic levels: the whole test program, related test groups or suites, and finally test cases. Therefore, there are three basic event mechanisms in gtest:
1. Global events
Before and after the execution of all Case, you need to customize a test class, inherit the testing::Environment class, implement the marked SetUp(),TearDown() two virtual functions, perform the SetUp function before all the tests begin, and perform TearDown functions after the test is finished. This event is targeted at the entire application, calling testing:: AddGlobalTestEnvironment in main function. (new MyEnvironment);.
2. Group processing events
Before and after the execution of each group, you need to define a class, inherit testing::Test, and implement the two static functions of the application tag TearDownTestCase() and SetUpTestCase(). It also needs to execute these two related functions before the execution of the group; it does not need to find global events like the above and needs to be registered, but you need to change the TEST macro to TEST_F macro.
3. Case event
Before and after the execution of Case in each case, it is similar to group event creation. The markup used is SetUp(),TearDown(), two functions. Note that it is not static. It is necessary to call these two correlation functions before executing the case.
This is actually very easy to understand. No matter what kind of work, there must be several categories: single processing, batch processing and all processing, which correspond to reality. Think about it this way, and you will understand.

2, Source code

Take a look at the source code of these events:

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);
};

Pay attention to distinguish between global and individual cases. Functions with the same name have different properties.

3, Event routine

After describing the assertions in gtest, let's look at some examples

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

//Just look at the running results
//overall situation
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;
};

//Groups: SetUpTestCase() and 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();
}

The operation result is:

[==========] 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

By comparing the results, you can clearly see the effect of use.

3, Summary

There are still many cases in the event application of gtest. In practice, we need to constantly summarize and apply relevant skills. As long as we keep learning, there will be a process from quantitative change to qualitative change. Only by persevering and going deep into the bottom can we constantly temper the technology to a higher level.

Keywords: C++

Added by brad_langdon on Sun, 05 Dec 2021 05:36:12 +0200