Utilisation de GoogleTest pour les tests unitaires d'une application C++
Table des matières
- 1. Introduction
- 2. Exemple d'un fichier de test GoogleTest
- 3. Installation de GoogleTest
- 4. Utilisation de GoogleTest dans Visual Studio
1 Introduction
GoogleTest est une bibliothèque de tests unitaires qui facilite leur écriture et leur passage. Si sa prise en main peut sembler une perte de temps au démarrage d'un projet, son utilisation permet ensuite d'améliorer la qualité des développements en permettant la remontée de bugs au plus tôt, voire le TDD (Test-Driven Development), technique de développement dans laquelle le développeur commence par écrire les tests, puis écrit son code.
Il existe de nombreuses bibliothèques de tests unitaires :
- En C++, Catch, Boost.Test, etc.
- En C, cmocka, cUnit, etc.
Dans le cadre de ce cours C++, nous vous proposons d'utiliser GoogleTest car il est de très bonne facture, a une communauté d'utilisateurs nombreuse, et offre une bonne intégration avec Visual Studio et Xcode.
Cette page est une introduction à GoogleTest et à son utilisation dans Visual Studio.
2 Exemple d'un fichier de test GoogleTest
Supposons que vous souhaitiez tester deux fonctions que vous avez écrites : une fonction qui calcule la factorielle d'un nombre et une fonction qui détermine si un nombre est un carré parfait ou non. Voici un exemple de test unitaire écrit avec GoogleTest :
#include "gtest/gtest.h" #include "declarationsDeVosFonctions.h" TEST(Exemple1, Factorielle) { EXPECT_EQ(1, factorielle(-1)); EXPECT_EQ(1, factorielle(0)); EXPECT_EQ(6, factorielle(3)); } TEST(Exemple1, CarreParfait) { EXPECT_FALSE(estUnCarreParfait(-2)); EXPECT_TRUE(estUnCarreParfait(0)); EXPECT_TRUE(estUnCarreParfait(4)); EXPECT_FALSE(estUnCarreParfait(8)); }
Pour de plus amples informations sur les primitives offertes par GoogleTest pour vos tests, lire la section Assertions de https://github.com/google/googletest/blob/master/googletest/docs/Primer.md
3 Installation de GoogleTest
3.1 Installation de GoogleTest proprement dite
- Téléchargez l'archive des sources GoogleTest
- En https://github.com/google/googletest, cliquez sur le bouton
clone or download
. - Une fenêtre s'ouvre : Cliquez sur
Download ZIP
- En https://github.com/google/googletest, cliquez sur le bouton
- Extrayez le contenu de cet archive si possible dans un répertoire
dont le chemin ne contient pas d'espace. dans la suite, nous
supposerons que vous avez extrait le contenu dans le répertoire
C:\Software
- Installation au sein de Visual Studio 2017
- Démarrez Visual Studio.
Fichier
/Nouveau
/Projet...
: une fenêtre s'ouvre.- Choisissez
Projet Win32
, indiquezGoogleTestAvecMain
au niveau du champ Nom :, vérifiez que le champ Solution : (en bas à gauche) a la valeur "Créer une nouvelle édition", et cliquez surOK
. - Une fenêtre d'assistant apparaît : cliquez sur
Suivant>
- Cochez la case Projet vide, sélectionnez Bibliothèque statique, décochez En-tête précompilé, et cliquez sur Terminer.
- Avec l'explorateur de solutions
- Si jamais, ils sont présents, supprimez (définitivement) les
fichiers
stdafx.h
,targetver.h
etstdafx.cpp
- Clic-droit sur "Fichiers sources, puis Ajouter / Elément
existant… . Une fenêtre s'ouvre : sélectionnez le fichier
C:\Software\googletest-master\googletest\src\gtest-all.cc
, puis OK - Même manipulation pour le fichier
C:\Software\googletest-master\googletest\src\gtest-main.cc
, - Clic droit sur
GoogleTestAvecMain
, Propriétés. - Une fenêtre s'ouvre. Dans la colonne de gauche, sélectionnez
C/C++
. - Dans le champ Autres répertoires Include, mettez
C:\Software\googletest-master\googletest;C:\Software\googletest-master\googletest\include
Cliquez sur OK - Menu Générer / Générer la solution : la génération doit se terminer avec succès.
- Votre bibliothèque est prête.
- Si jamais, ils sont présents, supprimez (définitivement) les
fichiers
- Installation au sein d'un autre IDE
- Lisez le fichier
C:\Software\googletest-master\googletest\README.md
- Lisez le fichier
3.2 Installation de GoogleTestAdapter, le plugin Visual Studio 2017 pour Google Test
- Fermez Visual Studio
- Avec un navigateur Web, allez à la page https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter
- Cliquez sur
Download
- Le navigateur affiche une fenêtre proposant d'ouvrir le fichier
GoogleTestAdapter-0.10.1.vsix
avecMicrosoft Visual Studio Version Selector
: cliquez surOK
- Une fois l'installation terminée, démarrez Visual Studio.
- Vous pouvez vérifier que l'installation de l'extension est faite
en allant dans le menu
Outils / Extensions et mise à jour...
: un fenêtre s'ouvre et affiche, notamment l'extensionGoogle Test Adapter
3.3 Installation de GoogleTestAdapter, le plugin Xcode pour Google Test
Le projet https://github.com/mattstevens/xcode-googletest propose deux
méthodes pour intégrer Google Test à Xcode. Voir le fichier
README.md
de ce projet pour voir la démarche à suivre.
4 Utilisation de GoogleTest dans Visual Studio
4.1 Cas d'une solution Visual Studio contenant un projet Win32 (par exemple, une bibliothèque)
4.1.1 Ouverture de votre solution dans Visual Studio
Dans Visual Studio, ouvrez la solution correspondant à votre
projet. Dans la suite, nous supposons que votre solution s'appelle
MaBibliotheque~
.
Par exemple (SVP, déroulez cet exemple si vous n'avez pas de solution contenant une biobliothèque) :
- Menu
Fichier
/Nouveau
/Projet...
: une fenêtre s'ouvre. - Choisissez
Projet Win32
, indiquezMaBibliotheque
au niveau du champ Nom :, vérifiez que le champ Solution : (en bas à gauche) a la valeur "Créer une nouvelle édition", et cliquez surOK
. - Une fenêtre d'assistant apparaît : cliquez sur
Suivant>
- Cochez la case Projet vide, sélectionnez Bibliothèque statique, décochez En-tête précompilé, et cliquez sur Terminer.
- Avec l'explorateur de solutions
- Si jamais, ils sont présents, supprimez (définitivement) les
fichiers
stdafx.h
,targetver.h
etstdafx.cpp
- Clic-droit sur "Fichiers sources, puis Ajouter / Nouvel
élément… . Une fenêtre s'ouvre : choisissez Fichier C++,
donnez le nom
mesFonctionsMathematiques.cpp
, et cliquez sur OK. Dans ce fichier source, écrire :
- Si jamais, ils sont présents, supprimez (définitivement) les
fichiers
#include "mesFonctionsMathematiques.h" // NB : Ces deux fonctions contiennent volontairement des erreurs. // Si vous ne les voyez pas, GoogleTest vous aidera à les voir. int factorielle(int const n) { int fact = 1; for (int i = 2; i < n; ++i) fact *= i; return fact; } bool estUnCarreParfait(int const n) { int i; for (i = 1; i*i < n; ++i); return (i*i == n); }
- Même manipulation en cliquant droit sur Fichiers sources pour
créer
mesFonctionsMathematiques.h
avec le contenu :
#pragma once int factorielle(int const n); bool estUnCarreParfait(int const n);
- Menu Générer / Générer la solution : la génération doit se terminer avec succès.
- Votre bibliothèque est prête.
4.1.2 Ajout du projet GoogleTestAvecMain
(créé précédemment) à votre solution
- Menu Fichier / Ajouter> / Projet existant…
- Naviguez pour sélectionner le fichier
GoogleTestAvecMain.vcxproj
, puis OK.
4.1.3 Création d'un projet de tests unitaires
- Menu Fichier / Nouveau / Projet
- Choisissez Application Console Win32, mettez
UnitTests
au niveau du champ Nom :, sélectionnez Ajouter à la solution au niveau du champ Solution :, cliquez sur OK. Très important : le nom de votre projet doit se terminer par "Test" ou Tests" (sinon, par la suite, le gestionnaire de tests ne pourra pas trouver vos tests ; cf. explications) - Une fenêtre d'assistant s'ouvre : cliquez sur Suivant>
- Une fenêtre "paramètres de l'application" s'ouvre. Décochez En-tête précompilé", cochez /Projet vide, cliquez sur Terminer.
- Dans l'explorateur de solutions, clic droit sur fichiers sources
du projet TestsUnitaires, Ajouter, Nouvel élément…, Fichier
C++ (en lui donnant le nom que vous souhaitez, par exemple
testsUnitaires.cpp
) et cliquez sur Ajouter - Tapez vos tests dans ce fichier. Dans notre exemple (Notez le chemin
dans le #include~ de
mesFonctionsMathematiques.h
):
#include "gtest/gtest.h" #include "../MaBibliotheque/mesFonctionsMathematiques.h" TEST(Exemple1, Factorielle) { EXPECT_EQ(1, factorielle(-1)); EXPECT_EQ(1, factorielle(0)); EXPECT_EQ(6, factorielle(3)); } TEST(Exemple1, CarreParfait) { EXPECT_FALSE(estUnCarreParfait(-2)); EXPECT_TRUE(estUnCarreParfait(0)); EXPECT_TRUE(estUnCarreParfait(4)); EXPECT_FALSE(estUnCarreParfait(8)); }
- Votre projet de tests unitaires a besoin d'accéder aux fichiers
d'include de GoogleTest. Donc, clic droit sur
UnitTest
, Propriétés.- Une fenêtre s'ouvre. Dans la colonne de gauche, sélectionnez
C/C++
. - Dans le champ Autres répertoires Include, mettez
C:\Software\googletest-master\googletest\include
Cliquez sur OK
- Une fenêtre s'ouvre. Dans la colonne de gauche, sélectionnez
- Votre projet de tests unitaires a besoin des références aux 2
autres bibliothèques de cette solution pour que l'édition de liens
se fasse :
- Dans l'explorateur de solutions, clic gauche sur projet
UnitTests
. Puis, menu Projet / Ajouter une référence…. - Cochez
GoogleTestAvecMain
etMaBibliotheque
. Cliquez sur OK.
- Dans l'explorateur de solutions, clic gauche sur projet
- Générez la solution : menu Générer / Générer la solution
4.1.4 Exécution des tests
Définissez
UnitTest
comme projet de démarrage : dans l'explorateur de solutions, clic droit surUnitTests
, puis clic gauche sur Définir comme projet de démarrage. NB : si vous oubliez cette étape, Visual Studio affichera une fenêtre pour signaler qu'il ne peut pas démarrer le programmeMaBibliotheque.lib
(cf. Figure 1).Figure 1 : Fenêtre "Impossible de démarrer le programme MaBibliotheque.lib"
Exécutez vos tests avec Menu Déboguer / Exécuter sans débogage. Une fenêtre console affiche le résultat du test (cf. Figure 2) :
Figure 2 : Sortie console de GoogleTest
Dit autrement, à la ligne 8 de testsUnitaires.cpp, factorielle(3)
renvoie 2 à l'exécution, alors que GoogleTest s'attendait à 6 (grâce à
l'instruction EXPECT_EQ(6, factorielle(3));
). Et, à la ligne 14,
estUnCarreParfait(0)
renvoie false
au lieu de true
(cf. instruction
EXPECT_TRUE(estUnCarreParfait(0));
)
4.1.5 Exécution des tests avec Google Test Adapter
L'interface textuelle précédente ne permet pas de repérer rapidement les tests qui posent problème. Google Test Adapter et l'environnement de tests de Visual Studio facilitent la tâche :
- Menu Test / Fenêtres> / Explorateur de tests : l'explorateur de tests s'ouvre sur la gauche de votre écran.
Il "mouline" pendant plusieurs secondes (cf. bande verte tournante dans le haut de l'explorateur de tests, voir Figure 3) pour déterminer la liste de vos tests. NB : cette étape prend du temps, mais n'est à réaliser qu'une seule fois.
Figure 3 : Explorateur de tests en train de mouliner (cf. bande verte tournante)
- Dans l'explorateur de tests, cliquez sur Exécuter tout. Pendant quelques instants, cet explorateur indique, dans son bandeau haut, que Visual Studio mouline. Puis, il affiche le résultat des tests.
Clic gauche sur un test en erreur, agrandissez la fenêtre du bas de l'explorateur de tests pour voir le détail du problème et accéder, en cliquant sur la ligne qui vous intéresse dans la StackTrace en bas à gauche de l'explorateur de tests, à la ligne concernée dans le fichier des tests (cf. Figure 4, notez que, dans l'affichage de
testsUnitaires.cpp
, le curseur est au niveau de la ligne 14, car on a cliqué surtestsUnitaires.cpp:14
en bas de l'explorateur de tests).Figure 4 : Affichage des informations d'un test en échec
- Corrigez votre source (NB : il peut arriver aussi que votre test
soit faux, mais c'est beaucoup plus rare !), puis relancez vos tests
en cliquant, dans l'explorateur de tests, sur Exécuter tout ou
Exécuter… v / Exécuter les tests échoués. Dans notre exemple,
modifiez
mesFonctionsMathematiques.c
de la manière suivante pour obtenir des tests réussis (cf. Figure 5) :
#include "mesFonctionsMathematiques.h" // Version corrigée int factorielle(int const n) { int fact = 1; for (int i = 2; i <= n; ++i) // Correction : "<=" au lieu de "<" fact *= i; return fact; } bool estUnCarreParfait(int const n) { int i; for (i = 0; i*i < n; ++i); // Correction : "i = 0" au lieu de "i = 1" return (i*i == n); }
Figure 5 : Explorateur de tests quand tous les tests sont OK
4.2 Cas d'une solution Visual Studio contenant déjà un projet console (par exemple, une application SFML)
4.2.1 Principe
Pour traiter ce cas, nous nous ramenons au cas précédent. Pour ce faire, nous décomposons notre solution en un projet console (qui est une coquille presque vide) et un projet librairie statique (qui contient l'ensemble de votre code).
4.2.2 Exemple
Par exemple (SVP, déroulez cet
exemple sur votre propre projet), supposons que vous ayez créé un
projet SFML appelé JeuDeLaMortQuiTue
avec la procédure vue depuis le
début de cette U.V. :
- Ouvrez votre solution
JeuDeLaMortQuiTue
. - Menu
Fichier
/Nouveau
/Projet...
: une fenêtre s'ouvre. - Choisissez
Projet Win32
, indiquezMaBibliotheque
au niveau du champ Nom :, vérifiez que le champ Solution : (en bas à gauche) a la valeur "Créer une nouvelle édition", et cliquez surOK
. - Une fenêtre d'assistant apparaît : cliquez sur
Suivant>
- Cochez la case Projet vide, sélectionnez Bibliothèque statique, décochez En-tête précompilé, et cliquez sur Terminer.
- Avec l'explorateur de solutions
- Si jamais, ils sont présents, supprimez (définitivement) les
fichiers
stdafx.h
,targetver.h
etstdafx.cpp
- Clic-droit sur "Fichiers sources, puis Ajouter / Nouvel
élément… . Une fenêtre s'ouvre : choisissez Fichier C++,
donnez le nom
monMain.cpp
, et cliquez sur OK. Dans ce fichier source :- recopiez tout le contenu de
main.cpp
de votre projetJeuDeLaMortQuiTue
; - ajoutez la ligne
include "monMain.h
" - remplacez
int main()
parint monMain()
- recopiez tout le contenu de
- Même manipulation en cliquant droit sur Fichiers sources pour
créer
monMain.h
avec le contenu :
- Si jamais, ils sont présents, supprimez (définitivement) les
fichiers
#pragma once int monMain();
- Votre projet
MaBibliotheque
a besoin d'accéder aux fichiers d'include de la SFML. Donc, clic droit surMaBibliotheque
, Propriétés.- Une fenêtre s'ouvre. Dans la colonne de gauche, sélectionnez
C/C++
. - Dans le champ Autres répertoires Include, mettez
C:\Software\SFML-2.4.2\include
Cliquez sur OK
- Une fenêtre s'ouvre. Dans la colonne de gauche, sélectionnez
- Modifiez
main.cpp
du projetJeuDeLaMortQuiTue
en remplaçant son contenu par :
#include "../MaBibliotheque/monMain.h" int main() { return monMain(); }
- Dans l'explorateur de solutions, pour chaque fichier
.h
ou.cpp
de votre projetJeuDeLaMortQuiTue
, excepté le fichiermain.cpp
, cliquez gauche sur le fichier, puis menu Fichier / Déplacer nomFichier vers > /MaBibliotheque
. Ainsi, votre projetJeuDeLaMortQuiTue
n'est désormais plus qu'une coquille vide qui contient unmain()
réduit à sa plus simple expression. - Votre projet
JeuDeLaMortQuiTue
a besoin de référencer la bibliothèqueMaBibliotheque
pour que l'édition de liens se fasse :- Dans l'explorateur de solutions, clic gauche sur projet
JeuDeLaMortQuiTue
. Puis, menu Projet / Ajouter une référence…. - Cochez
MaBibliotheque
. Cliquez sur OK.
- Dans l'explorateur de solutions, clic gauche sur projet
- Générez la solution : menu Générer / Générer la solution
- Définissez
JeuDeLaMortQuiTue
comme projet de démarrage : dans l'explorateur de solutions, clic droit surJeuDeLaMortQuiTue
, puis clic gauche sur Définir comme projet de démarrage. - Avec Menu Déboguer / Exécuter sans débogage, exécutez votre programme pour vérifier que cette restructuration ne l'empêche pas de fonctionner.
4.2.3 Mise en place et exécution de tests unitaires
Pour mettre en place et exécuter des tests unitaires, il suffit désormais de suivre la procédure décrite dans la section Cas d'une solution Visual Studio contenant un projet Win32 (par exemple, une bibliothèque) en tenant compte des spécificités suivantes :
- Une fois votre projet
UnitTest
créé conformément à la procédure, ce projet a besoin d'accéder aux bibliothèques de la SFML pour que l'édition de liens se fasse. Donc :- Clic droit sur
UnitTest
, Propriétés - Une fenêtre s'ouvre. Dans la colonne de gauche, sélectionnez
Editeur de liens
. - Dans le champ Répertoires de bibliothèques supplémentaires, mettez
C:\Software\SFML-2.4.2\lib
- Dans la colonne de gauche, cliquez sur le triangle devant Editeur
de liens pour déplier l'arborescence. Cliquez sur entrée et
ajoutez au début du champ Dépendance suplémentaires la chaîne de
caractè_res
sfml-audio.lib;sfml-graphics.lib;sfml-network.lib;sfml-system.lib;sfml-window.lib;
(sans les guillemets) - Cliquez sur OK
- Clic droit sur
- Pour exécuter vos tests unitaires :
- Définissez
UnitTest
comme rojet de démarrage : dans l'explorateur de solutions, clic droit surUnitTests
, puis clic gauche sur Définir comme projet de démarrage - Ensuite, menu Déboguer / Exécuter sans débogage OU BIEN exécution des tests à partie de l'explorateur de tests.
- Définissez
- Pour exécuter votre application :
- Définissez
JeuDeLaMortQuiTue
comme projet de démarrage : dans l'explorateur de solutions, clic droit surJeuDeLaMortQuiTue
, puis clic gauche sur Définir comme projet de démarrage. - Ensuite, menu Déboguer / Exécuter sans débogage
- Définissez
4.2.4 Remarque finale
Si vous avez besoin de créer un nouveau fichier pour votre
application, veillez à désormais le créer dans le projet
MaBibliotheque
afin que le projet JeuDeLaMortQuiTue
reste une
coquille vide.