【Cmake】Ctest测试工具

目录

前言

一、初识CTest

二、使用方法

三、完整的简单测试工程

附录

附录一 cmake命令

enable_testing

add_test


前言

原文:CTest - https://www.cnblogs.com/457220157-FTD/p/4139149.html

一、初识CTest

       CTest是CMake集成的一个测试工具,在使用CMakeLists.txt文件编译工程的时候,CTest会自动configure、build、test和展现测试结果

       CTest有两个模式:

  • 模式一: 使用CMake configure 和 build工程,在CMakeLists.txt文件中,使用特殊的命令取创建tests。CTest用来执行那些测试
  • 模式二: 使用CTest来执行一个script(这个script的语法必须和CMakeLists.txt相同),去控制整个程序的输出结果=

二、使用方法

  目前我们在工程中这样构建单元测试

project
 |--------include
 |
 |--------src
 |
 |-----------test
 |       |---CMakeLists.txt
 |
 |--------CMakeLists.txt

  1. 在外面的CMakeLists.txt中我们这样写

cmake_minimum_required(VERSION 2.8)
project(test)#指定工程名
....
add_subdirectory(test)#递归进入test目录
enable_testing()#见附录1 可以开启项目的测试功能。一定要在根目录下的CMakeLists.txt中开启
add_test(NAME mytest COMMAND Test)#见附录1

  2. 在test/CMakeLists.txt中写你的测试需要的即可(可以如下面那样写)

三、完整的简单测试工程

include

//sqr.h
 
 
#ifndef SQR_H_
#define SQR_H_
 
double sqr(double);
 
#endif

src  #我们的工程代码

//sqr.cpp
 
#include "sqr.h"
 
double sqr(double x) {
    return x * x;
}
 
//main.cpp
int main()
{
    return 0;
}

test #Ctest的代码,测试我们的工程函数

//test.cpp
#include "sqr.h"
#define BOOST_TEST_MODULE SqrTests
#include <boost/test/unit_test.hpp>
 
 
 
BOOST_AUTO_TEST_CASE(FailTest)
{
    BOOST_CHECK_EQUAL(5, sqr(2));
}
 
 
BOOST_AUTO_TEST_CASE(PassTest)
{
    BOOST_CHECK_EQUAL(4, sqr(2));
}
 
//CMakeLists.txt
find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
 
include_directories(include ${Boost_INCLUDE_DIRS}/boost)
 
add_definitions(-DBOOST_TEST_DYN_LINK -g)
add_executable(Test test.cpp)
 
target_link_libraries(Test sqr ${Boost_FILESYSTEM_LIBRARY}
                               ${Boost_SYSTEM_LIBRARY}
                               ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
 
message(WARNING ${Boost_FILESYSTEM_LIBRARY})
message(WARNING ${Boost_SYSTEM_LIBRARY})
message(WARNING ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})

 CMakeLists.txt #test的CMakeLists

cmake_minimum_required(VERSION 2.8)
project(test)
 
include_directories(include)
add_library(sqr STATIC src/sqr.cpp)
 
add_executable(demo src/main.cpp)
target_link_libraries(demo sqr)
 
add_subdirectory(test)
enable_testing()
add_test(NAME mytest COMMAND Test)

简单例子说明

通过在项目根目录下的CMakeLists.txt配置文件中添加

enable_testing()


可以开启项目的测试功能。一定要在根目录下的CMakeLists.txt中开启,不然执行make test时会报错。

随后项目的cmake配置文件中可以添加add_test指令

add_test(NAME <name> [CONFIGURATIONS [Debug|Release|...]]
           [WORKING_DIRECTORY dir]
           COMMAND <command> [arg1 [arg2 ...]])



其中通过NAME关键值指定本测试的名称,可以随意命名,
Debug/Release选项可以控制在不同的编译版本下是否进行测试。
通过WORKING_DIRECTORY可以设置工作路径,command表示可运行程序

比如:

ADD_TEST(NAME test1 COMMAND main)



你可以不对结果进行检查,但大多数情况下你都需要检查test1的输出结果,可以通过如下:

set_tests_properties(test1 PROPERTIES PASS_REGULAR_EXPRESSION "Hello Cmake")


运行cmake && make test结果如下:

Start 1: test1
1/1 Test #1: test1 ............................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 1


如果失败的话,也会有提示

Start 1: test1
1/1 Test #1: test1 ............................***Failed  Required regular expression not found.Regex=[Hello
]  0.00 sec

0% tests passed, 1 tests failed out of 1
 

原文链接:https://blog.csdn.net/sun_ashe/article/details/104527591/

示例2

CMakeCTest简单示例 -https://wenku.baidu.com/view/12bb3c49bb4ae45c3b3567ec102de2bd9605de82.html

cmake命令之add_test和set_tests_properties使用案例

(摘自:https://blog.csdn.net/weixin_42108533/article/details/119220713)

add_test的命令形式如下

add_test(NAME <name> COMMAND <command> [<arg>...]
         [CONFIGURATIONS <config>...]
         [WORKING_DIRECTORY <dir>]
         [COMMAND_EXPAND_LISTS])

set_tests_properties的命令形式如下

set_tests_properties(test1 [test2...] 
PROPERTIES prop1 value1 prop2 value2)

我见过的cmake工具测试的套路之一如下

  • 首先,启动测试 enable_testing()

(开启项目的测试功能。一定要在根目录下的CMakeLists.txt中开启,不然执行make test时会报错。)

  • 其次,add_test(...)
  • 接下来,set_tests_properties(...)

案例目录如下

├── build
├── CMakeLists.txt
└── main.cpp

main.cpp的内容如下

#include<stdlib.h>
#include<stdio.h>

using namespace std;

int sum(int a, int b)
{
    return a + b;
}

int main(int argc, char *argv[])
{
    if(3 == argc)
    {
        cout << "parameter right" << endl;
        cout << sum(atoi(argv[1]), atoi(argv[2])) << endl;
    }
    else
    {
        cout << "input num err" << endl;
        return -1;
    }

    return 0;
}

CMakeLists.txt的内容如下

#最小版本说明
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
 
#项目信息
PROJECT(main)
 
#生成可执行文件
ADD_EXECUTABLE(main main.cpp)
 
#使能测试
enable_testing()
 
#添加测试
add_test(demo_test main 2 3)
 
#设定测试特性
set_tests_properties(demo_test PROPERTIES PASS_REGULAR_EXPRESSION "5")

build是编译目录,方便编译出错时,清除生成的缓存文件

cd build  //进入编译目录
cmake ..   //编译主目录的CMakeLists.txt
make        //编译生成的MakeFile.txt
make test   //执行CMakeLists.txt里的测试

执行结果如下图所示

参考文献如下

cmake的帮助文档的网址

CMake Reference Documentation — CMake 3.21.7 Documentation

附录

附录一 cmake命令

enable_testing

可以开启项目的测试功能。

一定要在根目录下的CMakeLists.txt中开启,不然执行make test时会报错。

添加对TestingDashboard的支持
在之前已经定义了项目对测Test的支持,现在只需要将那些Test上传到Dashboard。
在上层CMakeLists.txt中将

# enable testing
enable_testing()

替换成

# enable dashboard scripting
include(CTest)


CTest模块将自动调用enable_testing().
创建CTestConfig.cmake在上层目录中,在cmake文件中,我们可以声明项目的名字和上传到的地址。在cmake文件中,添加如下内容:

set(CTEST_PROJECT_NAME "CMakeTutorial")
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")

set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
set(CTEST_DROP_SITE_CDASH TRUE)


当ctest运行时将读取这个文件。

cmake完成之后,运行以下指令将测试上传到Dashboard:

ctest [-VV] -D Experimental


利用-C选项设置生成器:

ctest [-VV] -C Debug -D Experimental



可以在https://my.cdash.org/index.php?project=CMakeTutorial.查看测试结果。
原文链接:https://blog.csdn.net/xu_yun_huan_yue/article/details/120155307

add_test

该命令将目标(或自定义命令)添加到CTest。因此,当您在build目录中执行ctest时,所有添加的测试都会执行。如果您不想使用CTest,而只是手动执行测试二进制文件,那么就没有必要使用add_test

在较大的项目中,测试通常由几个二进制文件组成,使用单个命令执行所有测试会更方便(特别是当您的构建管道是自动化的时候)。

CMake的CTest方法

摘自:http://t.csdn.cn/pIiJW

PART 1:

参考:http://hahack.com/codes/cmake/


Demo目录结构如下:

Test/
├── add.cpp
└── CMakeLists.txt

add.cpp
#include <iostream>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    if (argc != 3) {
        std::cout << "parameter error" << std::endl;
        return -1; 
    }   
 
    int a, b;
    a = atoi(argv[1]);
    b = atoi(argv[2]);
    std::cout << a << " + " << b << " is " << a + b << std::endl;
    return 0;
}

CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
ADD_EXECUTABLE(add add.cpp)
enable_testing()
ADD_TEST(NAME test_add_2_3 COMMAND add 2 3)
SET_TESTS_PROPERTIES(test_add_2_3
    PROPERTIES PASS_REGULAR_EXPRESSION "5")
ADD_TEST(NAME test_add_4_5 COMMAND add 4 5)
SET_TESTS_PROPERTIES(test_add_4_5
    PROPERTIES PASS_REGULAR_EXPRESSION "9")
在CMakeLists.txt里面,我们添加了两个测试用例。其中 PASS_REGULAR_EXPRESSION 用来测试输出是否包含后面的字符串。
在Test目录下建立build目录,cd build && cmake .., make, make test, 结果如下:

huyanjie@debian:~/test/Test/build$ make test
Running tests...
Test project /home/huyanjie/test/Test/build
    Start 1: test_add_2_3
1/2 Test #1: test_add_2_3 .....................   Passed    0.00 sec
    Start 2: test_add_4_5
2/2 Test #2: test_add_4_5 .....................   Passed    0.00 sec
 
100% tests passed, 0 tests failed out of 2
 
Total Test time (real) =   0.01 sec
可以看到两个用例都正确执行了。
像上面的方式写测试用例还是比较繁琐,还可以定义宏来简化:

CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
ADD_EXECUTABLE(add add.cpp)
enable_testing()
 
macro(do_test ARG1 ARG2 RESULT)
    ADD_TEST(NAME test_add_${ARG1}_${ARG2} COMMAND add ${ARG1} ${ARG2})
    SET_TESTS_PROPERTIES(test_add_${ARG1}_${ARG2}
        PROPERTIES PASS_REGULAR_EXPRESSION ${RESULT})
endmacro(do_test)
do_test(2 3 5)
do_test(4 5 9)
PART 2:

CPPUNIT使用如下:

参考http://blog.csdn.net/freefalcon/article/details/753819

#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TextOutputter.h>
#include <cppunit/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
 
class StringTest : public CppUnit::TestFixture
{
    CPPUNIT_TEST_SUITE(StringTest);
    CPPUNIT_TEST(testSwap);
    CPPUNIT_TEST(testFind);
    CPPUNIT_TEST_SUITE_END();
public:
    void setUp()
    {   
        m_str1 = "Hello, world";
        m_str2 = "Hi, cppunit";
    }   
    void tearDown()
    {   
 
    }   
    void testSwap()
    {   
        std::string str1 = m_str1;
        std::string str2 = m_str2;
        m_str1.swap(m_str2);
        CPPUNIT_ASSERT(m_str1 == str2);
        CPPUNIT_ASSERT(m_str2 == str2);
    }   
    void testFind()
    {   
        int pos1 = m_str1.find(',');
        int pos2 = m_str2.rfind(',');
        CPPUNIT_ASSERT_EQUAL(5, pos1);
        CPPUNIT_ASSERT_EQUAL(2, pos2);
    }   
protected:
    std::string m_str1;
    std::string m_str2;
};
 
CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);
int main(int argc, char *argv[])
{
    CppUnit::TestResult r;
    CppUnit::TestResultCollector rc;
    r.addListener(&rc);
 
    CppUnit::TestRunner runner;
    runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
    runner.run(r);
 
    CppUnit::TextOutputter o(&rc, std::cout);
    o.write();
 
    return rc.wasSuccessful()?0:-1;
}
PART 3

CMake 结合CPPUnit


原文链接:https://blog.csdn.net/huyanjie0327/article/details/46652313

posted on 2022-10-04 01:21  bdy  阅读(3283)  评论(0编辑  收藏  举报

导航