Jak rozpocząć pracę z GTest i CMake

Ostatnio sprzedano mi CMake do kompilacji moich projektów C++, a teraz chciałbym zacząć pisać kilka testów jednostkowych dla mojego kodu. Zdecydowałem się skorzystać z narzędzia Google Test, aby w tym pomóc, ale potrzebuję pomocy w rozpoczęciu.

Cały dzień czytałem różne Poradniki i przykłady obejmują Primer , wprowadzenie W IBM i kilka pytań na temat SO ( tutaj i tutaj), a także inne źródła, które straciłem. I zdaję sobie sprawę, że jest ich dużo, ale jakoś wciąż mam problemy.

Obecnie próbuję zaimplementować najbardziej podstawowy test, aby potwierdzić, że dobrze skompilowałem / zainstalowałem gtest i nie działa. Jedyny plik źródłowy (testgtest.cpp) pochodzi niemal dokładnie z tej poprzedniej odpowiedzi:

#include <iostream>

#include "gtest/gtest.h"

TEST(sample_test_case, sample_test)
{
    EXPECT_EQ(1, 1);
}

I moich powiązanych Cmakelistów.txt jest następujący:

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
)

Zauważ, że wybrałem link do gtest_main zamiast podawać main na końcu cpp plik, ponieważ wierzę, że pozwoli mi to łatwiej skalować testowanie do wielu plików.

Podczas budowania wygenerowanego .plik sln (w Visual C++ 2010 Express) niestety dostaję długą listę błędów formularza

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)

Co chyba oznacza, że nie linkuję z bibliotekami gtest. Upewniłem się, że podczas łączenia z bibliotekami debugowania próbowałem budować w trybie debugowania.

EDIT

Po dokładnym pokopaniu, ja myślę, że mój problem ma coś wspólnego z typem biblioteki, w której buduję gtest. Podczas budowania gtest z CMake, jeśli BUILD_SHARED_LIBS jest nie zaznaczone, a ja łączę mój program z nimi .pliki lib dostaję błędy wymienione powyżej. Jeśli jednak BUILD_SHARED_LIBS jest zaznaczone, to generuję zbiór .lib i .pliki dll. Kiedy teraz łączy się z nimi .pliki lib program kompiluje, ale po uruchomieniu skarży się, że nie może znaleźć gtest.dll.

Jakie są różnice między SHARED a nie SHARED biblioteką, a jeśli wybierz opcję Nie udostępniane, dlaczego to nie działa? Czy istnieje opcja w Cmakelistach.txt dla mojego projektu, którego mi brakuje?

Author: Vadim Kotov, 2011-12-14

7 answers

Rozwiązanie polegało na umieszczeniu katalogu źródłowego gtest jako podkatalogu twojego projektu. Włączyłem działające Cmakelisty.txt poniżej, jeśli jest to pomocne dla kogokolwiek.

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 )
 58
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-31 11:29:03

Oto kompletny działający przykład, który właśnie przetestowałem. Pobiera bezpośrednio z sieci, albo stały tarball, albo najnowszy katalog 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)
 18
Author: user1427799,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-26 23:25:16

Najprawdopodobniej za takie błędy winna jest różnica w opcjach kompilatora pomiędzy Twoim testowym binarnym a biblioteką Google Test. Dlatego zaleca się wprowadzenie Google Test w formie źródłowej i zbudowanie go wraz z testami. Jest to bardzo łatwe do zrobienia w CMake. Po prostu wywołujesz ADD_SUBDIRECTORY ze ścieżką do katalogu głównego gtest i możesz użyć tam zdefiniowanych celów Biblioteki Publicznej (gtest i gtest_main). Więcej informacji znajdziesz w tym wątku CMake w googletestframework group.

[edytuj] Opcja BUILD_SHARED_LIBS jest na razie skuteczna tylko w systemie Windows. Określa typ bibliotek, które CMake ma zbudować. Jeśli ustawisz ją na ON, CMake zbuduje je jako biblioteki DLL w przeciwieństwie do bibliotek statycznych. W takim przypadku musisz zbudować swoje testy za pomocą-DGTEST_LINKED_AS_SHARED_LIBRARY=1 i skopiować pliki DLL wytworzone przez CMake do katalogu z binarnym testem (CMake domyślnie umieszcza je w oddzielnym katalogu wyjściowym). Chyba że gtest w static lib nie działa dla Ciebie, łatwiej nie ustawić tej opcji.

 13
Author: VladLosev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-16 16:42:33

Możesz dostać to, co najlepsze z obu światów. Możliwe jest użycie ExternalProject, aby pobrać źródło gtest, a następnie użyć add_subdirectory(), aby dodać je do swojej kompilacji. Ma to następujące zalety:

  • gtest jest zbudowany jako część twojej głównej kompilacji, więc używa tych samych flag kompilatora itp. a tym samym unika problemów takich jak te opisane w pytaniu.
  • nie ma potrzeby dodawania źródeł gtest do własnego drzewa źródeł.

Używany w normalny sposób, ExternalProject nie zrobi Pobierz i rozpakuj w czasie konfiguracji (np. gdy CMake jest uruchomiony), ale możesz to zrobić przy odrobinie pracy. Napisałem post na blogu o tym, jak to zrobić, który zawiera również ogólną implementację, która działa dla każdego zewnętrznego projektu, który używa CMake jako swojego systemu budowania, a nie tylko gtest. Można je znaleźć tutaj:

Aktualizacja: to podejście jest teraz również częścią dokumentacji googletest .

 8
Author: Craig Scott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-30 09:44:07

Po dokładniejszym pokopaniu, myślę, że mój problem ma coś wspólnego z typem biblioteki, w której buduję gtest. Podczas budowania gtest z CMake, jeśli BUILD_SHARED_LIBS nie jest zaznaczony, a ja łączę mój program z nimi .pliki lib dostaję błędy wymienione powyżej. Jeśli jednak build_shared_libs jest zaznaczone, to generuję zestaw .lib i .pliki dll. Kiedy teraz łączy się z nimi .pliki lib program kompiluje, ale po uruchomieniu skarży się, że nie może znaleźć gtest.dll.

To dlatego, że musisz dodać -DGTEST_LINKED_AS_SHARED_LIBRARY=1 do definicji kompilatora w Twoim projekcie, jeśli chcesz użyć gtest jako biblioteki współdzielonej.

Możesz również użyć bibliotek statycznych, pod warunkiem, że skompilujesz je z włączoną opcją gtest_force_shared_crt, aby wyeliminować widoczne błędy.

Podoba mi się biblioteka, ale dodanie jej do projektu to prawdziwy ból. I nie masz szans zrobić tego dobrze, chyba że kopiesz (i zhakujesz) pliki gtest cmake. Szkoda. W szczególności nie podoba mi się pomysł dodania gtest jako źródła. :)

 2
Author: Slava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-19 11:28:08

Twoje i VladLosevs' s rozwiązania są prawdopodobnie lepsze niż moje. Jeśli jednak potrzebujesz rozwiązania brute-force, spróbuj tego:

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)
 0
Author: Torleif,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-26 21:32:43

Najprostsze Cmakelisty.txt wyedytowałem z odpowiedzi w tym wątku i jakieś próby i błędy to:

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 powinien być już zainstalowany w Twoim systemie.

 -2
Author: AlexBriskin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-24 19:36:06