février
2009
Je n’ai jamais réellement fait de test unitaire en C++ voir dans n’importe quel langage du tout et je commence de plus en plus à réutiliser des codes que je fais il y a souvent très longtemps, je les retouche et je rajoute un bug et j’ai à chaque fois du mal à l’identifier (obligé de retester les fonctions une par une, re faire du code de test que j’avais parfois déjà fais, etc.). Bref si vous aussi vous êtes dans ma situation, que vous cherchez une solution pour aller plus vite, vous avez sûrement déjà entendu parlé des tests unitaires et des frameworks disponibles en C++ pour automatiser tout ça. Si ce n’est pas le cas je vous conseille d’aller lire cet article qui propose une comparaison des frameworks les plus connus :
Dan Crevier’s Blog : A comparison of C++ unit testing frameworks (en anglais)
Après l’avoir lu, vous faites comme moi confiance à l’auteur et choisissez la bibliothèque CxxTest et essayez de l’intégrer dans votre application. Si vous aussi vous utilisez CMake comme outil de construction, vous aurez remarqué que l’intégration de CxxTest est plus que sommaire, je vous propose donc une solution plus complète.
Nous allons supposer que vous avez organisé vos fichiers comme suit :
- dossier src : contient toutes les sources ainsi que vos headers ;
- dossier test : va contenir vos tests unitaires ;
- dossier build : contiendra le fichier généré par CxxTest (il est très important que le dossier existe).
Voici maintenant un build minimaliste avec quelques commentaires pour vous expliquer son fonctionnement :
#Configuration du projet
project(mon-projet)
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
# Va permettre de pouvoir trouver Find
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ".")
# Fait la liaison avec la bibliothèque CxxTest
FIND_PACKAGE(CxxTest REQUIRED)
SET(CXXTEST_USE_PYTHON 1)
file(
GLOB_RECURSE
source_files
src/*.cpp
src/*.hpp
)
file(
GLOB_RECURSE
test-files
test/*.hpp
)
# Unit testing
ENABLE_TESTING()
CXXTEST_ADD_TEST(unit-test build/mon-test-unitaire.cpp ${test-files})
add_executable(
test-unit
build/mon-test-unitaire.cpp
)
add_library(
lib-mon-projet STATIC
${source_files}
)
add_executable(mon-projet
src/main.cc
)
include_directories(
"src"
"." #Nécessaire pour CxxTest
${CXXTEST_INCLUDE_DIR}
)
#Configuration de l'édition de liens
target_link_libraries(
test-unit
lib-mon-projet
)
target_link_libraries(
mon-projet
lib-mon-projet
)
Tout d’abord vous aurez besoin du fichier FindCxxTest.cmake que j’ai repiqué d’ici et « amélioré ». Ma version se trouve ici.
Pourquoi l’avoir modifié ? Et bien parce que la version normale suppose que notre programme test n’ait pas besoin de l’ensemble de notre projet pour fonctionner or normalement quand vous faites un test unitaire sur une classe très importante, vous aurez besoin de la définition de presque toutes vos classes. La version normale ne vous permet pas cela.
Comment alors faire pour linker notre test unitaire à notre programme ? La première chose serait de faire un exécutable contenant toutes les sources de notre projet sauf le fichier contenant la fonction main (main.cc) :
test-unit
build/bspline.cpp
${source_files}
)
add_executable(mon-projet
src/main.cc
${source_files}
)
Vous comprenez au passage pourquoi j’ai décidé de prendre l’extension main.cc au lieu de cpp, quand je fais ma liste de sources :
GLOB_RECURSE
source_files
src/*.cpp
src/*.hpp
)
Je prends ainsi automatiquement toutes les sources de mon projet sauf le fichier main.cc…
Le problème avec cette solution est qu’elle va faire compiler tous nos fichiers deux fois (une fois pour test-unit et une autre fois pour mon-projet. Pour éviter cela il suffit de faire une bibliothèque statique temporaire et de la linker aux deux comme proposé dans ma solution ; ainsi les fichiers ne seront compilés qu’une fois.
Et voilà, l’intégration est terminée ! On peut sûrement amélioré tout ceci et je vous encourage à me contacter si vous avez trouvé quelque chose de plus élégant :).
Attention : Bien sûr je suppose que vous avez mis dans les variables d’environnements le dossier d’include de CxxTest et le dossier racine pour trouver les scripts python. Voici comment c’est chez moi :
export CMAKE_INCLUDE_PATH=$CMAKE_INCLUDE_PATH:/home/tanek/Logiciels/cxxtest/cxxtest
Bonjour,
Je suis en train de me battre avec CMake depuis maintenant 2 jours et je n’arrive toujours pas linker CxxTest :
— Could NOT find CxxTest (missing: CXXTEST_INCLUDE_DIR CXXTEST_PYTHON_TESTGEN_EXECUTABLE)
Aurait tu un template fonctionnel de ton architecture?
Merci d’avance