Test Fixtures: Using the Same Data Configuration for Multiple Tests
Test Fixtures:为多个测试使用相同数据配置
If you find yourself writing two or more tests that operate on similar data, you can use a test fixture. It allows you to reuse the same configuration of objects for several different tests.
如果发现编写了两个或多个类似数据操作的测试,可以使用test fixture。Test fixture允许为不同测试你重复使用对象相同的配置。
To create a fixture, just:
创建一个fixture,仅需要:
1、Derive a class from testing::Test . Start its body with protected: or public: as we'll want to access fixture members from sub-classes.
从testing::Test中派生一个类,用protected:或public:开始主题部分,因为我们需要从子类中进入fixture成员。
2、Inside the class, declare any objects you plan to use.
在类内部声明任何计划使用的对象。
3、If necessary, write a default constructor or SetUp() function to prepare the objects for each test. A common mistake is to spell SetUp() as Setup() with a small u - don't let that happen to you.
如果必要,编写默认构造函数或SetUp()函数为每个测试准备对象,一个常见错误是用小写的u拼写的Setup()函数来代替SetUp(),请不要发生那样的错误。
4、If necessary, write a destructor or TearDown() function to release any resources you allocated in SetUp() . To learn when you should use the constructor/destructor and when you should use SetUp()/TearDown(), read this FAQ entry.
如果必要,编写析构函数或TearDown释放在SetUp()中申请的任何资源。学习合适应该使用构造/析构对和合适应该使用SetUp/TearDown(),阅读相关FAQ释疑。(译者注:最为关键的两点是构造函数与析构函数不能够抛出异常和以及调用虚拟函数)
5、If needed, define subroutines for your tests to share. 如果需要,定义为测试共享的子过程。
When using a fixture, use TEST_F() instead of TEST() as it allows you to access objects and subroutines in the test fixture:
如果要使用fixture,用TEST_F()取代TEST(),TEST_F()允许在test fixture中进入对象和子过程:
TEST_F(test_case_name, test_name) {
... test body ...
}
Like TEST(), the first argument is the test case name, but for TEST_F() this must be the name of the test fixture class. You've probably guessed: _F is for fixture.
类似TEST(),第一个参数使用测试案例名字,但是TEST_F()必须使用test fixture类的名字,你可能测到了:_F是fixture的含义。
Unfortunately, the C++ macro system does not allow us to create a single macro that can handle both types of tests. Using the wrong macro causes a compiler error.
不幸的是,C++宏系统不允许我们为运用两种类型测试创建一个简单的宏,使用错误的宏语句可导致编译错误。
Also, you must first define a test fixture class before using it in a TEST_F(), or you'll get the compiler error "`virtual outside class declaration`".
当然,必须在使用TEST_F()之前首先定义test fixture类,否则将得到编译错误“virtual outside class declaration”
For each test defined with TEST_F(), Google Test will:
对于每个定义的TEST_F(),Google Test将做如下工作:
1、Create a fresh test fixture at runtime
在运行时创建一个全新的test fixture
2、Immediately initialize it via SetUp() ,
通过SetUp()立即初始化test fixture
3、Run the test
运行测试
4、Clean up by calling TearDown()
调用TearDown()清除资源
5、Delete the test fixture. Note that different tests in the same test case have different test fixture objects, and Google Test always deletes a test fixture before it creates the next one. Google Test does not reuse the same test fixture for multiple tests. Any changes one test makes to the fixture do not affect other tests.
删除test fixture。注意相同测试案例中的不同测试具有不同的fixture对象,Google Test通常在创建下一个fixture前删除当前test fixture。Google Test并不为对多个测试重复使用相同的test fixture。任何在fixture上的测试更改并不影响其他测试上的fixture。
As an example, let's write tests for a FIFO queue class named Queue, which has the following interface:
我们将命名为Queue的FIFO队列类编写测试作为一个例子,Queue具有下面的接口:
template <typename E> // E is the element type.
class Queue {
public:
Queue();
void Enqueue(const E& element);
E* Dequeue(); // Returns NULL if the queue is empty.
size_t size() const;
...
};
First, define a fixture class. By convention, you should give it the name FooTest where Foo is the class being tested.
首先,定义一个fixture类,通常,需要给出一个名字FooTest,此处Foo是被测试类的名字。
class QueueTest : public testing::Test {
protected:
virtual void SetUp() {
q1_.Enqueue(1);
q2_.Enqueue(2);
q2_.Enqueue(3);
}
// virtual void TearDown() {}
Queue<int> q0_;
Queue<int> q1_;
Queue<int> q2_;
};
In this case, TearDown() is not needed since we don't have to clean up after each test, other than what's already done by the destructor.
此处,由于在每次测试后不需要清除资源,因此TearDown()并不需要,除了已经在析构函数中做了。
Now we'll write tests using TEST_F() and this fixture.
现在我们使用TEST_F()和fixture编写测试
TEST_F(QueueTest, IsEmptyInitially) {
EXPECT_EQ(0, q0_.size());
}
TEST_F(QueueTest, DequeueWorks) {
int* n = q0_.Dequeue();
EXPECT_EQ(NULL, n);
n = q1_.Dequeue();
ASSERT_TRUE(n != NULL);
EXPECT_EQ(1, *n);
EXPECT_EQ(0, q1_.size());
delete n;
n = q2_.Dequeue();
ASSERT_TRUE(n != NULL);
EXPECT_EQ(2, *n);
EXPECT_EQ(1, q2_.size());
delete n;
}
The above uses both ASSERT_* and EXPECT_* assertions. The rule of thumb is to use EXPECT_* when you want the test to continue to reveal more errors after the assertion failure, and use ASSERT_* when continuing after failure doesn't make sense. For example, the second assertion in the Dequeue test is ASSERT_TRUE(n != NULL), as we need to dereference the pointer n later, which would lead to a segfault when n is NULL.
上面例子使用了ASSERT_和EXPECT_*断言,当想要在断言失败时继续暴露更多的错误时,经验规则告诉我们使用EXPECT_*,当失败后继续运行变得无意义时,使用ASSERT_*。例如,在Dequeue测试中第二个断言为ASSERT_TRUE( n != NULL ). 由于我们需要后面解引用n指针,当n为NULL时导致segfault(译者注:segfault指访问了不允许访问的内存, 或者试图用不允许的方式访问内存,感谢Madhero帮助)。
When these tests run, the following happens:
当测试运行时,发生下面事情:
1、Google Test constructs a QueueTest object (let's call it t1 ).
Google Test构造一个QueueTest对象(让我们称之为t1)
2、t1.SetUp() initializes t1 .
t1.SetUp()初始化t1
3、The first test ( IsEmptyInitially ) runs on t1 .
在t1上运行第一个测试(IsEmptyInitially)
4、t1.TearDown() cleans up after the test finishes.
测试结束时,t1.TearDown()清除
5、t1 is destructed.
t1析构
6、The above steps are repeated on another QueueTest object, this time running the DequeueWorks test.
另一个QueueTest对象重复上面的步骤,此处这次运行DequeueWorks测试
Availability: Linux, Windows, Mac.
Note: Google Test automatically saves all Google Test flags when a test object is constructed, and restores them when it is destructed.
转载请注明来自ubunoon[http://www.cnblogs.com/ubunoon]