CMake 与 gtest:自动下载 gtest 与搭建测试驱动环境

下面的 CMake 命令已经像魔法一样刻在 Unix 的世界里。

./configure
make
make install

在上一篇 Bazel 与 gtest:构建一个最简单的测试驱动开发环境 中,Bazel 可以从 Github 中下载 googletest,其实 CMake 3.11 有了一个 FetchContent 模块,同样支持从网络下载。

项目结构

CMakeLists.txt (注意大小写)作为顶层目录里的文件,指导生成对应平台的构建文件。不同的 Bazel,我们似乎没必要严格使用 Google 家的单体哲学,因此代码和测试用例会分别放在 srctests 文件夹。

├── CMakeLists.txt
├── src
└── tests

CMakeLists.txt

首先,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 中添加对测试的支持(注意,放在 ifendif() 之间):

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 其实也是有自动下载功能的,这点上估计还有很多人不知道。当然,如果非要扯可重入性的话,本地源码才是最靠谱的。

你可能感兴趣的:(C/C++,cmake)