C++ 项目之Googletest单元测试
- 2019 年 10 月 6 日
- 筆記
C++ 项目之Googletest单元测试
1.Clion集成Googletest单元测试
Googletest – Google Testing and Mocking Framework
源码下载地址:
https://github.com/google/googletest/releases
Googletest中包含两个模块,分别是gtest与gmock,需要分别源码编译,编译完后,到指定目录去拷贝includes文件夹与.so文件到下面路径的指定位置.
然后项目中创建ext目录,里面分为两块
- 第一块:includes
包含gmock与gtest的include文件,对应于gcc -I参数,头文件路径,包含以.h结尾的头文件
- 第二块:libs
包含gmock与gtest的libs文件,对应gcc -L参数,库文件路径,里面包含的是一些.so或.dll等动态或静态链接库
├── ext │ ├── includes │ │ ├── gmock │ │ └── gtest │ └── libs │ ├── gmock │ └── gtest
上述本地项目路径配置好后,在CmakeLists.txt中进行配置:
# ext set(BASE_INCLUDES ext/includes) set(BASE_LIBS ext/libs) # googletest set(GTEST_INCLUDE_DIR ${BASE_INCLUDES}/gtest/include) set(GMOCK_INCLUDE_DIR ${BASE_INCLUDES}/gmock/include) set(GTEST_LINK_DIR ${BASE_LIBS}/gtest/lib/) set(GMOCK_LINK_DIR ${BASE_LIBS}/gmock/lib/) # 去哪里找头文件 相当于gcc/clang 中的-I(i的大写字母)参数 include_directories(${GTEST_INCLUDE_DIR}) include_directories(${GMOCK_INCLUDE_DIR}) # 去哪里找库文件 .so .dll .dylib 相当于gcc 中的-L参数 link_directories(${GTEST_LINK_DIR}) link_directories(${GMOCK_LINK_DIR})
然后为每个test配上链接库即可.
例如,现在有个测试file,文件名为:了l1.cpp
那么在CmakeLists.txt中配置为:
add_executable(l1 l1.cpp) target_link_libraries(l1 gtest gtest_main)
2.gtest之Helloworld
int main(int argc, char* argv[]) { // 接收命令行参数 testing::InitGoogleTest(&argc, argv); vector<int> x={1,2,3,5}; // EXPECT_EQ使用 for (int i = 0; i < x.size(); ++i) { EXPECT_EQ(x[i], 1) << "Vectors x and y differ at index " << i; } RUN_ALL_TESTS(); return 0; }
例如上述就是个完整的例子,每次运行:
testing::InitGoogleTest(&argc, argv);
然后使用:
RUN_ALL_TESTS();
运行所有的Test,每个Test编写参考后面断言.
我们看看运行效果:
l1.cpp:113: Failure Expected equality of these values: x[i] Which is: 2 1 Vectors x and y differ at index 1 l1.cpp:113: Failure Expected equality of these values: x[i] Which is: 3 1 Vectors x and y differ at index 2 l1.cpp:113: Failure Expected equality of these values: x[i] Which is: 5 1 Vectors x and y differ at index 3 [==========] Running 0 tests from 0 test cases. [==========] 0 tests from 0 test cases ran. (0 ms total) [ PASSED ] 0 tests. [ FAILED ] 0 tests, listed below: 0 FAILED TESTS
3.gtest初识之断言
关于断言Google包装了一系列EXPECT
和ASSERT
的宏,而EXPECT系列和ASSERT系列的区别是:
EXPECT
失败时,案例继续往下执行。-
ASSERT
失败时,直接在当前函数中返回,当前函数中ASSERT
后面的语句将不会执行。
例如:
TEST(ASSERTTest, ASSERT_VS_EXPECT) { ASSERT_TRUE(10<2); // ASSERT失败,直接在当前函数中返回,后面语句不执行 ASSERT_FALSE(10<2); EXPECT_EQ(6, Foo(310, 18)); }
每个Test是个宏,Test底层源码如下:
# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
对应test_case名与test名.
上述代码中10<2为False,而使用了ASSERT_TRUE
,该Test后面所有内容就不会执行,如果换成EXPECT_TRUE
则正常运行!
布尔值检查
Fatal assertion |
Nonfatal assertion |
Verifies |
---|---|---|
ASSERT_TRUE(condition); |
EXPECT_TRUE(condition); |
condition is true |
ASSERT_FALSE(condition); |
EXPECT_FALSE(condition); |
condition is false |
数值型数据检查
Fatal assertion |
Nonfatal assertion |
Verifies |
---|---|---|
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 |
字符串检查
TEST(StringCmpTest, Demo) { char* pszCoderZh = "CoderZh"; wchar_t* wszCoderZh = L"CoderZh"; std::string strCoderZh = "CoderZh"; std::wstring wstrCoderZh = L"CoderZh"; EXPECT_STREQ("CoderZh", pszCoderZh); EXPECT_STREQ(L"CoderZh", wszCoderZh); EXPECT_STRNE("CnBlogs", pszCoderZh); EXPECT_STRNE(L"CnBlogs", wszCoderZh); EXPECT_STRCASEEQ("coderzh", pszCoderZh); //EXPECT_STRCASEEQ(L"coderzh", wszCoderZh); 不支持 EXPECT_STREQ("CoderZh", strCoderZh.c_str()); EXPECT_STREQ(L"CoderZh", wstrCoderZh.c_str()); }
其中STREQ和STRNE同时支持char和wchar_t类型的,STRCASEEQ和STRCASENE却只接收char*
显示返回成功或失败
直接返回成功:SUCCEED();
返回失败:
Fatal assertion |
Nonfatal assertion |
---|---|
FAIL(); |
ADD_FAILURE(); |
// 返回成功与否 TEST(ExplicitTest, Demo) { ADD_FAILURE() << "这行打印失败 Sorry"; // None Fatal Asserton,继续往下执行。 //FAIL(); // Fatal Assertion,不往下执行该案例。 EXPECT_TRUE(1==2)<<"1==2 failed!"; // 为了验证上述失败后是否执行下面 SUCCEED(); }
异常检查
分为三个:
EXPECT_NO_THROW(statement);
不抛出异常
EXPECT_ANY_THROW(statement);
抛出任意类型异常
EXPECT_THROW(statement, exception_type);
抛出指定类型异常
TEST(ExceptionTest,et) { // 抛出任意类型异常 EXPECT_ANY_THROW(10/0); //Expected: 10/0 throws an exception. // 抛出指定类型异常 EXPECT_THROW(1/0,int); //Expected: 1/0 throws an exception of type int. }
Predicate Assertions
检查一个函数的返回值TRUE还是FALSE时,希望能够输出传入的参数是什么,以便失败后好跟踪
例如:
// 预测断言 bool MN(int m, int n) { return m>n; } //检查一个函数的返回值TRUE还是FALSE时,希望能够输出传入的参数是什么,以便失败后好跟踪 TEST(PredicateAssertionTest, Demo) { int m = 5, n = 6; EXPECT_PRED2(MN, m, n); //只提供<=5个参数 传递参数要与函数MN对应 }
`EXPECT_PRED2(pred2, val1, val2);
ASSERT类似.PRED2可以到PRED5
最多支持5个参数.
浮点型检查
EXPECT_FLOAT_EQ(expected, actual)
与EXPECT_DOUBLE_EQ(expected, actual)
ASSERT类似.
对相近的两个数比较:
EXPECT_NEAR(val1, val2, abs_error);
ASSERT类似.
例如:
// 浮点型 TEST(FloatDoubleTest,Demo) { ASSERT_DOUBLE_EQ(1.1,1.1); EXPECT_FLOAT_EQ(1.2,4.0); EXPECT_NEAR(1.234,1.888,0.9); // EXPECT_PRED_FORMAT2(testing::FloatLE, val1, val2); // EXPECT_PRED_FORMAT2(testing::DoubleLE, val1, val2); EXPECT_PRED_FORMAT2(testing::FloatLE,1,0); // LE表示小于等于 也就是value1<=value2 EXPECT_PRED_FORMAT2(testing::DoubleLE,0.1,0.2); }
类型检查
// 类型检查 template <typename T> class Tt{ public: void foo() { testing::StaticAssertTypeEq<bool, T>(); // 与下面调用一致就不报错,否则报错 } }; TEST(TypeAssertionTest, Demo) { Tt<bool> tt; tt.foo(); }
学习参考自:https://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html