Niedawno sprzedano mi używanie CMake do kompilowania moich projektów C ++ i teraz chciałbym rozpocząć pisanie testów jednostkowych dla mojego kodu. Zdecydowałem się skorzystać z narzędzia Google Test, aby pomóc w tym, ale potrzebuję pomocy w rozpoczęciu.
Przez cały dzień czytałem różne przewodniki i przykłady, w tym Primer , wprowadzenie w IBM i kilka pytań na temat SO ( tu i tutaj ), a także inne źródła, które straciłem z oczu. Zdaję sobie sprawę, że jest tam wiele, ale jakoś nadal mam trudności.
Obecnie próbuję zaimplementować najbardziej podstawowy test, aby potwierdzić, że poprawnie skompilowałem / zainstalowałem gtest i nie działa. Jedyny plik źródłowy (testgtest.cpp) pochodzi prawie dokładnie z tej poprzedniej odpowiedzi:
#include <iostream>
#include "gtest/gtest.h"
TEST(sample_test_case, sample_test)
{
EXPECT_EQ(1, 1);
}
a mój powiązany plik CMakeLists.txt wygląda następująco:
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 zdecydowałem się połączyć z gtest_main zamiast podawać main na końcu pliku cpp, ponieważ uważam, że pozwoli mi to na łatwiejsze skalowanie testów do wielu plików.
Podczas budowania wygenerowanego pliku .sln (w Visual C ++ 2010 Express) otrzymuję niestety 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, jak sądzę, oznacza, że nie łączę się pomyślnie z bibliotekami gtest. Upewniłem się, że podczas łączenia się z bibliotekami debugowania próbowałem następnie budować w trybie debugowania.
EDYTOWAĆ
Po dokładniejszym zagłębieniu się, myślę, że mój problem jest związany z rodzajem biblioteki, w której buduję gtest. Podczas budowania gtest z CMake, jeśli BUILD_SHARED_LIBS
jest odznaczone i łączę swój program z tymi plikami .lib, otrzymuję wymienione powyżej błędy. Jeśli jednak BUILD_SHARED_LIBS
jest zaznaczone, tworzę zestaw plików .lib i .dll. Podczas łączenia z tymi plikami .lib program kompiluje, ale po uruchomieniu narzeka, że nie może znaleźć pliku gtest.dll.
Jakie są różnice między biblioteką a SHARED
i nie SHARED
, a jeśli wybiorę opcję nieudostępnianą, dlaczego to nie działa? Czy brakuje opcji w pliku CMakeLists.txt dla mojego projektu?
źródło
ExternalProject_Add
zamiastadd_subdirectory
. Zobacz tę odpowiedź, aby uzyskać szczegółowe informacje.enable_testing()
?Odpowiedzi:
Rozwiązanie polegało na umieszczeniu katalogu źródłowego gtest jako podkatalogu twojego projektu. Załączam działający plik CMakeLists.txt poniżej, jeśli jest to pomocne dla kogoś.
źródło
pthread
do połączonych bibliotek, zmieniając przedostatnią linię natarget_link_libraries(runUnitTests gtest gtest_main pthread)
make test
aby uruchomić testy, lub uruchomićctest
z katalogu kompilacji. Uruchom,ctest -V
aby zobaczyć wyniki testu Google, a także danectest
wyjściowe.Oto kompletny przykład roboczy, który właśnie przetestowałem. Pobiera się bezpośrednio z sieci, albo ze stałego archiwum, albo z najnowszego katalogu subversion.
źródło
https://github.com/google/googletest/archive/release-1.8.0.zip
GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.8.1
zamiast adresu URLhttps://github.com/google/googletest/archive/release-1.10.0.zip
Możesz uzyskać to, co najlepsze z obu światów. Można użyć
ExternalProject
do pobrania źródła gtest, a następnie użyć go,add_subdirectory()
aby dodać je do kompilacji. Ma to następujące zalety:Używany w normalny sposób, ExternalProject nie wykona pobierania i rozpakowywania w czasie konfiguracji (tj. 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ż uogólnioną implementację, która działa dla każdego zewnętrznego projektu, który używa CMake jako swojego systemu kompilacji, a nie tylko gtest. Znajdziesz je tutaj:
Aktualizacja: to podejście jest teraz również częścią dokumentacji googletest .
źródło
Najprawdopodobniej przyczyną takich błędów jest różnica w opcjach kompilatora między testowym plikiem binarnym a biblioteką Google Test. Dlatego zaleca się wprowadzenie Google Test w formie źródłowej i zbudowanie go razem z testami. W CMake jest to bardzo łatwe. Po prostu wywołujesz
ADD_SUBDIRECTORY
ścieżkę do katalogu głównego gtest, a następnie możesz użyć celów biblioteki publicznej (gtest
igtest_main
) zdefiniowanych tam. Więcej informacji ogólnych znajduje się w tym wątku CMake w grupie googletestframework.[edytuj] Ta
BUILD_SHARED_LIBS
opcja działa na razie tylko w systemie Windows. Określa typ bibliotek, które ma zbudować CMake. Jeśli ustawisz to naON
, CMake utworzy je jako biblioteki DLL, a nie statyczne biblioteki. W takim przypadku musisz zbudować swoje testy z -DGTEST_LINKED_AS_SHARED_LIBRARY = 1 i skopiować pliki DLL utworzone przez CMake do katalogu z testowym plikiem binarnym (CMake domyślnie umieszcza je w oddzielnym katalogu wyjściowym). O ile gtest w bibliotece statycznej nie działa, łatwiej jest nie ustawiać tej opcji.źródło
Dzieje się tak, ponieważ musisz dodać -DGTEST_LINKED_AS_SHARED_LIBRARY = 1 do definicji kompilatora w swoim projekcie, jeśli chcesz używać gtest jako biblioteki współdzielonej.
Możesz także użyć bibliotek statycznych, pod warunkiem, że skompilowałeś je z włączoną opcją gtest_force_shared_crt, aby wyeliminować błędy, które widziałeś.
Biblioteka mi się podoba, ale dodawanie jej do projektu to prawdziwy ból. I nie masz szans zrobić tego dobrze, chyba że zaczniesz kopać (i zhakować) do plików cmake gtest. Wstyd. W szczególności nie podoba mi się pomysł dodania gtest jako źródła. :)
źródło
OP korzysta z systemu Windows, a znacznie łatwiejszym sposobem korzystania z GTest jest dziś użycie vcpkg + cmake.
Zainstaluj vcpkg zgodnie z https://github.com/microsoft/vcpkg i upewnij się, że możesz uruchomić
vcpkg
z wiersza cmd. Zwróć uwagę na folder instalacyjny vcpkg, np.C:\bin\programs\vcpkg
.Zainstaluj gtest używając
vcpkg install gtest
: to pobierze, skompiluje i zainstaluje GTest.Użyj pliku CmakeLists.txt jak poniżej: pamiętaj, że możemy używać celów zamiast włączać foldery.
Uruchom cmake z: (w razie potrzeby edytuj folder vcpkg i upewnij się, że ścieżka do pliku łańcucha narzędzi vcpkg.cmake jest poprawna)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=C:\bin\programs\vcpkg\scripts\buildsystems\vcpkg.cmake
i buduj
cmake --build build
jak zwykle. Zauważ, że vcpkg skopiuje również wymagany plik gtest (d) .dll / gtest (d) _main.dll z folderu instalacyjnego do folderów Debug / Release.Testuj z
cd build & ctest
.źródło
Rozwiązania Twoje i VladLosevsa są prawdopodobnie lepsze niż moje. Jeśli jednak potrzebujesz rozwiązania brutalnego, spróbuj tego:
źródło
Najprostszy plik CMakeLists.txt, który wydestylowałem z odpowiedzi w tym wątku, a kilka prób i błędów to:
Gtest powinien być już zainstalowany w twoim systemie.
źródło
Podobnie jak aktualizacja komentarza @ Patricia w zaakceptowanej odpowiedzi i komentarza @ Fraser do pierwotnego pytania, jeśli masz dostęp do CMake 3.11+, możesz skorzystać z funkcji FetchContent CMake .
Strona FetchContent CMake używa googletest jako przykładu!
Podałem małą modyfikację zaakceptowanej odpowiedzi:
Możesz użyć
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
właściwości target celów gtest i gtest_main, tak jak są one ustawione w skrypcie Google test CMakeLists.txt .źródło
target_include_directories
iFetchContent_MakeAvailable(googletest)
zamiast tego użyć . Spowoduje to zarówno wypełnienie zawartości, jak i dodanie jej do głównej wersji. CMake FetchContent - więcej informacjiPostanowiłem wrzucić coś ogólnego, naprawdę szybko demonstrując inny sposób zrobienia tego niż wcześniej opublikowane odpowiedzi, w nadziei, że może to komuś pomóc. Poniższe działały dla mnie na moim Macu. Najpierw uruchomiłem polecenia konfiguracyjne dla gtests. Właśnie użyłem skryptu, który znalazłem, aby wszystko skonfigurować.
Następnie stworzyłem prostą strukturę folderów i napisałem kilka szybkich zajęć
Stworzyłem plik CMakeLists.txt najwyższego poziomu dla folderu narzędzi i CMakeLists.txt dla folderu testów
To jest CMakeLists.txt w folderze testy
Pozostaje tylko napisać sample gtest i gtest main
sample gtest
próbka gtest main
Następnie mogę skompilować i uruchomić gtesty za pomocą następujących poleceń z folderu utils
źródło