CMake 笔记 | [20] 利用Google Test库进行单元测试

注意
本文最后更新于 2024-01-30,文中内容可能已过时。

一、导言

导言

本篇,我们将学习如何在CMake的帮助下使用Google Test框架实现单元测试。与前一个配置(Catch2)相比,Google Test框架不仅仅是一个头文件,也是一个库,包含两个需要构建和链接的文件。可以将它们与我们的代码项目放在一起,但是为了使项目更加轻量级,我们将选择在配置时,下载一个定义良好的Google Test,然后构建框架并链接它。我们将使用较新的FetchContent模块(从CMake版本3.11开始可用)。关于相关使用将在后续的笔记中学习。

此外我们将在相关测试内同学习完成后挑选一个测试框架(目前Google Test更加流行)*写一个小的项目实践,尽可能多的将该框架下的功能加以熟悉。*

二、项目结构

NOTE:

main.cppsum_integers.cppsum_integers.hpp与上一篇内容相同,我们对test.cpp将做相关的修改。

1
2
3
4
5
6
.
├── CMakeLists.txt
├── main.cpp
├── sum_integers.cpp
├── sum_integers.h
└── test.cpp

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter4/03

三、项目代码

CMakeLists.txt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
cmake_minimum_required(VERSION 3.11 FATAL_ERROR)

project(test_gtest LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

add_library(sum_integers sum_integers.cpp)

add_executable(sum_up main.cpp)
target_link_libraries(sum_up sum_integers)

option(ENABLE_UNIT_TESTS "Enable unit tests" ON)
message(STATUS "Enable testing: ${ENABLE_UNIT_TESTS}")

if(ENABLE_UNIT_TESTS)
  include(FetchContent)

  FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://gitcode.net/mirrors/google/googletest.git
    GIT_TAG        release-1.8.0
  )

  FetchContent_GetProperties(googletest)

  if(NOT googletest_POPULATED)
    FetchContent_Populate(googletest)

    # Prevent GoogleTest from overriding our compiler/linker options
    # when building with Visual Studio
    set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
    # Prevent GoogleTest from using PThreads
    set(gtest_disable_pthreads ON CACHE BOOL "" FORCE)

    # adds the targers: gtest, gtest_main, gmock, gmock_main
    add_subdirectory(
      ${googletest_SOURCE_DIR}
      ${googletest_BINARY_DIR}
    )

    # Silence std::tr1 warning on MSVC
    if(MSVC)
      foreach(_tgt gtest gtest_main gmock gmock_main)
        target_compile_definitions(${_tgt}
          PRIVATE
            "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING"
        )
      endforeach()
    endif()
  endif()

  add_executable(cpp_test "")

  target_sources(cpp_test
    PRIVATE
      test.cpp
  )

  target_link_libraries(cpp_test
    PRIVATE
      sum_integers
      gtest_main
  )

  enable_testing()

  add_test(
    NAME google_test
    COMMAND $<TARGET_FILE:cpp_test>
  )
endif()

**注意:**CMake 3.11版本以后才可以使用FetchContent模块。

引用
1
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

告诉CMakeWindows 平台上自动从共享库(DLL)中导出所有符号(函数、变量、类等)。

当将此选项设置为 ON 时,CMake会自动在库的代码中插入导出指令,确保它们可以被外部链接。这在 Windows 上特别重要,因为需要明确的导出声明才能让符号从 DLL 外部访问。

然而,启用此选项可能会导致生成较大的二进制文件,并可能意外地暴露符号。如果链接了多个库,还可能导致符号冲突。因此,虽然它简化了符号的导出,但需要仔细考虑其影响,以及是否适用于自己的项目。

引用
1
2
3
4
5
option(ENABLE_UNIT_TESTS "Enable unit tests" ON)
message(STATUS "Enable testing: ${ENABLE_UNIT_TESTS}")
if(ENABLE_UNIT_TESTS)
    # all the remaining CMake code will be placed here
endif()

检查ENABLE_UNIT_TESTS。默认情况下,它为ON,但有时需要设置为OFF,以免在没有网络连接时,也能使用Google Test

引用
1
2
3
4
5
6
7
include(FetchContent)

FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://gitcode.net/mirrors/google/googletest.git
  GIT_TAG        release-1.8.0
)

使用了FetchContent模块来下载和集成Google Test库(googletest)。

  • include(FetchContent):用于包含FetchContent模块,该模块允许在项目中获取外部依赖项。
  • FetchContent_Declare(googletest ...):使用FetchContent_Declare宏来声明要获取的外部依赖项。在这种情况下,它声明了一个名为googletest的外部依赖项。
  • GIT_REPOSITORY:这是指定用于获取库的Git存储库的URL
  • GIT_TAG:这是Git存储库中的特定标签或分支,指定希望获取的库的版本。在这里,它指定了Google Test库的版本为release-1.8.0

使用这段代码后,当构建项目时,CMake将尝试下载并集成Google Test库,以便可以在项目中进行单元测试。请注意,实际项目中可能还需要在测试目标中链接Google Test库,并设置测试用例等。

引用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
if(NOT googletest_POPULATED)
    FetchContent_Populate(googletest)

    # Prevent GoogleTest from overriding our compiler/linker options
    # when building with Visual Studio
    set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
    # Prevent GoogleTest from using PThreads
    set(gtest_disable_pthreads ON CACHE BOOL "" FORCE)

    # adds the targers: gtest, gtest_main, gmock, gmock_main
    add_subdirectory(
      ${googletest_SOURCE_DIR}
      ${googletest_BINARY_DIR}
    )

    # Silence std::tr1 warning on MSVC
    if(MSVC)
      foreach(_tgt gtest gtest_main gmock gmock_main)
        target_compile_definitions(${_tgt}
          PRIVATE
            "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING"
        )
      endforeach()
    endif()
  endif()
  • if(NOT googletest_POPULATED):检查是否已经获取并集成了Google Test库。如果googletest_POPULATED未定义,则会执行其中的代码块。
  • FetchContent_Populate(googletest):将下载的Google Test库内容填充到指定的目录,以便后续构建和集成。
  • set(gtest_force_shared_crt ON CACHE BOOL "" FORCE):在使用Visual Studio构建时,将强制Google Test使用共享运行时(C Runtime)库。可以避免构建时的链接错误。
  • set(gtest_disable_pthreads ON CACHE BOOL "" FORCE):禁用Google Testpthreads的使用。这可能在某些环境中是必需的,例如在没有pthreads支持的平台上。
  • add_subdirectory(...):将Google Test库添加到项目中。它会在指定的源码目录和二进制目录中进行构建。
  • 对于Microsoft Visual Studio(MSVC),在构建Google Test库时,通过target_compile_definitionsgtestgtest_maingmockgmock_main目标添加了宏定义以消除MSVC下的警告。
相关源码

test.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include "sum_integers.h"
#include "gtest/gtest.h"
#include <vector>

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

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);
}
输出:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mkdir build
cd build
cmake ..
ctest
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/03/build
    Start 1: google_test
1/1 Test #1: google_test ......................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.01 sec
./cpp_test
[==========] Running 2 tests from 1 test case.
[----------] 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 case ran. (0 ms total)
[  PASSED  ] 2 tests.
Buy me a coffee~
支付宝
微信
0%