下面的 CMake 命令已经像魔法一样刻在 Unix 的世界里。
./configure
make
make install
在上一篇 Bazel 与 gtest:构建一个最简单的测试驱动开发环境 中,Bazel 可以从 Github 中下载 googletest,其实 CMake 3.11 有了一个 FetchContent
模块,同样支持从网络下载。
CMakeLists.txt (注意大小写)作为顶层目录里的文件,指导生成对应平台的构建文件。不同的 Bazel,我们似乎没必要严格使用 Google 家的单体哲学,因此代码和测试用例会分别放在 src
和 tests
文件夹。
├── CMakeLists.txt
├── src
└── tests
首先,CMake 版本要求,和对应的项目名字:
# 3.11 才有 FetchContent
cmake_minimum_required(VERSION 3.11 FATAL_ERROR)
# 项目名称
project(cmake-gtest LANGUAGES CXX)
googletest 要求 C++11,因此:
# C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
添加源代码文件夹,另外,这里不拆分头文件和实现,因此include_directories
仍然是 src
。如果没有暴露头文件,googletest 是无法获得被测试的代码:
include_directories(src)
add_subdirectory(src)
设置开启单元测试(可选):
option(ENABLE_UNIT_TESTS "Enable unit tests" ON)
message(STATUS "Enable testing: ${ENABLE_UNIT_TESTS}")
接下来的内容都会放到下面的 if
内:
if (ENABLE_UNIT_TESTS)
# 后面的内容都贴到这里
endif()
导入 FetchContent
模块:
include(FetchContent)
指定 googletest 版本和地址:
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.10.0
)
CMake 3.14 版本之后,只需要使用
FetchContent_MakeAvailable(googletest)
就可以了。
如果是 3.14 以前,则需要使用更加具体的构建过程:
FetchContent_GetProperties(googletest)
if(NOT googletest_POPULATED)
FetchContent_Populate(googletest)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(gtest_disable_pthreads ON CACHE BOOL "" FORCE)
# add the targets: gtest、gtest_main、gmock、gmock_main
add_subdirectory(
${googletest_SOURCE_DIR}
${googletest_BINARY_DIR}
)
endif()
先写一个简单的测试项目,在 src
文件夹中新建 CMakeLists.txt,写入:
# example library
add_library(sum_integers sum_integers.cpp)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
# main code
add_executable(sum_up main.cpp)
target_link_libraries(sum_up sum_integers)
sum_integers.hpp:
#pragma once
#include
int sum_integers(const std::vector integers);
sum_integers.cpp:
#include "sum_integers.hpp"
#include
int sum_integers(const std::vector integers)
{
auto sum = 0;
for (auto i : integers)
{
sum += i;
}
return sum;
}
main.cpp
#include
#include
#include
#include "sum_integers.hpp"
int main(int argc, char *argv[])
{
std::vector integers;
for (auto i = 1; i < argc; i++)
{
integers.push_back(std::stoi(argv[i]));
}
auto sum = sum_integers(integers);
std::cout << sum << std::endl;
return 0;
}
tests
文件夹就非常简单了,只需要一个测试:
test.cpp:
#include "sum_integers.hpp"
#include "gtest/gtest.h"
#include
TEST(example, sum_zero)
{
auto integers = {1, -1, 2, -2, 3, -3};
auto result = sum_integers(integers);
ASSERT_EQ(result, 0);
}
TEST(example, sum_five)
{
auto integers = {1, 2, 3, 4, 5};
auto result = sum_integers(integers);
ASSERT_EQ(result, 15);
}
注意一下,因为后面使用的是 gtest_main
就不需要显式的使用样板代码:
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
最后在顶层的 CMakeLists.txt 中添加对测试的支持(注意,放在 if
和 endif()
之间):
add_executable(cpp_test "")
target_sources(cpp_test
PRIVATE
tests/test.cpp
)
target_link_libraries(cpp_test
PRIVATE
sum_integers
gtest_main
)
enable_testing()
add_test(
NAME google_test
COMMAND $
)
这样就完成了一个最简单的 googletest 测试项目了。顺便提一下,CMake 本身自带的 CTest 就是支持 Google Test 的。
接下来到了使用环节,就属于经典操作了:
mkdir -p build
cd build
cmake ..
之后就可以通过 make
命令构建项目了。
make
可以直接使用 ctest
获取测试结果(报告):
ctest
输出:
Start 1: google_test
1/1 Test #1: google_test ...................... Passed 0.02 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.04 sec
或者使用编译好的测试入口:
./cpp_test
输出具体的测试情况:
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from example
[ RUN ] example.sum_zero
[ OK ] example.sum_zero (0 ms)
[ RUN ] example.sum_five
[ OK ] example.sum_five (0 ms)
[----------] 2 tests from example (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[ PASSED ] 2 tests.
现代 CMake 其实也是有自动下载功能的,这点上估计还有很多人不知道。当然,如果非要扯可重入性的话,本地源码才是最靠谱的。