2025-02-27 15:46阅读: 28评论: 0推荐: 0

Windows下搭建googletest测试环境 for Qt6

背景

因为需要将CMake构建的项目从VS 2022移植到Qt6,网上找了很多资料,但很少有适用于自己情况的,比如最简单的,通过CMake从网络下载googletest代码到项目,在Qt CMake上无法下载,而在VS 2022上下载、编译完全没有问题. 于是,决定从官网找解决办法.

官网:github googeltest Readme文档

环境

环境1:

工具环境 版本
系统 Win10x64专业版
IDE VS 2022
编译器 msvc 17.2
构建工具 CMake 3.23.1

环境2:

工具环境 版本
系统 Win10x64专业版
IDE Qt 6.5.2
编译器 MinGW 11.2.0 64bit
构建工具 CMake 3.24.2

googletest源码包:googletest Release 1.16.0


注意:

  1. googletest要求CMake使用3.14以后版本,因为后面用到FetchContent_MakeAvailable()命令;
  2. googletest要求使用C++14以后版本,才能成功编译.

CMake构建项目

构建GoogleTest并使用之,就是需要告诉我们的构建系统,在哪可以找到头文件、源文件、库文件.

搭建googletest环境,有2步:

1)作为独立的CMake项目进行编译;
2)集成到客户已有源码的项目.

独立的CMake项目

Step1. 下载源码包并构建编译脚本

  • 使用命令行

可从googletest官网下载源码包,也可用Powershell执行下面命令下载,然后生成构建脚本:

git clone https://github.com/google/googletest.git -b v1.16.0
cd googletest        # Main directory of the cloned repository.
mkdir build          # Create a directory to hold the build output.
cd build
cmake ..             # Generate native build scripts for GoogleTest.

上面默认包含了GoogleMock(Mock,基于GoogleTest框架,可用来模拟对象行为). 如果不想要,上面最后一行命令可换为:

cmake .. -DBUILD_GMOCK=OFF

默认是用Debug模式构建,如果想用Release模式,则可执行:

cmake --build . --config Release -v
  • 使用CMake-gui

当然,也可用CMake-gui进行这步操作(不一定非得VS 2022编译器):

img

Configure后,会得到如下结果:
img

这里可以按需配置编译选项.

Step2. 编译、安装(install)到本地目录
编译项目,生成库文件后,需要将头文件、库文件拷贝到本地指定目录,方便不同项目使用.

  • 类Unix系统

如果是类Unix系统,可执行命令(需要管理员权限):

make
sudo make install  # Install in /usr/local/ by default
  • Windows系统

方式一:用VS 2022

如果是Windows系统,且已安装Visual Studio(VS),那么可以直接打开上一步生成的gtest.sln文件或者googletest-distribution.sln,然后用VS进行编译.
注意:如果库的安装路径(CMAKE_INSTALL_PREFIX)中C盘,那么需要管理员权限打开VS

打开项目后,会得到如下多个目标的解决方案:

img

到这里,还没有生成库文件(.lib, .dll). 需要右键ALL_BUILD > 生成,为构建生成目标;接着,右键INSTALL > 生成,将头文件、库文件安装到指定目录.

于是,在指定目录可以看到安装好的文件:

img

include/gtest目录头文件:

img

lib目录库文件:

img

注意:我们在VS 2022中,默认设置的Debug + x64模式;如果需要修改,可在VS 2022中修改,然后右键重新生成目标即可.

方式二:用命令行

如果不用VS(需要任意一款CMake支持的C++编译器),直接用命令行,也是可以的. Powershell执行命令:

cmake --install .

注意:

  1. 如果提示"Install cannot find `.../Release/gmock.lib` File exists"(文件未找到)的错误,说明前面以Debug模式构建,而install默认Release模式. 重新以Release模式构建项目即可.

  2. 如果C盘没有安装文件,可能没有以管理员权限运行Powershell.

集成到现有CMake项目

  • 以库和头文件的方式使用GoogleTest

CMake中用find_package查找库文件对应的包,前提是库目录已添加到环境变量PATH中.

find_package(GTest CONFIG REQUIRED)

# or check result after find_package
find_package(GTest)
if (NOT GTest_FOUND)
    message(FATAL_ERROR "GTest not found")
endif()

后面就能使用GTest包.


注意find_package的原理是在搜索路径中搜索PackageNameConfig.cmake文件. 对于GTest包,这个文件名为GTestConfig.cmake. 所以可添加GOOGLETEST_DIR%%\lib\cmake到PATH环境变量.


  • 以源码的方式使用GoogleTest

健壮、灵活

有4种方式:

  1. 将GooglTest源码拷贝到指定位置,然后在用户项目中include该路径即可. 缺点是缺少灵活性,很难持续更新.
  2. 将GooglTest源码作为项目树的一部分. 最简单,但很难持续更新,一些项目可能不允许这样做.
  3. 将GoogleTest作为git submodule添加到项目. git submodule持续更新非常方便,但需要联网从第三方服务器下载,而且不是自动完成,可能导致项目使用者的版本不同. git submodule可参见git submodule 使用.
  4. CMake下载GoogleTest作为构建步骤的一部分. 最简单、灵活的一种方式,但也可能存在不同工具的兼容性问题.

方式1:在Qt 自动生成的googletest项目基础上,修改的CMakeList.txt.

cmake_minimum_required(VERSION 3.14)

project(add LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

enable_testing()
find_package(Threads REQUIRED)

message(STATUS "GOOGLETEST_DIR = $ENV{GOOGLETEST_DIR}")

# use defined instead of testing whether the environment value exists or not directly
if (DEFINED ENV{GOOGLETEST_DIR} AND NOT "$ENV{GOOGLETEST_DIR}" STREQUAL "")
    file(TO_CMAKE_PATH "$ENV{GOOGLETEST_DIR}" GOOGLETEST_DIR) # convert Windows-style path to cmake path
else ()
    if (NOT "" STREQUAL "")
        message(WARNING "Using googletest src dir specified at Qt Creator wizard")
    endif ()
    set(GOOGLETEST_DIR "")
endif ()
if (EXISTS ${GOOGLETEST_DIR})
    # keep same with the actual file path
    set(GTestSrc ${GOOGLETEST_DIR}/googletest)
    set(GMockSrc ${GOOGLETEST_DIR}/googlemock)
elseif (UNIX AND EXISTS /usr/src/gtest)
    set(GTestSrc /usr/src/gtest)
    message(WARNING "Using gtest from system")
    if (EXISTS /usr/src/gmock)
        set(GMockSrc /usr/src/gmock)
    endif ()
else ()
    message( FATAL_ERROR "No googletest src dir found - set GOOGLETEST_DIR to enable!")
endif ()

set(GTestFiles ${GTestSrc}/src/gtest-all.cc)
set(GTestIncludes ${GTestSrc} ${GTestSrc}/include)
if (NOT ${GMockSrc} STREQUAL "")
    list(APPEND GTestFiles ${GMockSrc}/src/gmock-all.cc)
    list(APPEND GTestIncludes ${GMockSrc} ${GMockSrc}/include)
endif ()

include_directories(${GTestIncludes})

add_executable(add main.cpp add_test.cpp
               ${GTestFiles})
add_test(NAME add COMMAND add)
target_link_libraries(add PRIVATE Threads::Threads)

方式2、3:不推荐,不过操作也简单

方式4:推荐的方式,但需要持续联网,而且工具支持

cmake_minimum_required(VERSION 3.14)
...

include(FetchContent)
FetchContent_Declare(
  googletest
  # Specify the commit you depend on and update it regularly.
  URL https://github.com/google/googletest/archive/5376968f6948923e2411081fd9372e71a59d8e77.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

# Now simply link against gtest or gtest_main as needed. Eg
add_executable(hello main.cpp add_test.cpp)
target_link_libraries(hello gtest_main)
add_test(NAME add_test COMMAND hello)

还有其他的写法,添加检查机制,更加灵活、安全,但本质一样.

cmake_minimum_required(VERSION 3.14)
...

if (NOT googletest) # is googletest defined if already built?
    include(FetchContent)
    FetchContent_Declare(
    googletest
        # Specify the commit you depend on and update it regularly.
        URL https://github.com/google/googletest/archive/refs/heads/master.zip
    )
    # For Windows: Prevent overriding the parent project's compiler/linker settings
    set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
    FetchContent_MakeAvailable(googletest)
endif()

注意:必须在FetchContent_Declare命令前添加include(FetchContent),而且要求CMake 3.11以上版本;FetchContent_MakeAvailable命令要求CMake 3.14以上版本


测试环境

添加测试文件add_test.cpp

#include <gtest/gtest.h>
#include <gmock/gmock-matchers.h>

using namespace testing;

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

TEST(Hello, add_test)
{
    EXPECT_EQ(1, 1);
    ASSERT_THAT(0, Eq(0));

    EXPECT_EQ(add(1, 2), 3);
    EXPECT_TRUE(add(4, 5) == 9);
}

自动生成的main.cpp文件

#include <gtest/gtest.h>

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

编译、运行得到结果:

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from Hello
[ RUN      ] Hello.add_test
[       OK ] Hello.add_test (0 ms)
[----------] 1 test from Hello (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

则说明测试用例通过.

本文作者:明明1109

本文链接:https://www.cnblogs.com/fortunely/p/18739847

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   明明1109  阅读(28)  评论(0编辑  收藏  举报
历史上的今天:
2022-02-27 muduo笔记 线程安全相关类MutexLock, MutexLockGuard
2022-02-27 muduo笔记 标记类copyable, noncopyable
2022-02-27 muduo笔记 原子类AtomicIntegerT<T>
2022-02-27 muduo笔记 时间戳类Timestamp
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.