Как начать работать с GTest и CMake - PullRequest
106 голосов
/ 14 декабря 2011

Я недавно был продан с использованием 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);
}

и моего связанного 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
)

Обратите внимание, что я выбрал ссылку на gtest_main вместо предоставления main в конце файла cpp, так как считаю, что это позволит мне более легко масштабировать тестирование до нескольких файлов.

При сборке сгенерированногоФайл .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)

, который, по моему мнению, означает, что я не могу успешно связываться с библиотеками gtest.Я убедился, что при связывании с отладочными библиотеками я попытался встроить в режим отладки.

РЕДАКТИРОВАТЬ

Сделав еще несколько копаний, я думаю, что мойПроблема связана с типом библиотеки, в которую я встраиваю gtest.При сборке gtest с CMake, если BUILD_SHARED_LIBS не проверен, и я связываю свою программу с этими .lib-файлами, я получаю ошибки, упомянутые выше.Однако, если установлен флажок BUILD_SHARED_LIBS, я создаю набор файлов .lib и .dll.При связывании этих .lib-файлов программа компилируется, но при запуске жалуется, что не может найти gtest.dll.

В чем различия между SHARED и не SHARED библиотекой, иесли я выбираю не поделился, почему это не работает?Есть ли в CMakeLists.txt вариант для моего проекта, который мне не хватает?

Ответы [ 7 ]

66 голосов
/ 31 января 2014

Решение состояло в том, чтобы поместить исходный каталог 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 )
26 голосов
/ 27 ноября 2014

Вот полный рабочий пример, который я только что протестировал.Он загружает прямо из Интернета, либо фиксированный архив, либо последнюю версию каталога 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)
13 голосов
/ 15 декабря 2011

Скорее всего, в таких ошибках виновата разница в параметрах компилятора между вашим тестовым двоичным файлом и библиотекой Google Test. Вот почему рекомендуется ввести Google Test в исходную форму и собрать его вместе с вашими тестами. Это очень легко сделать в CMake. Вы просто вызываете ADD_SUBDIRECTORY с путем к корню gtest, а затем можете использовать цели публичной библиотеки (gtest и gtest_main), определенные там. В этой ветке CMake содержится дополнительная справочная информация в группе googletestframework.

[править] Параметр BUILD_SHARED_LIBS пока действует только в Windows. Он определяет тип библиотек, которые вы хотите, чтобы CMake собирал. Если вы установите его на ON, CMake будет строить их как DLL, а не как статические библиотеки. В этом случае вы должны собрать свои тесты с -DGTEST_LINKED_AS_SHARED_LIBRARY = 1 и скопировать DLL-файлы, созданные CMake, в каталог с тестовым двоичным файлом (CMake помещает их в отдельный выходной каталог по умолчанию). Если gtest в статической lib не работает для вас, проще не устанавливать эту опцию.

10 голосов
/ 25 июля 2015

Вы можете получить лучшее из обоих миров.Можно использовать ExternalProject для загрузки исходного кода gtest, а затем использовать add_subdirectory(), чтобы добавить его в свою сборку.Это имеет следующие преимущества:

  • gtest построен как часть вашей основной сборки, поэтому он использует те же флаги компилятора и т. Д. И, следовательно, позволяет избежать проблем, подобных тем, которые описаны в вопросе.
  • Нет необходимости добавлять источники gtest в ваше собственное дерево исходников.

При обычном использовании ExternalProject не выполняет загрузку и распаковку во время настройки (т. Е. При запуске CMake.), но вы можете сделать это с помощью небольшой работы.Я написал сообщение в блоге о том, как это сделать, которое также включает обобщенную реализацию, которая работает для любого внешнего проекта, который использует CMake в качестве своей системы сборки, а не только gtest.Вы можете найти их здесь:

Обновление: Этот подход теперь также часть документации googletest .

2 голосов
/ 19 октября 2012

Сделав еще кое-что, я думаю, что моя проблема связана с типом библиотеки, в которую я собираю gtest. При сборке gtest с CMake, если опция BUILD_SHARED_LIBS не проверена, и я связываю свою программу с этими файлами .lib, я получаю ошибки, упомянутые выше. Однако, если установлен флажок BUILD_SHARED_LIBS, я создаю набор файлов .lib и .dll. При связывании этих .lib-файлов программа компилируется, но при запуске жалуется, что не может найти gtest.dll.

Это потому, что вы должны добавить -DGTEST_LINKED_AS_SHARED_LIBRARY = 1 к определениям компилятора в вашем проекте, если вы хотите использовать gtest в качестве разделяемой библиотеки.

Вы также можете использовать статические библиотеки при условии, что вы скомпилировали их с опцией gtest_force_shared_crt, чтобы устранить ошибки, которые вы видели.

Мне нравится библиотека, но добавить ее в проект - настоящая боль. И у вас нет шансов сделать это правильно, если вы не покопаетесь (и не взломаете) файлы gtest cmake. Позор. В частности, мне не нравится идея добавления gtest в качестве источника. :)

0 голосов
/ 24 января 2016

Простейший файл CMakeLists.txt, который я извлек из ответов в этой теме, и некоторые методы проб и ошибок:

project(test CXX C)
cmake_minimum_required(VERSION 2.6.2)

#include folder contains current project's header filed
include_directories("include")

#test folder contains test files
set (PROJECT_SOURCE_DIR test) 
add_executable(hex2base64 ${PROJECT_SOURCE_DIR}/hex2base64.cpp)

# Link test executable against gtest nothing else required
target_link_libraries(hex2base64 gtest pthread)

Gtest уже должен быть установлен в вашей системе.

0 голосов
/ 27 февраля 2012

Ваши и решения Владла Лосева, вероятно, лучше, чем мои. Однако если вы хотите использовать метод грубой силы, попробуйте следующее:

SET(CMAKE_EXE_LINKER_FLAGS /NODEFAULTLIB:\"msvcprtd.lib;MSVCRTD.lib\")

FOREACH(flag_var
    CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
    CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
    if(${flag_var} MATCHES "/MD")
        string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
    endif(${flag_var} MATCHES "/MD")
ENDFOREACH(flag_var)
...