外观
【12】CTest 工具
1413字约5分钟
教学视频
即将到来 ...
- 【12】CMake:CTest 工具
1. 前言
CMake 提供了一个名为 CTest 的工具,用于管理和运行测试用例。主要功能有
- 自动发现和运行测试
- 并行测试执行
- 测试结果收集和报告
提示
测试一般分为以下几种类型:
- 单元测试 —— 它是对软件中的最小可测试单元进行检查和验证的过程。单元测试通常是由开发人员编写的,用于验证代码的正确性。单元测试的目的是确保代码的每个部分都能正常工作,从而提高代码的质量。单元测试一般隔离性强,不依赖外部组件。
- 集成测试 —— 它是对软件中的多个模块进行联合测试的过程。集成测试通常是由测试人员和开发人员共同编写的,用于验证软件的整体功能。集成测试的目的是确保软件的各个模块能够协同工作,从而提高软件的质量。集成测试一般需要测试环境。
- 系统测试 —— 它是对软件的整体功能进行测试的过程。系统测试通常是由测试人员编写的,用于验证软件的整体功能。系统测试的目的是确保软件的整体功能能够满足用户的需求。系统测试一般需要完整的测试环境,主要在功能、性能、负载、安全等方面进行测试。
2. CTest 的基本介绍
在安装 CMake 的同时,CTest 也会被安装。因此,我们可以直接在 CMakeLists.txt
文件中使用 CTest 相关的内容。
2.1 启用测试
在添加测试之前,我们需要在 CMakeLists.txt
文件中启用测试。启用测试的方法是在 CMakeLists.txt
文件中添加
enable_testing()
我们先准备一个简单的计算两数之和的项目,目录如下
Add
├── CMakeLists.txt
├── main.cpp
├── add.cpp
└── add.hpp
add.cpp
#include "add.hpp"
int add(int a, int b)
{
return a + b;
}
add.hpp
#ifndef ADD_HPP
#define ADD_HPP
int add(int a, int b);
#endif // ADD_HPP
main.cpp
#include <cstdio>
#include <cstdlib>
#include "add.hpp"
int main(int argc, char *argv[])
{
if (argc < 4)
{
printf("Usage: %s <a> <b> <sum>\n", argv[0]);
return -1;
}
int a = std::atoi(argv[1]);
int b = std::atoi(argv[2]);
int predict = std::atoi(argv[3]);
int sum = add(a, b);
return sum == predict ? 0 : -1;
}
这是一个简单的计算两数之和的项目,需要用户输入 3 个命令行参数,分别是两个加数和预期的和。如果计算结果与预期的和相等,则返回 0
,否则返回 -1
。然后,我们在 CMakeLists.txt
文件中写入以下内容
cmake_minimum_required(VERSION 3.16)
project(Add)
add_library(add STATIC add.cpp)
add_executable(demo main.cpp)
target_link_libraries(demo PRIVATE add)
enable_testing()
至此,我们完成了测试的前期准备工作。
2.2 添加测试
在 CMakeLists.txt
文件中添加测试的方法是使用 add_test
命令。add_test
命令的语法如下
add_test(
NAME <name> # 测试的名称,可以随便写,但最好见名知意
COMMAND <command> [arg1 [arg2 ...]] # 测试的命令,可以是一个可执行文件或一个脚本
)
其中,name
是测试的名称,command
是测试的命令。我们在 CMakeLists.txt
文件末尾写入以下内容以添加 5 个测试
add_test(NAME AddTest.positive COMMAND demo 1 2 3)
add_test(NAME AddTest.negative COMMAND demo -1 -2 -3)
add_test(NAME AddTest.zero COMMAND demo 0 0 0)
add_test(NAME AddTest.mixed COMMAND demo 1 -2 -1)
add_test(NAME AddTest.failed_example COMMAND demo 1 2 4)
2.3 运行测试
在项目根目录下执行以下命令,构建项目
mkdir build
cd build
cmake ..
cmake --build .
然后,我们可以使用以下命令运行测试
ctest
运行结果如下
Test project /path/to/Add/build
Start 1: AddTest.positive
1/5 Test #1: AddTest.positive ................. Passed 0.00 sec
Start 2: AddTest.negative
2/5 Test #2: AddTest.negative ................. Passed 0.00 sec
Start 3: AddTest.zero
3/5 Test #3: AddTest.zero ..................... Passed 0.00 sec
Start 4: AddTest.mixed
4/5 Test #4: AddTest.mixed .................... Passed 0.00 sec
Start 5: AddTest.failed_example
5/5 Test #5: AddTest.failed_example ...........***Failed 0.00 sec
80% tests passed, 1 tests failed out of 5
Total Test time (real) = 0.01 sec
3. 与 GoogleTest 结合使用
GoogleTest 是 Google 开发的一个 C++ 测试框架,它提供了丰富的断言和测试用例管理功能,CMake 也提供了 GoogleTest 相关的宏和函数,可以很方便的将 GoogleTest 与 CTest 集成。
3.1 文件准备
首先,我们可以直接删除 main.cpp
文件,但可以添加一个测试文件 test_add.cpp
,变更后的目录结构如下
Add
├── CMakeLists.txt
├── add.cpp
├── add.hpp
└── test_add.cpp
test_add.cpp
文件内容如下
#include <gtest/gtest.h>
#include "add.hpp"
TEST(AddTest, Positive) { EXPECT_EQ(add(1, 2), 3); }
TEST(AddTest, Negative) { EXPECT_EQ(add(-1, -2), -3); }
TEST(AddTest, Zero) { EXPECT_EQ(add(0, 0), 0); }
TEST(AddTest, Mixed) { EXPECT_EQ(add(1, -2), -1); }
TEST(AddTest, FailedExample) { EXPECT_EQ(add(1, 2), 4); }
然后,我们改写 CMakeLists.txt
文件,使其支持 GoogleTest 测试框架。改写后的 CMakeLists.txt
文件内容如下
cmake_minimum_required(VERSION 3.16)
project(Add)
add_library(add STATIC add.cpp)
# 先不要疑惑为什么 test_add.cpp 没有 main 函数也可以编译成可执行文件,后面会解释
add_executable(test_add test_add.cpp)
find_package(GTest REQUIRED) # 寻找 GTest 库
include(GoogleTest) # 使用 GoogleTest 提供的 CMake 函数
# GTest::gtest_main 提供了 main 函数,因此 test_add.cpp 不需要额外提供 main 函数
target_link_libraries(test_add
PRIVATE add GTest::gtest_main
)
enable_testing()
# 自动添加 GoogleTest 测试用例
gtest_discover_tests(test_add)
3.2 运行测试
在项目根目录下执行以下命令,构建项目
mkdir build
cd build
cmake ..
cmake --build .
最后,我们可以使用以下命令运行测试
ctest
运行结果如下
Test project /path/to/Add/build
Start 1: AddTest.Positive
1/5 Test #1: AddTest.Positive ................. Passed 0.00 sec
Start 2: AddTest.Negative
2/5 Test #2: AddTest.Negative ................. Passed 0.00 sec
Start 3: AddTest.Zero
3/5 Test #3: AddTest.Zero ..................... Passed 0.00 sec
Start 4: AddTest.Mixed
4/5 Test #4: AddTest.Mixed .................... Passed 0.00 sec
Start 5: AddTest.FailedExample
5/5 Test #5: AddTest.FailedExample ............***Failed 0.00 sec
80% tests passed, 1 tests failed out of 5
Total Test time (real) = 0.01 sec