0. 简介
在开发大量的程序后,我们发现每一个之前留下的BUG都需要耗费大量的时间去排查设计。这样会造成算法开发人员耗费大量的时间和精力。而gtest就是这样的一个工具,它是Google的一个开源框架,主要功能是用于编写单元测试,从而检查自己的程序是否符合预期行为。这当然是QA(测试工程师)最常用的工具,但是作为一名算法工程师也需要清楚自己的算法是否符合设计需求以及规范。
1. 认识 gtest
1.1 安装 gtest
gtest作为一种测试框架,它可以在垮平台(Linux,Mac OS X,Windows,Cygwin,Windows CE和Symbian)编写C++测试程序。它是基于xUnit架构的测试框架,支持自动发现测试,丰富的断言集,用户定义的断言,death测试,致命与非致命的失败,类型参数化测试,各类运行测试的选项和XML的测试报告。
#下载链接# git clone https://github.com/google/googletest.git# mkdir -p googletest/build# cd googletest/build# cmake ..# make -j8# sudo make install# 或者直接apt安装sudoapt-getinstall libgtest-dev
# 更新Apt工具软件包列表sudoapt update
# 装GCC、MAKE、GDB等工具sudoaptinstall build-essential gdb
通过上述操作,GTest库文件安装在**/usr/local/lib/目录,头文件安装在/usr/local/include/**目录。
1.2 gtest编程
这里为了验证gtest安装的情况,我们给出了一个demo程序示例。
CMakeLists.txt:
cmake_minimum_required(VERSION 3.1.0)
project(main VERSION 0.1.7)# 添加库文件,库文件名称为:${PROJECT_NAME},也就是xxx# 依赖的实现文件是xxx.cpp#add_library(${PROJECT_NAME} xxx.cpp)# Generate the testing executable file.
include(CTest)# 启用测试
enable_testing()# 添加测试可执行文件,即最后生成的可执行文件名称为:main_test,# 依赖的实现文件是main.cpp
add_executable(${PROJECT_NAME}_test main.cpp)# 寻找GTest和Threads库,两个库必需
find_package(GTest REQUIRED)
find_package(Threads REQUIRED)# 包含GTest的头文件目录
include_directories(${GTEST_INCLUDE_DIRS})# 生成测试可执行文件main_test需要链接gtest、pthread库
target_link_libraries(${PROJECT_NAME}_test ${GTEST_BOTH_LIBRARIES}${CMAKE_THREAD_LIBS_INIT})# 让CMake能够发现main_test文件,以便使用ctest命令时能够自动运行测试文件
gtest_discover_tests(${PROJECT_NAME}_test)# 当前及其下级目录打开测试功#set(FooTestArgs --foo 1 --bar 2)#gtest_add_tests(FooTest "${FooTestArgs}" AUTO)# CMake 原生支持的测试很简单# add_test(StringOperationTest ${PROJECT_NAME}_test)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
main.cpp
#include<gtest/gtest.h>intadd(int a,int b){return a + b;}TEST(testCase, test0){EXPECT_EQ(add(8,11),19);}intmain(int argc,char**argv){
testing::InitGoogleTest(&argc, argv);returnRUN_ALL_TESTS();}
1.3
gtest_add_tests
与
gtest_discover_tests()
这里着重强调一下
gtest_add_tests
与
gtest_discover_tests()
,这两个命令旨在代替使用 add_test() 注册测试,并且将为每个Google Test测试用例创建一个单独的CTest测试。
gtest_add_testst
通过扫描源代码的谷歌测试宏,用CTest自动添加测试
gtest_add_tests(TARGET target
[SOURCES src1...][EXTRA_ARGS arg1...][WORKING_DIRECTORY dir][TEST_PREFIX prefix][TEST_SUFFIX suffix][SKIP_DEPENDENCY][TEST_LIST outVar])# test
include(GoogleTest)
add_executable(FooTest FooUnitTest.cxx)
gtest_add_tests(TARGET FooTest
TEST_SUFFIX .noArgs
TEST_LIST noArgsTests
)
set_tests_properties(${noArgsTests} PROPERTIES TIMEOUT 10)
TARGET target
指定Google测试可执行文件,它必须是一个已知的CMake可执行文件目标。当运行测试时,CMake将替代构建的可执行文件的位置。
SOURCES src1...
提供后,将仅扫描列出的文件以查找测试用例。如果未提供此选项,则将使用指定 target 的 SOURCES 属性获取源列表。
EXTRA_ARGS arg1...
在命令行上传递给每个测试用例的任何额外参数。
WORKING_DIRECTORY dir
指定运行已发现的测试用例的目录,如果没有提供这个选项,则使用当前的二进制目录。如果没有提供这个选项,则使用当前的二进制目录。
TEST_PREFIX prefix
指定在每个发现的测试用例名称之前添加的 prefix 。当在多次调用 gtest_add_test() 的过程中使用相同的源文件,但使用不同的 EXTRA_ARGS 时,这将很有用。
TEST_SUFFIX suffix
与 TEST_PREFIX 相似,不同之处在于在每个发现的测试用例的名称后都添加了 suffix 。无论 TEST_PREFIX 和 TEST_SUFFIX 可以指定。
SKIP_DEPENDENCY
通常情况下,这个函数会创建一个依赖关系,如果任何被扫描的源代码被改变,这个依赖关系会导致 CMake 被重新运行。这是为了确保发现的测试列表被更新。如果不需要这种行为 (在实际编写测试用例的时候可能会这样),可以使用这个选项来防止依赖关系被添加。
TEST_LIST outVar
由 outVar 命名的变量将在调用范围中填充发现的测试用例列表。这允许调用者执行诸如操作发现的测试的测试属性之类的操作。
CMake 自从 3.10 提供了新的方法,也就是我们下面要说的
gtest_discover_tests()
gtest_discover_tests(target
[EXTRA_ARGS arg1...][WORKING_DIRECTORY dir][TEST_PREFIX prefix][TEST_SUFFIX suffix][NO_PRETTY_TYPES][NO_PRETTY_VALUES][PROPERTIES name1 value1...][TEST_LIST var][DISCOVERY_TIMEOUT seconds][XML_OUTPUT_DIR dir][DISCOVERY_MODE <POST_BUILD|PRE_TEST>])# test
enable_testing()
include(GoogleTest)
find_package(GTest 1.10.0)
add_executable(test test.cpp)
target_link_libraries(test GTest::gtest GTest::gtest_main GTest::gmock
GTest::gmock_main)
gtest_discover_tests(test)
target
指定Google测试可执行文件,它必须是一个已知的CMake可执行文件目标。当运行测试时,CMake将替代构建的可执行文件的位置。
EXTRA_ARGS arg1...
在命令行上传递给每个测试用例的任何额外参数。
WORKING_DIRECTORY dir
指定运行已发现的测试用例的目录,如果没有提供这个选项,则使用当前的二进制目录。如果没有提供这个选项,则使用当前的二进制目录。
TEST_PREFIX prefix
指定在每个发现的测试用例名称之前添加的 prefix 。当在多次调用 gtest_discover_tests() 的过程中使用相同的测试可执行文件,但使用不同的 EXTRA_ARGS 时,这将很有用。
TEST_SUFFIX suffix
与 TEST_PREFIX 相似,不同之处在于在每个发现的测试用例的名称后都添加了 suffix 。无论 TEST_PREFIX 和 TEST_SUFFIX 可以指定。
NO_PRETTY_TYPES
默认情况下,类型参数化测试的类型索引会被CTest测试名称中的实际类型名称所取代。如果这种行为是不可取的(例如,因为类型名很累赘),这个选项将抑制这种行为。
NO_PRETTY_VALUES
默认情况下,值参数化测试的值索引会被CTest测试名称中的实际值取代。如果这种行为不可取(例如,因为值字符串很累赘),这个选项将抑制这种行为。
PROPERTIES name1 value1...
指定在通过调用 gtest_discover_tests() 发现的所有测试上设置的附加属性。
TEST_LIST var
使测试列表在变量 var 中可用,而不是默认的 _TESTS 中。当在多次调用 gtest_discover_tests() 的过程中使用同一测试可执行文件时,此功能很有用。请注意,此变量仅在CTest中可用。
DISCOVERY_TIMEOUT num
3.10.3版的新内容。指定CMake等待测试枚举可用测试的时间(以秒为单位)。如果测试花费的时间超过此时间,则发现(和您的构建)将失败。大多数测试可执行文件会很快枚举其测试,但是在某些特殊情况下,测试可能需要更长的超时时间。默认值为5。另请参见 execute_process() 的 TIMEOUT 选项。
1.4 gtest 断言(assertion)
在gtest中,是通过断言(assertion)来判断代码实现的功能是否符合预期。断言的结果分为
success
、
non-fatal failture
和
fatal failture
。
根据断言失败的种类,gtest提供了两种断言函数:
success
:即断言成功,程序的行为符合预期,程序继续向下允许。non-fatal failure
:即断言失败,但是程序没有直接crash,而是继续向下运行。gtest提供了宏函数EXPECT_XXX(expected, actual)
:如果condition(expected, actual)
返回false
,则EXPECT_XXX
产生的就是non-fatal failure
错误,并显示相关错误。fatal failure
:断言失败,程序直接crash,后续的测试案例不会被运行。gtest提供了宏函数ASSERT_XXX(expected, actual)
。在写单元测试时,更加倾向于使用EXPECT_XXX
,因为ASSERT_XXX
是直接crash退出的,可能会导致一些内存、文件资源没有释放,因此可能会引入一些bug。
2. ROS中使用gtest
…详情请参照古月居
版权归原作者 敢敢のwings 所有, 如有侵权,请联系我们删除。