Windows下搭建googletest测试环境 for Qt6
背景
因为需要将CMake构建的项目从VS 2022移植到Qt6,网上找了很多资料,但很少有适用于自己情况的,比如最简单的,通过CMake从网络下载googletest代码到项目,在Qt CMake上无法下载,而在VS 2022上下载、编译完全没有问题. 于是,决定从官网找解决办法.
环境
环境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
注意:
- googletest要求CMake使用3.14以后版本,因为后面用到
FetchContent_MakeAvailable()
命令; - 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编译器):
Configure后,会得到如下结果:
这里可以按需配置编译选项.
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
打开项目后,会得到如下多个目标的解决方案:
到这里,还没有生成库文件(.lib, .dll). 需要右键ALL_BUILD > 生成,为构建生成目标;接着,右键INSTALL > 生成,将头文件、库文件安装到指定目录.
于是,在指定目录可以看到安装好的文件:
include/gtest目录头文件:
lib目录库文件:
注意:我们在VS 2022中,默认设置的Debug + x64模式;如果需要修改,可在VS 2022中修改,然后右键重新生成目标即可.
方式二:用命令行
如果不用VS(需要任意一款CMake支持的C++编译器),直接用命令行,也是可以的. Powershell执行命令:
cmake --install .
注意:
-
如果提示"Install cannot find `.../Release/gmock.lib` File exists"(文件未找到)的错误,说明前面以Debug模式构建,而install默认Release模式. 重新以Release模式构建项目即可.
-
如果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种方式:
- 将GooglTest源码拷贝到指定位置,然后在用户项目中include该路径即可. 缺点是缺少灵活性,很难持续更新.
- 将GooglTest源码作为项目树的一部分. 最简单,但很难持续更新,一些项目可能不允许这样做.
- 将GoogleTest作为git submodule添加到项目. git submodule持续更新非常方便,但需要联网从第三方服务器下载,而且不是自动完成,可能导致项目使用者的版本不同. git submodule可参见git submodule 使用.
- 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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-02-27 muduo笔记 线程安全相关类MutexLock, MutexLockGuard
2022-02-27 muduo笔记 标记类copyable, noncopyable
2022-02-27 muduo笔记 原子类AtomicIntegerT<T>
2022-02-27 muduo笔记 时间戳类Timestamp