什么是gtest
软件测试技术保证了软件不断迭代时基本功能的正常运行,在迭代开发中,写软件测试代码,可以保证每次提交的代码在基本功能上的一致性,避免错误回归,保证迭代质量。
gtest是一个跨平台的(Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian)C++单元测试框架,由google公司发布。gtest是为在不同平台上为编写C++测试而生成的。它提供了丰富的断言、致命和非致命判断、参数化、”死亡测试”等等。
gtest宏
TEST(test_case_name, test_name)
TEST_F(test_fixture,test_name)
Test宏用于定义一个简单的测试场景。在函数中可以使用下面提到了两种断言来进行检查,如果函数的输出于预期不符,在测试运行时就会产生错误。
gtest中断言的宏可以分为两类:一类是ASSERT宏,另一类就是EXPECT宏了。
1、ASSERT_系列:如果当前点检测失败则退出当前函数
2、EXPECT_系列:如果当前点检测失败则继续往下执行
一个简单测试
ROS软件在默认的catkin包的CMakeLiets.txt中默认集成了gtest测试框架,不过这部分被注释掉了,使用的时将其解注释即可
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# 增加gtest测试的代码文件
catkin_add_gtest(${PROJECT_NAME}-test
test/gTest.cpp
include/self_checking/TestUnit/NodeTest/SpawnDao.cpp
include/self_checking/TestUnit/NodeTest/SpawnDao.h
)
# 为代码运行链接必要的库
# 若编译时出现“未定义的引用”等问题,检查此处的链接
if (TARGET ${PROJECT_NAME}-test)
target_link_libraries(${PROJECT_NAME}-test
libmysqlcppconn.so
)
endif ()
在Test代码文件中定义具体的测试用例,例子中写了一个名为DaoTest的用例,用例下有一个名为getWarningCount和parserIdentifyNameByRouteKey的测试。一个名为LineTest的用例,用例下有一个名为getCurrentTime的测试。
#include <ctcs/DAO/MessageDao.h>
#include <ctcs/MQ/MessageParser.h>
#include "gtest/gtest.h"
#include "ctcs/Bean/Line.h"
TEST(DaoTest, getWarningCount) {
MessageDao Dao;
EXPECT_EQ(Dao.getWarningCount(2), 0);
}
TEST(DaoTest, parserIdentifyNameByRouteKey) {
EXPECT_EQ(MessageParser::parserIdentifyNameByRouteKey("KFR00E04C6804D0.mm_log"), "KFR00E04C6804D0");
}
TEST(LineTest,getCurrentTime) {
long before = Line::getCurrentTime();
sleep(5);
long after = Line::getCurrentTime();
EXPECT_EQ(after - before, 5);
}
event_base *MQProxy::evbase;
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
//运行此句后,上面的用例会自动被调用
return RUN_ALL_TESTS();
}
gTest.cpp
需要运行相关测试代码,在ROS工作空间目录下(与src同级的目录)键入:
catkin_make run_tests
测试代码就会编译运行,运行结果如下
[==========] Running 3 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 2 tests from DaoTest
[ RUN ] DaoTest.getWarningCount
[ OK ] DaoTest.getWarningCount (47 ms)
[ RUN ] DaoTest.parserIdentifyNameByRouteKey
[ OK ] DaoTest.parserIdentifyNameByRouteKey (0 ms)
[----------] 2 tests from DaoTest (47 ms total)
[----------] 1 test from LineTest
[ RUN ] LineTest.
[ OK ] LineTest. (5000 ms)
[----------] 1 test from LineTest (5000 ms total)
[----------] Global test environment tear-down
[==========] 3 tests from 2 test cases ran. (5047 ms total)
[ PASSED ] 3 tests.
在输出的信息中看到3个测试被完成,显示完成时间,测试结果是否通过,案例中3个测试均通过。
在LineTest这个测试用例里面,getCurrentTime方法用于获取当前时间,等待5秒后,重新获得当前时间,两个时间作差,得出的结果应当是5。在EXPECT_EQ(after - before, 5)中,断言两者相差5,所以断言实现,测试通过,如果把断言改成4,重新运行测试,得到结果如下:
[----------] 1 test from LineTest
[ RUN ] LineTest.getCurrentTime
/home/louis/ctc_ws/src/ctcs/test/uTest.cpp:24: Failure
Value of: 4
Expected: after - before
Which is: 5
[ FAILED ] LineTest.getCurrentTime (5000 ms)
[----------] 1 test from LineTest (5000 ms total)
[----------] Global test environment tear-down
[==========] 3 tests from 2 test cases ran. (5034 ms total)
[ PASSED ] 2 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] LineTest.getCurrentTime
可知一个测试无法通过,原因是期望的输出是4,而结果输出5,在运行测试时会得到警告。