Recientemente me han vendido el uso de CMake para compilar mis proyectos de C ++, y ahora me gustaría comenzar a escribir algunas pruebas unitarias para mi código. Decidí usar la utilidad Google Test para ayudar con esto, pero necesito ayuda para comenzar.
Todo el día he estado leyendo varias guías y ejemplos que incluyen el Manual , una introducción en IBM y algunas preguntas sobre SO ( aquí y aquí ), así como otras fuentes de las que he perdido la noción. Me doy cuenta de que hay mucho por ahí, pero de alguna manera todavía tengo dificultades.
Actualmente estoy tratando de implementar la prueba más básica, para confirmar que he compilado / instalado gtest correctamente y no funciona. El único archivo fuente (testgtest.cpp) se toma casi exactamente de esta respuesta anterior:
#include <iostream>
#include "gtest/gtest.h"
TEST(sample_test_case, sample_test)
{
EXPECT_EQ(1, 1);
}
y mi CMakeLists.txt asociado es el siguiente:
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
)
Tenga en cuenta que he elegido vincular contra gtest_main en lugar de proporcionar el principal al final del archivo cpp, ya que creo que esto me permitirá escalar las pruebas más fácilmente a varios archivos.
Cuando construyo el archivo .sln generado (en Visual C ++ 2010 Express) desafortunadamente obtengo una larga lista de errores del formulario
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)
lo que creo que significa que no estoy enlazando con éxito a las bibliotecas gtest. Me he asegurado de que al vincular contra las bibliotecas de depuración, he intentado compilar en modo de depuración.
EDITAR
Después de investigar un poco más, creo que mi problema tiene algo que ver con el tipo de biblioteca en la que estoy construyendo gtest. Cuando construyo gtest con CMake, si no BUILD_SHARED_LIBS
está marcado, y vinculo mi programa con estos archivos .lib, recibo los errores mencionados anteriormente. Sin embargo, si BUILD_SHARED_LIBS
está marcado, entonces produzco un conjunto de archivos .lib y .dll. Cuando ahora se vincula con estos archivos .lib, el programa compila, pero cuando se ejecuta se queja de que no puede encontrar gtest.dll.
¿Cuáles son las diferencias entre una SHARED
y una SHARED
biblioteca no , y si elijo no compartido, ¿por qué no funciona? ¿Hay una opción en CMakeLists.txt para mi proyecto que me falta?
fuente
ExternalProject_Add
lugar de hacerloadd_subdirectory
. Vea esta respuesta para más detalles.enable_testing()
hacer?Respuestas:
La solución consistía en colocar el directorio fuente de gtest como un subdirectorio de su proyecto. He incluido el CMakeLists.txt de trabajo a continuación si es útil para alguien.
fuente
pthread
a las bibliotecas vinculadas, cambiando la segunda última línea atarget_link_libraries(runUnitTests gtest gtest_main pthread)
make test
para ejecutar las pruebas, o ejecutarctest
desde el directorio de compilación. Ejecutectest -V
para ver la salida de prueba de google, así como lactest
salida.Aquí hay un ejemplo de trabajo completo que acabo de probar. Se descarga directamente desde la web, ya sea un tarball fijo o el último directorio de subversión.
fuente
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
lugar de URLhttps://github.com/google/googletest/archive/release-1.10.0.zip
Puedes obtener lo mejor de ambos mundos. Es posible usarlo
ExternalProject
para descargar la fuente gtest y luego usarloadd_subdirectory()
para agregarlo a su compilación. Esto tiene las siguientes ventajas:Utilizado de la manera normal, ExternalProject no realizará la descarga y el desempaquetado en el momento de la configuración (es decir, cuando se ejecuta CMake), pero puede hacerlo con solo un poco de trabajo. He escrito una publicación de blog sobre cómo hacer esto, que también incluye una implementación generalizada que funciona para cualquier proyecto externo que use CMake como su sistema de compilación, no solo gtest. Usted puede encontrarlos aquí:
Actualización: este enfoque ahora también forma parte de la documentación de googletest .
fuente
Lo más probable es que la diferencia en las opciones del compilador entre el binario de prueba y la biblioteca de Google Test sea la culpa de dichos errores. Es por eso que se recomienda traer Google Test en el formulario fuente y compilarlo junto con sus pruebas. Es muy fácil de hacer en CMake. Simplemente invoque
ADD_SUBDIRECTORY
con la ruta a la raíz gtest y luego puede usar los objetivos de la biblioteca pública (gtest
ygtest_main
) definidos allí. Hay más información de fondo en este hilo de CMake en el grupo googletestframework.[editar] La
BUILD_SHARED_LIBS
opción solo es efectiva en Windows por ahora. Especifica el tipo de bibliotecas que desea que CMake construya. Si lo configuraON
, CMake los compilará como archivos DLL en lugar de bibliotecas estáticas. En ese caso, debe crear sus pruebas con -DGTEST_LINKED_AS_SHARED_LIBRARY = 1 y copiar los archivos DLL producidos por CMake en el directorio con su binario de prueba (CMake los coloca en un directorio de salida separado de forma predeterminada). A menos que gtest en lib estática no funcione para usted, es más fácil no configurar esa opción.fuente
Esto se debe a que debe agregar -DGTEST_LINKED_AS_SHARED_LIBRARY = 1 a las definiciones del compilador en su proyecto si desea utilizar gtest como biblioteca compartida.
También puede usar las bibliotecas estáticas, siempre que la haya compilado con la opción gtest_force_shared_crt para eliminar los errores que haya visto.
Me gusta la biblioteca, pero agregarla al proyecto es un verdadero dolor. Y no tiene la oportunidad de hacerlo correctamente a menos que profundice (y piratee) en los archivos cmake de gtest. Vergüenza. En particular, no me gusta la idea de agregar gtest como fuente. :)
fuente
El OP está usando Windows, y una forma mucho más fácil de usar GTest hoy es con vcpkg + cmake.
Instale vcpkg según https://github.com/microsoft/vcpkg , y asegúrese de que puede ejecutar
vcpkg
desde la línea cmd. Tome nota de la carpeta de instalación de vcpkg, por ejemplo.C:\bin\programs\vcpkg
.Instale gtest usando
vcpkg install gtest
: esto descargará, compilará e instalará GTest.Use CmakeLists.txt como se muestra a continuación: tenga en cuenta que podemos usar objetivos en lugar de incluir carpetas.
Ejecute cmake con: (edite la carpeta vcpkg si es necesario y asegúrese de que la ruta al archivo vcpkg.cmake toolchain sea correcta)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=C:\bin\programs\vcpkg\scripts\buildsystems\vcpkg.cmake
y construir usando
cmake --build build
como de costumbre. Tenga en cuenta que, vcpkg también copiará el gtest (d) .dll / gtest (d) _main.dll requerido de la carpeta de instalación a las carpetas Debug / Release.Prueba con
cd build & ctest
.fuente
Las soluciones suyas y de VladLosevs son probablemente mejores que las mías. Sin embargo, si desea una solución de fuerza bruta, intente esto:
fuente
El CMakeLists.txt más simple que extraje de las respuestas en este hilo y algunas pruebas y errores son:
Gtest ya debería estar instalado en su sistema.
fuente
Del mismo modo que una actualización del comentario de @ Patricia en la respuesta aceptada y el comentario de @ Fraser para la pregunta original, si tiene acceso a CMake 3.11+, puede utilizar la función FetchContent de CMake .
¡La página FetchContent de CMake utiliza googletest como ejemplo!
He proporcionado una pequeña modificación de la respuesta aceptada:
Puede utilizar la
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
propiedad de destino de los objetivos gtest y gtest_main tal como se establecen en la prueba de google CMakeLists.txt script de .fuente
target_include_directories
y usarFetchContent_MakeAvailable(googletest)
en su lugar. Esto completará el contenido y lo agregará a la compilación principal. CMake FetchContent - más informaciónDecidí lanzar algo genérico juntos rápidamente demostrando una forma diferente de hacerlo que las respuestas publicadas anteriormente, con la esperanza de que pueda ayudar a alguien. Lo siguiente funcionó para mí en mi mac. En primer lugar, ejecuté los comandos de configuración para gtests. Acabo de usar un script que encontré para configurar todo.
Luego, hice una estructura de carpetas simple y escribí algunas clases rápidas
Hice un CMakeLists.txt de nivel superior para la carpeta de utilidades, y un CMakeLists.txt para la carpeta de pruebas
Este es el CMakeLists.txt en la carpeta de pruebas
Entonces todo lo que queda es escribir una muestra gtest y gtest main
muestra gtest
muestra gtest principal
Luego puedo compilar y ejecutar gtests con los siguientes comandos desde la carpeta utils
fuente