0%

gtest测试框架使用

前言

在实际项目开发过程中,需要进行必要的单元测试,以保证代码开发阶段的功能性。这里简单介绍下 google 跨平台的c++单元测试框架 gtest。

安装

gtest 编译需要 cmake 支持,安装步骤如下:

1
2
3
4
5
6
$ git clone https://github.com/google/googletest.git
$ cd googletest/
$ mkdir build
$ cd build/
$ cmake ..
$ sudo make install

测试

gtest 提供了TEST()宏,用来定义测试函数:

1
2
3
4
TEST(test_suite_name, test_case_name) 
{
// test body ...
}

在测试函数中,gtest 提供了 EXPECT_*ASSERT_* 两种风格的断言。如果 ASSERT_* 执行失败了,会导致测试函数立即返回;但 EXPECT_* 如果执行失败了,并不会导致测试函数返回。

ASSERT EXPECT ESTIMATE
ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition为true
ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition为false
ASSERT_EQ(expected, actual); EXPECT_EQ(expected, actual); expected == actual
ASSERT_NE(val1, val2); EXPECT_NE(val1, val2); val1 != val2
ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); val1 < val2
ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); val1 <= val2
ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); val1 > val2
ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); val1 >= val2
ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str); the two C strings have the same content
ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); the two C strings have different content
ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str); the two C strings have the same content, ignoring case
ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); the two C strings have different content, ignoring case
1
2
3
4
5
6

TEST(MyTest, Add)
{
EXPECT_EQ(1 + 1, 2);
ASSERT_EQ(1 + 1, 2);
}
  • 编写简单的测试用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <gtest/gtest.h>

int add(int a, int b) {
return a + b;
}

TEST(Demo, add) {
EXPECT_EQ(add(1, 2), 3);
}

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

return RUN_ALL_TESTS();
}
  • CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cmake_minimum_required (VERSION 3.2)

project(mytest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall")

find_package(GTest REQUIRED)
find_package(Threads REQUIRED)

include_directories(${GTEST_INCLUDE_DIRS})

add_executable(mytest test.cpp)
target_link_libraries(mytest ${GTEST_BOTH_LIBRARIES})
target_link_libraries(mytest ${CMAKE_THREAD_LIBS_INIT})

add_test(Test mytest)
enable_testing()
  • 执行测试用例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ make test
    Running tests...
    Test project /work/temp/gtest-demo/build
    Start 1: Test
    1/1 Test #1: Test ............................. Passed 0.00 sec

    100% tests passed, 0 tests failed out of 1

    Total Test time (real) = 0.00 sec
  • samples

gtest 的源码中包含很多测试 samples,并且在 docs 中有简短的说明,以 sample1 为例,实现了阶乘和质数的方法。

1
2
3
4
5
6
7
8
9
// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
int Factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}

return result;
}

对应阶乘方法的单元测试用例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Tests factorial of negative numbers.
TEST(FactorialTest, Negative) {
EXPECT_EQ(1, Factorial(-5));
EXPECT_EQ(1, Factorial(-1));
EXPECT_GT(Factorial(-10), 0);
}

// Tests factorial of 0.
TEST(FactorialTest, Zero) {
EXPECT_EQ(1, Factorial(0));
}

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

编译 samples 需要指定编译选项 cmake -Dgtest_build_samples=ON ${GTEST_DIR}

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
$ ./sample1_unittest
Running main() from /work/googletest/googletest/src/gtest_main.cc
[==========] Running 6 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 3 tests from FactorialTest
[ RUN ] FactorialTest.Negative
[ OK ] FactorialTest.Negative (0 ms)
[ RUN ] FactorialTest.Zero
[ OK ] FactorialTest.Zero (0 ms)
[ RUN ] FactorialTest.Positive
[ OK ] FactorialTest.Positive (0 ms)
[----------] 3 tests from FactorialTest (0 ms total)

[----------] 3 tests from IsPrimeTest
[ RUN ] IsPrimeTest.Negative
[ OK ] IsPrimeTest.Negative (0 ms)
[ RUN ] IsPrimeTest.Trivial
[ OK ] IsPrimeTest.Trivial (0 ms)
[ RUN ] IsPrimeTest.Positive
[ OK ] IsPrimeTest.Positive (0 ms)
[----------] 3 tests from IsPrimeTest (0 ms total)

[----------] Global test environment tear-down
[==========] 6 tests from 2 test suites ran. (0 ms total)
[ PASSED ] 6 tests.

总结

利用 gtest 可以快速进行单元测试编写,验证软件开发过程中的问题,是软件开发中不可缺少的环节。