通过 CMake 进行测试

2019-08-10 language c/cpp

CMake 除了提供自动编译的工具之外,还可以用来进行测试,提供了一整套基于 ctest 的工具。

使用简介

可以通过如下方式添加测试用例。

OPTION(WITH_UNIT_TESTS "Compile with unit tests" OFF)

# Setup testing
IF(WITH_UNIT_TESTS)
        ENABLE_TESTING()
        ADD_SUBDIRECTORY(test)
ENDIF()

# test/CMakeLists.txt
FILE(GLOB SRCS *.c)
ADD_EXECUTABLE(testfoo ${SRCS})
TARGET_LINK_LIBRARIES(testfoo libs)
ADD_TEST(
    NAME testfoo
    COMMAND testfoo your arguments
)

然后在编译时通过 cmake .. -DWITH_UNIT_TESTS=ON 执行,并通过 make test 进行测试,实际等价于在 build 目录下运行 ctest 命令。

另外,可以指定测试的参数,以及输出的匹配。

ADD_TEST(test foobar 10 5)
SET_TESTS_PROPERTIES(test PROPERTIES PASS_REGULAR_EXPRESSION "ok")

对于 valgrind,如果输出是 reachable 类型,那么实际上是依赖于 OS 的内存回收,此时及时已经配置了 --error-exitcode=1 也不会返回 0 ,尤其是对于全局变量。

为此,对于 CMake 而言,就需要配置 FAIL_REGULAR_EXPRESSION "reachable",这样对其它内存泄露也会报错。

SetUp TearDown

一般在测试用例中会存在 SetUp 以及 TearDown ,分别用来做一些测试前后的准备工作,除此之外,还有一种方式 Fixture ,也就是打桩。

相比来说,打桩的处理流程会更加复杂,通常为了方便管理,会将测试相关的内容单独抽象一层。

CMAKE_MINIMUM_REQUIRED(VERSION 3.7)

PROJECT(foo)

ENABLE_TESTING()

#ADD_TEST(NAME DBSetUp   COMMAND /usr/bin/false)
ADD_TEST(NAME DBSetUp   COMMAND ${CMAKE_COMMAND} -E echo setup)
ADD_TEST(NAME DBCleanUp COMMAND ${CMAKE_COMMAND} -E echo cleanup)
ADD_TEST(NAME TCaseFoo  COMMAND ${CMAKE_COMMAND} -E echo "Needs Fixture Foo")
ADD_TEST(NAME TCaseBar  COMMAND ${CMAKE_COMMAND} -E echo "Needs Fixture Bar")

# Specified multi dependences, like "DB;File"
SET_TESTS_PROPERTIES(TCaseFoo TCaseBar
                                PROPERTIES FIXTURES_REQUIRED  DB)
SET_TESTS_PROPERTIES(DBSetUp    PROPERTIES FIXTURES_SETUP     DB)
SET_TESTS_PROPERTIES(DBCleanUp  PROPERTIES FIXTURES_CLEANUP   DB)
SET_TESTS_PROPERTIES(DBSetUp DBCleanUp TCaseFoo TCaseBar
        PROPERTIES RESOURCE_LOCK SerialDB
)

在运行一堆的测试用例之前,需要准备一些资源,最常见的是 DB 相关的数据。

----- 运行指定的测试用例
$ ctest -R <TEST_NAME>

----- 重新运行失败的用例
$ ctest --rerun-failed

如果通过 ctest 单独测试某个用例,ctest 会先根据配置生成相关的依赖,如果 SetUp 执行失败会跳过相关的测试用例 (注意,清理函数还会继续执行) 。

当已经完成测试,可以通过 ctest -R cleanup 执行清理操作。

默认各个测试是并发执行的,如果需要串行执行,可以通过 RESOURCE_LOCK 来实现。

其它

超时设置

可以针对单个测试用例设置超时时间,单位是秒。

ADD_TEST(yourtest ...)
SET_TESTS_PROPERTIES(yourtest PROPERTIES TIMEOUT 30)

另外,如果单独使用 ctest 进行测试,那么可以在启动的时候添加 --timeout 120 参数,指定默认的超时时间。

参考