Windows搭建gtest学习环境

文章目录

    • 下载源码
    • 合入测试工程
    • 命令行编译
    • Clion编译

参考: https://blog.csdn.net/wdcyf15/article/details/110833055

目标:win11 + mingw + cmake + googletest,用命令行 & clion GUI分别编译成功测试工程,并且运行用例

前置安装mingw & cmake,参考:https://blog.csdn.net/weixin_44927066/article/details/131626415

下载源码

参考中下载的是gtest 1.8版本,但是cmake会报错gtest里的cmake版本太低,我选择2022年中发布的1.12.0版本。github有时登录不上,可以用国内镜像站,我是在这里下载的:https://hub.njuu.cf/google/googletest/releases

Windows搭建gtest学习环境_第1张图片

合入测试工程

下载完毕后新建项目,目录如下,googletest-release-1.12.0就是上一步下载的zip包解压得到的,build则是存cmake中间文件用的,新建一个文件夹就好,初始为空。clion会自己刷新cmake项目,我们首先是用命令行编译,所以可以直接无视clion的报错和cmake中间文件,后面再行配置。

Windows搭建gtest学习环境_第2张图片

文件内容(与参考贴基本一致,我只改了一下cmake的版本,让它跟gtest的cmake版本一致,其实不改也无所谓):

注意:使用clion开发,当你增加一个.cpp / .h文件时,clion会可能提示要不要把这个文件加入CMakelists,这里要选择“不”。我就不小心在gtest_win/CMakeLists.txt里引入了gtest_win/test/test_swap.cpp,报错找不到gtest/gtest.h,定位了半天才发现是这个原因。

# gtest_win/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)  # cmake -G "MinGW Makefiles" ..
project(GTESTWIN)

#set(CMAKE_CXX_STANDARD 17)

# 头文件
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/include")
# 源文件
AUX_SOURCE_DIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/src/src" DIR_SRCS)

add_executable(gtest_win ./src/main.cpp ${DIR_SRCS})

# 增加测试工程
add_subdirectory(./test)
# gtest_win/.gitignore
.idea
build
// gtest_win/src/main.cpp
#include 
#include "include/swap/swap.h"

using namespace std;

int main(int argc, char **argv) {
    int val1 = 10;
    int val2 = 20;
    cout << "before swap: val1=" << val1 << ", val2=" << val2 << endl;

    swap(val1, val2);

    cout << "after swap: val1=" << val1 << ", val2=" << val2 << endl;
    return 0;
}
// gtest_win/src/include/swap/swap.h
#ifndef __SWAP_H_
#define __SWAP_H_

void swap(int &a, int &b);

#endif // !__SWAP_H_
// gtest_win/src/src/swap.cpp
#include "swap/swap.h"

void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
# gtest_win/test/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)  # cmake -G "MinGW Makefiles" ..
project(GTESTWIN_TEST)

# gtest库,使用getst库下的cmakelists
add_subdirectory(./googletest-release-1.12.0)

# gtest/gmock头文件
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/googletest-release-1.12.0/googletest/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/googletest-release-1.12.0/googlemock/include)

# 待测头文件
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../src/include")
# 待测源文件
AUX_SOURCE_DIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/../src/src" DIR_SRCS)
# 测试源文件
AUX_SOURCE_DIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}" TEST_SRCS)

add_executable(gtest_win_test ${DIR_SRCS} ${TEST_SRCS})

# 链接测试库,pthread 库一定要写在 ${GTEST_BOTH_LIBRARIES} 的后面, 否则编译时会报错,
# GTEST_BOTH_LIBRARIES表示链接google test的两个库
target_link_libraries( gtest_win_test
        PRIVATE
        gtest
        gtest_main # 使用gtest带的main函数,如果检测到外部有main函数,则使用外部main函数,外部main函数要配置gtest初始化。
        gmock
        gmock_main  # 使用gmock带的main函数,如果检测到外部有main函数,则使用外部main函数,与gtest_main同时存在则自动配置。
        pthread )
// gtest_win/test/test_swap.cpp
#include 
#include "gtest/gtest.h"
#include "gmock/gmock.h"

#include 
#include 
#include 

#include "swap/swap.h"

using ::testing::_;
using ::testing::Return;
using ::testing::AtLeast;
using ::testing::Exactly;
using namespace testing;
using namespace std;

TEST(SWAP_TEST, SWAP_TWO_INT) {
    int val1 = 10;
    int val2 = 20;
    swap(val1, val2);
    EXPECT_EQ(20, val1);
    EXPECT_EQ(10, val2);
}

命令行编译

原理上有了上面的目录结构和文件内容,在gtest_win文件夹下执行下面的命令即可编译出build/gtest_win.exebuild/test/gtest_win_test.exe两个可执行文件。

cd build
cmake -G "MinGW Makefiles" ..
make

下面记录一下遇到的坑。

1、make报错:error: ‘mutex’ in namespace ‘std’ does not name a type

参考:https://blog.csdn.net/qq_38795209/article/details/97749383; https://zhuanlan.zhihu.com/p/355510947

原因:在mingw构建工具链的“线程模型:win32”中不支持互斥。您必须选择任何具有“线程模型:posix”的工具链。

解决:重新下载x86_64-posix-seh的mingw

2、make报错:undefined reference to `WinMain’

CMakeFiles\gtest_win_test.dir/objects.a(test_swap.cpp.obj):test_swap.cpp:(.rdata$_ZTV27SWAP_TEST_SWAP_TWO_INT_Test[_ZTV27SWAP_TEST_SWAP_TWO_INT_Test]+0x20): undefined reference to `testing::Test::SetUp()'
CMakeFiles\gtest_win_test.dir/objects.a(test_swap.cpp.obj):test_swap.cpp:(.rdata$_ZTV27SWAP_TEST_SWAP_TWO_INT_Test[_ZTV27SWAP_TEST_SWAP_TWO_INT_Test]+0x28): undefined reference to `testing::Test::TearDown()'
CMakeFiles\gtest_win_test.dir/objects.a(test_swap.cpp.obj):test_swap.cpp:(.text$_ZN27SWAP_TEST_SWAP_TWO_INT_TestD1Ev[_ZN27SWAP_TEST_SWAP_TWO_INT_TestD1Ev]+0x22): undefined reference to `testing::Test::~Test()'
CMakeFiles\gtest_win_test.dir/objects.a(test_swap.cpp.obj):test_swap.cpp:(.text$_ZN27SWAP_TEST_SWAP_TWO_INT_TestC1Ev[_ZN27SWAP_TEST_SWAP_TWO_INT_TestC1Ev]+0x14): undefined reference to `testing::Test::Test()'
D:/Program Files/mingw-w64-v8.0.2/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
make[2]: *** [test\CMakeFiles\gtest_win_test.dir\build.make:116: test/gtest_win_test.exe] Error 1
make[1]: *** [CMakeFiles\Makefile2:178: test/CMakeFiles/gtest_win_test.dir/all] Error 2
make: *** [Makefile:135: all] Error 2

查来查去是我大意了,根目录下CMakeLists.txt里target_link_libraries写成了target_link_directories。上文给出的文件中是已经修正过的版本。查了一下,两个命令是有不同的(理解有限,有待深入学习):

  • target_link_libraries:将指定库链接到指定目标。link_libraries用来链接静态库,target_link_libraries用来链接导入库。格式:target_link_libraries( …) target表示被链接的目标,item表示要链接的源,item可以有多于一个。参数:

    • PUBLIC 在public后面的库会被Link到你的target中,并且里面的符号也会被导出,提供给第三方使用。

    • PRIVATE 在private后面的库仅被link到你的target中,并且终结掉,第三方不能感知你调了啥库

    • INTERFACE 在interface后面引入的库不会被链接到你的target中,只会导出符号。

  • target_link_directories:用于指定链接器在链接给定目标时应搜索库所在的路径。比较少用。

顺便记录几个常见的cmake命令:

参考:https://www.jianshu.com/p/8909efe13308; https://blog.csdn.net/qq_26849933/article/details/127139052; https://blog.csdn.net/fengbingchun/article/details/128292359

  • add_subdirectory:添加一个子cmake项目,子cmake项目文件夹内有cmake文件
  • include_directories:添加头文件路径,告诉编译器应该去哪里找头文件。如果提示xxx变量/函数没有声明,就需要检查include_directories是否漏了某些文件夹。此外,include_directories也与源文件中引用头文件的目录长度有关:上面的例子中,gtest_win/CMakeLists.txt中用的是include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/include"),swap.cpp中引用写作#include "swap/swap.h";若gtest_win/CMakeLists.txt里用include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/include/swap"),则swap.cpp里应该写#include "swap.h"
  • aux_source_directory:添加源文件并保存到相应变量,一般会在 add_executable / add_library中引用源文件变量
  • link_libraries:添加库文件路径,告诉编译器应该去哪里找库文件。如果提示xxx变量/函数没有定义,且这个变量/函数是在lib库里定义的,就去找找link_libraries是不是少添加了某些路径。

以下是成功日志:

PS D:\proj\doc\gtest_demo\gtest_win\build> cmake -G "MinGW Makefiles" ..
-- The C compiler identification is GNU 8.1.0
-- The CXX compiler identification is GNU 8.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: D:/Program Files/mingw-w64-v8.0.2/mingw64/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/Program Files/mingw-w64-v8.0.2/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find Python (missing: Python_EXECUTABLE Interpreter) 
-- Configuring done
-- Generating done
-- Build files have been written to: D:/proj/doc/gtest_demo/gtest_win/build
PS D:\proj\doc\gtest_demo\gtest_win\build> 
PS D:\proj\doc\gtest_demo\gtest_win\build>
PS D:\proj\doc\gtest_demo\gtest_win\build> make
[  7%] Building CXX object CMakeFiles/gtest_win.dir/src/main.cpp.obj
[ 14%] Building CXX object CMakeFiles/gtest_win.dir/src/src/swap.cpp.obj
[ 21%] Linking CXX executable gtest_win.exe
[ 21%] Built target gtest_win
[ 28%] Building CXX object test/googletest-release-1.12.0/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj
[ 35%] Linking CXX static library ..\..\..\lib\libgtest.a
[ 35%] Built target gtest
[ 42%] Building CXX object test/googletest-release-1.12.0/googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.obj
[ 50%] Linking CXX static library ..\..\..\lib\libgtest_main.a
[ 50%] Built target gtest_main
[ 57%] Building CXX object test/googletest-release-1.12.0/googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.obj
[ 64%] Linking CXX static library ..\..\..\lib\libgmock.a
[ 64%] Built target gmock
[ 71%] Building CXX object test/googletest-release-1.12.0/googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.obj
[ 78%] Linking CXX static library ..\..\..\lib\libgmock_main.a
[ 78%] Built target gmock_main
[ 85%] Building CXX object test/CMakeFiles/gtest_win_test.dir/__/src/src/swap.cpp.obj
[ 92%] Building CXX object test/CMakeFiles/gtest_win_test.dir/test_swap.cpp.obj
[100%] Linking CXX executable gtest_win_test.exe
[100%] Built target gtest_win_test
PS D:\proj\doc\gtest_demo\gtest_win\build>
PS D:\proj\doc\gtest_demo\gtest_win\build> .\test\gtest_win_test.exe
Running main() from D:\proj\doc\gtest_demo\gtest_win\test\googletest-release-1.12.0\googletest\src\gtest_main.cc
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from SWAP_TEST
[ RUN      ] SWAP_TEST.SWAP_TWO_INT
[       OK ] SWAP_TEST.SWAP_TWO_INT (0 ms)
[----------] 1 test from SWAP_TEST (1 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (5 ms total)
[  PASSED  ] 1 test.
PS D:\proj\doc\gtest_demo\gtest_win\build>

Clion编译

命令行编译把坑基本踩完了,clion也没什么坑了。这是我的设置,跟之前cmake学习里的一致。

Windows搭建gtest学习环境_第3张图片

Windows搭建gtest学习环境_第4张图片

刷新cmake项目之后,会自动蹦出几个编译选项,选这个:

499d6e35660c2b9fd8d04f7a65aa423

编译、运行通过:

f40df1c4cd8b31758aa97ddf1b250cd

cmake编译完了之后就可以跳转了。

你可能感兴趣的:(C语言学习,c++,单元测试)