如何开始使用GTest和CMake

Chr*_*ris 113 unit-testing cmake googletest

我最近因使用CMake编译我的C++项目而被出售,现在我想开始为我的代码编写一些单元测试.我决定使用Google Test实用程序来帮助解决这个问题,但在入门时需要一些帮助.

我一整天都在阅读各种指南和示例,包括Primer,IBM介绍以及有关SO(此处此处)的一些问题以及我已经忘记的其他来源.我意识到那里有很多,但不知怎的,我仍然遇到困难.

我目前正在尝试实施最基本的测试,以确认我已经编译/安装了gtest,并且它无法正常工作.唯一的源文件(testgtest.cpp)被认为几乎完全由前面的回答:

#include <iostream>

#include "gtest/gtest.h"

TEST(sample_test_case, sample_test)
{
    EXPECT_EQ(1, 1);
}
Run Code Online (Sandbox Code Playgroud)

和我关联的CMakeLists.txt如下:

cmake_minimum_required(VERSION 2.6)
project(basic_test)

# Setup testing
enable_testing()
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIR})

# Add test cpp file
add_executable(runUnitTests
    testgtest.cpp
)

# Link test executable against gtest & gtest_main
target_link_libraries(runUnitTests ${GTEST_LIBRARY_DEBUG} ${GTEST_MAIN_LIBRARY_DEBUG})

add_test(
    NAME runUnitTests
    COMMAND runUnitTests
)
Run Code Online (Sandbox Code Playgroud)

请注意,我选择链接gtest_main而不是在cpp文件的末尾提供main,因为我相信这将允许我更容易地将测试扩展到多个文件.

构建生成的.sln文件(在Visual C++ 2010 Express中)时,我很遗憾地得到了一个很长的表单错误列表

2>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: virtual __thiscall std::basic_iostream<char,struct std::char_traits<char> >::~basic_iostream<char,struct std::char_traits<char> >(void)" (??1?$basic_iostream@DU?$char_traits@D@std@@@std@@UAE@XZ) already defined in gtestd.lib(gtest-all.obj)
Run Code Online (Sandbox Code Playgroud)

我认为这意味着我没有成功链接到gtest库.我确保在链接调试库时,我已经尝试在调试模式下构建.

编辑

做了一些挖掘之后,我认为我的问题与我正在构建gtest的库的类型有关.使用CMake构建gtest时,如果BUILD_SHARED_LIBS未经检查,并且我将程序与这些.lib文件链接,则会出现上述错误.但是,如果BUILD_SHARED_LIBS选中,则生成一组.lib和.dll文件.当现在链接这些.lib文件时程序编译,但运行时抱怨它找不到gtest.dll.

a SHARED和非SHARED库之间有什么区别,如果我选择不共享,为什么它不起作用?CMakeLists.txt中是否有我错过的项目选项?

Chr*_*ris 70

解决方案涉及将gtest源目录作为项目的子目录.如果它对任何人都有帮助,我已经在下面包含了工作的CMakeLists.txt.

cmake_minimum_required(VERSION 2.6)
project(basic_test)

################################
# GTest
################################
ADD_SUBDIRECTORY (gtest-1.6.0)
enable_testing()
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})

################################
# Unit Tests
################################
# Add test cpp file
add_executable( runUnitTests testgtest.cpp )
# Link test executable against gtest & gtest_main
target_link_libraries(runUnitTests gtest gtest_main)
add_test( runUnitTests runUnitTests )
Run Code Online (Sandbox Code Playgroud)

  • 不要打败死马,但我认为这值得一提.Fraser上面的评论提出了一个非常重要的观点:"你可以通过使用ExternalProject_Add而不是add_subdirectory来避免包含你自己的GTest源代码." 有关详细信息,请参阅Fraser的回答和评论:http://stackoverflow.com/a/9695234/1735836 (4认同)
  • 我不确定 add_test() 的作用,但它似乎并没有导致测试二进制文件运行......我错过了什么吗? (3认同)
  • @weberc2你必须运行`make test`来运行测试,或者从build目录运行`ctest`.运行`ctest -V`以查看google测试输出以及`ctest`输出. (3认同)
  • 就我而言,我还需要将 `pthread` 添加到链接库中,将倒数第二行更改为 `target_link_libraries(runUnitTests gtest gtest_main pthread)` (2认同)

小智 31

这是我刚刚测试过的一个完整的工作示例.它直接从Web下载,可以是固定的tarball,也可以是最新的subversion目录.

cmake_minimum_required (VERSION 3.1)

project (registerer)

##################################
# Download and install GoogleTest

include(ExternalProject)
ExternalProject_Add(gtest
  URL https://googletest.googlecode.com/files/gtest-1.7.0.zip
  # Comment above line, and uncomment line below to use subversion.
  # SVN_REPOSITORY http://googletest.googlecode.com/svn/trunk/ 
  # Uncomment line below to freeze a revision (here the one for 1.7.0)
  # SVN_REVISION -r700

  PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest
  INSTALL_COMMAND ""
)
ExternalProject_Get_Property(gtest source_dir binary_dir)

################
# Define a test
add_executable(registerer_test registerer_test.cc)

######################################
# Configure the test to use GoogleTest
#
# If used often, could be made a macro.

add_dependencies(registerer_test gtest)
include_directories(${source_dir}/include)
target_link_libraries(registerer_test ${binary_dir}/libgtest.a)
target_link_libraries(registerer_test ${binary_dir}/libgtest_main.a)

##################################
# Just make the test runnable with
#   $ make test

enable_testing()
add_test(NAME    registerer_test 
         COMMAND registerer_test)
Run Code Online (Sandbox Code Playgroud)

  • 我不知道为什么你为此投降了.您的解决方案可以防止有人将Google Test签入版本控制.感谢您的解决方案. (7认同)
  • 您使用的URL现在已损坏.最新的URL是"https:// github.com/google/googletest/archive/release-1.8.0.zip" (3认同)
  • 很好的答案!我们也可以使用 ```GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.8.1``` 代替 URL (3认同)

Vla*_*sev 13

最有可能的是,测试二进制文件和Google测试库之间编译器选项的差异应该归咎于此类错误.这就是为什么建议在源代码表单中引入Google Test并将其与测试一起构建.在CMake中很容易做到.您只需ADD_SUBDIRECTORY使用gtest根路径调用 ,然后就可以使用在那里定义的公共库目标(gtestgtest_main).googletest框架组中的此CMake线程中有更多背景信息.

[edit]该BUILD_SHARED_LIBS选项目前仅在Windows上有效.它指定了您希望CMake构建的库的类型.如果将其设置为ON,则CMake会将它们构建为DLL而不是静态库.在这种情况下,您必须使用-DGTEST_LINKED_AS_SHARED_LIBRARY = 1构建测试,并将CMake生成的DLL文件复制到包含测试二进制文件的目录中(默认情况下,CMake将它们放在单独的输出目录中).除非静态库中的gtest不适合您,否则更容易不设置该选项.

  • 虽然注意`ADD_DIRECTORY`应该是`ADD_SUBDIRECTORY` (2认同)

Cra*_*ott 12

你可以充分利用这两个世界.可以使用ExternalProject下载gtest源,然后使用add_subdirectory()它将其添加到您的构建中.这具有以下优点:

  • gtest是作为主构建的一部分构建的,因此它使用相同的编译器标志等,因此避免了问题中描述的问题.
  • 无需将gtest源添加到您自己的源代码树中.

以正常方式使用,ExternalProject将不会在配置时进行下载和解包(即运行CMake时),但是只需要一点点工作就可以实现.我写过一篇关于如何做到这一点的博客文章,其中还包括一个通用实现,适用于任何使用CMake作为构建系统的外部项目,而不仅仅是gtest.你可以在这里找到它们:

更新:此方法现在也是googletest文档的一部分.

  • IMO,这可能是使用 CMake 项目实施 Google 测试的最简洁方法。希望版主多注意回答的内容和质量。 (3认同)