您的位置:首页 > 编程语言 > C语言/C++

遇见gtest--事件

2015-11-02 20:52 363 查看
1、前言
    在单元测试中,我们经常需要在某个测试套件、测试用例或者整个测试运行之前进行前置条件设置及检查,或者运行之后对运行结果进行校验等操作。在gtest中,称之为事件机制。gtest将事件按照作用的范围不同进行划分,从大到小总共分为3个层次:
    1)整个测试层面,即在测试工程开始前和结束后进行;
    2)测试套件层面,即在某个测试套件开始前和结束后进行;
    3)测试用例层面,即在某个测试用例开始前和结束后进行;

2、测试层面事件实现
    要实现测试层面的事件,我们需要继承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() {}
private:
struct Setup_should_be_spelled_SetUp {};
virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
};


    这个类中有两个虚函数:SetUp和TearDown。我们的子类只需要实现这个方法即可。其中在SetUp方法中实现所有测试启动之前需要完成的操作,而TearDown函数中实现所有测试运行结束后需要进行的操作。例如:

class GlobalEvent2 :
public testing::Environment
{
public:

virtual void SetUp()
{
cout << "Before any case, Global 2" << endl;
}

virtual void TearDown()
{
cout << "After all cases done, Global 2" << endl;
}
};


    然后,在main函数中,在RUN_ALL_TESTS()之前,我们调用如下语句:
    testing::AddGlobalTestEnvironment(new GlobalEnvent);
    将这个测试层面的的事件添加到事件列表即可。这样,在测试执行之前,系统会先执行GlobalEvent2的SetUp方法;在所有测试用例执行完之后,系统会执行GlobalEvent2的TearDown方法。另外,我们可以定义任意多个继承自testing::Environment的子类,以实现不同的全局事件。所有的子类的SetUp按照我们调用testing::AddGlobalTestEnvironment添加它们的先后顺序执行,而TearDown的执行顺序则与添加顺序相反。

3、测试套件层面事件
    要在测试套件层面上定义事件,我们需要继承testing::Test类,并覆盖它的静态方法:SetUpTestCase和TearDownTestCase.在继续之前我们首先看看testing::Test类的定义:

class GTEST_API_ Test {
public:
friend class TestInfo;

// Defines types for pointers to functions that set up and tear down
// a test case.
typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;

// 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 case.
//
// Google Test will call Foo::SetUpTestCase() before running the first
// test in test case Foo.  Hence a sub-class can define its own
// SetUpTestCase() method to shadow the one defined in the super
// class.
static void SetUpTestCase() {}

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

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

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

// Returns true iff 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 case, or for the entire
// invocation of the test program when used outside of the context of a
// test case.  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
// SetUpTestCase or TearDownTestCase 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 iff the current test has the same fixture class as
// the first test in the current test case.
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; }

// Uses a GTestFlagSaver to save and restore all Google Test flags.
const internal::GTestFlagSaver* const gtest_flag_saver_;

// Often a user mis-spells 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 a user declares void Setup() in his test
//   fixture.
//
//   - This method is private, so it will be another compiler error
//   if a user calls it from his 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 NULL; }

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


    从testing::Test类的声明可以看到,SetUpTestCase和TearDownTestCase为静态方法,并且它们的注释也很详细。在测试套件的第一个测试用例开始前,SetUpTestCase函数会被调用,而在测试套件中的最后一个测试用例运行结束后,TearDownTestCase函数会被调用。

4、测试用例层面的事件
    要实现单个测试用例的事件,我们需要同样需要继承testing::Test类,并实现它的protected virtual方法SetUp和TearDown。gtest在运行这个测试用例之前,会首先调用SetUp方法,然后在测试用例结束之后,调用TearDown方法。

5、总结
    通过gtest事件机制,我们可以让gtest在运行测试、测试套件、测试用例的前后分别运行指定的代码段。这一点很有用,比如在单元测试中,我们可以将初始化操作放入SetUp函数中,而资源回收等操作方在TearDown函数中实现,这样可以使得我们在测试用例中只需专注于测试即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gtest c++