一、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的事件应用还有很多的情况,在实践中需要不断的总结和应用相关的技巧,只要不断的学习,就会有量变到质变的过程,坚持不懈,深入底层才能不断的把技术锤炼到更高的境界。
|