Google_Test

基本用法

程序中引用#include<gtest/gtest.h>

编译时加入参数-lgtest

gtest的主要用法和assert类似:

1
2
3
4
5
6
7
ASSERT_TRUE(condition);
EXPECT_TRUE(condition);
ASSERT_NE(val1, val2);
ASSERT_GT(val1, val2);
ASSERT_LE(val1, val2);
ASSERT_STREQ(expected_str, actual_str);
ASSERT_STRCASEEQ(expected_str, actual_str);

assert在条件为假时中止程序,expect则只会报错。

简单测试

创建一个测试:

  1. 使用 TEST() 宏定义和命名一个测试函数。它们就是普通的C++的无返回值函数。
  2. 函数中可以使用任何C++表达式,以及GTest中的断言。
  3. 如果任一断言失败了(终止或非终止的),或者如果测试崩溃了,该测试失败;反之成功。
1
2
3
4
5
6
7
8
9
10
11
12
TEST(test_case_name, test_name) {
... test body ...
}

// for example
// Tests factorial of positive numbers.
TEST(FactorialTest, HandlesPositiveInput) {
EXPECT_EQ(1, Factorial(1));
EXPECT_EQ(2, Factorial(2));
EXPECT_EQ(6, Factorial(3));
EXPECT_EQ(40320, Factorial(8));
}

捆绑测试

如果有多个测试使用类似的数据,可以使用捆绑测试(text fixture)。它允许几个不同的测试复用相同的配置。

创建一个捆绑:

  1. ::testing::Test 派生一个类。使用 protected:public: ,因为我们需要能从子类访问捆绑的成员。
  2. 在类中声明任何你想用的对象。
  3. 如果有必要,实现默认构造函数或者 SetUp() 函数来为测试准备数据。
  4. 如果有必要,实现一个析构函数或者 TearDown() 函数来释放在 SetUp() 中分配的资源。
  5. 如果需要,定义用于共享的子例程。

TEST_F() 代替 TEST() ,这样就可以访问捆绑测试中的对象和子例程了:

1
2
3
TEST_F(test_case_name, test_name) {
... test body ...
}

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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_;
};

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

Main函数

可以参考下面的样板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "this/package/foo.h"
#include <gtest/gtest.h>

namespace {

// The fixture for testing class Foo.
class FooTest : public ::testing::Test {
protected:
// You can remove any or all of the following functions if its body
// is empty.

FooTest() {
// You can do set-up work for each test here.
}

virtual ~FooTest() {
// You can do clean-up work that doesn't throw exceptions here.
}

// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:

virtual void SetUp() {
// Code here will be called immediately after the constructor (right
// before each test).
}

virtual void TearDown() {
// Code here will be called immediately after each test (right
// before the destructor).
}

// Objects declared here can be used by all tests in the test case for Foo.
};

// Tests that the Foo::Bar() method does Abc.
TEST_F(FooTest, MethodBarDoesAbc) {
const string input_filepath = "this/package/testdata/myinputfile.dat";
const string output_filepath = "this/package/testdata/myoutputfile.dat";
Foo f;
EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
}

// Tests that Foo does Xyz.
TEST_F(FooTest, DoesXyz) {
// Exercises the Xyz feature of Foo.
}

}// namespace

int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

一个神奇的问题

编写一个demo的时候,遇到了C++的一个很迷的问题,就是模版类的头文件不能够和模版类的实现.cpp分离开

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
* mastering Google Test
* it's the tested header file -- queue.h
*/
#ifndef QUEUE_H
#define QUEUE_H

#include <cstdio>
template <class E> // E is the element type
class queue{
public:
queue();
void enqueue(const E& obj);
E* dequeue(); // returns NULL if the queue is empty
size_t size();
~queue();
private:
E* array;
int head, tail;
static const int SIZE = 100;
};

#include "queue.cpp" // 必须要加上这一句否则编译不过(模版类一定要在头文件中声明实现,不能分离)

#endif