ROS中使用gtest测试框架

Louis
发布于 2019-10-15 / 615 阅读 / 0 评论 / 0 点赞

ROS中使用gtest测试框架

什么是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,在运行测试时会得到警告。

内容拓展

玩转Google开源C++单元测试框架Google Test系列(gtest)之七-深入解析gtest

gtest的介绍和使用


评论