Make et CMake/Ctest - LISIC

Transcription

Make et CMake/Ctest - LISIC
Make et CMake/Ctest
E. RAMAT
Université du Littoral - Côte d’Opale
21 septembre 2010
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
1 / 54
Objectifs
aboder les outils de gestion du processus de compilation ;
intégrer la phase de tests unitaires ;
documenter ses sources et générer la documentation ;
Contexte
Ces thèmes sont abordés dans le contexte des langages C et C++.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
2 / 54
Plan
1
Make
2
CMake
3
CTest et Boost
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
3 / 54
Introduction
Les Makefiles sont des fichiers utilisés par le programme make pour
exécuter un ensemble d’actions
Plusieurs utilitaires
GNU make
mais aussi : gmake, nmake, tmake, . . .
Make est un outil qui contrôle la génération d’exécutables et les autres
fichiers non-source d’un programme à partir des fichiers sources.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
4 / 54
Introduction
gérer les dépendances entre fichiers à : construire / compiler /
“linker” / exécuter
automatiser la construction / l’exécution en reconstruisant ce qui
est nécessaire et uniquement suffisant
rapidité de construction par rapport au processus “à la main”
Exemples
.o/.c/.h : bibliothèque, archive, installation
.tex/.dvi/.ps : génération de documentation
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
5 / 54
Principe
Un graphe de dépendances va être construit à partir :
de cibles (fichier ou simple nom)
de leurs dépendances
des tâches à réaliser
Qu’est qu’une dépendance ?
Un élément qui nécessite l’exécution des tâches s’il n’est pas à jour
par rapport à la cible
Comment détermine-t-on qu’on est à jour ?
Par les dates de dernière modification
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
6 / 54
Principe
L’ensemble des informations est centralisé dans un fichier, interprété
par la commande make :
Nom par défaut : makefile ou Makefile
Constitué de règles
Une règle a la forme :
cible : liste des dépendances
<tab> tâches (en sh)
Des raccourcis et des variables d’environnement permettent de décrire
plus facilement les règles, les cibles, les dépendances et les tâches
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
7 / 54
Principe
Un premier exemple
helloworld : helloworld . o
<tab > gcc -o helloworld helloworld . o
helloworld . o : helloworld . c helloworld . h
<tab > gcc -c helloworld . c
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
8 / 54
Principe
Schéma général
cible1 ... cibleN : prerequis1 ... prerequisP
<tab >
commande1 ; ... ; commandeC
ou bien
cible1 ... cibleN : prerequis1 ... prerequisP ; cde1 ; ... ; cdeC
ou encore
cible1 ... cibleN : prerequis1 ... prerequisP
<tab >
commande1
<tab >
...
<tab >
commandeC
Tous les cas intermédiaires sont possibles ...
Les cibles doivent être séparées par des espaces ou tabulations
ainsi que les dépendances.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
9 / 54
Interprétation
Pour décider d’exécuter les tâches d’une règle, il faut vérifier au
préalable si une des dépendances nécessite une mise en
cohérence par rapport à la cible.
Les commandes qui composent la tâches sont alors exécutées
séquentiellement
Si une commande provoque à une erreur, alors la cible n’est pas
rendue cohérente et TOUT le processus s’arrête.
Une cible est incohérente lorsque :
I
I
I
un de ses dépendants est incohérent,
la cible n’existe pas,
sa date de dernière modification est antérieure à celles de ses
dépendances
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
10 / 54
La commande Make
make
make nomDeCible : construit la cible indiquée
make f monMakefile : utilise le fichier indiqué si ce dernier ne se
nomme pas makefile ou Makefile
make i : ignire globalement toutes les erreurs qui peuvent survenir
make n : montre ce que l’on ferait
make : recontruit la première cible trouvée dans le fichier Makefile
ou makefile dans le répertoire courant
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
11 / 54
Autres éléments de syntaxe
Commentaire : toute suite de caractères après un #.
Le caractère TAB :
I
I
I
une ligne commence par TAB, ce qui suit est interprété comme une
commande shell
une série d’espaces n’a pas le même effet
un TAB esthétique en début de ligne peut jouer des tours . . .
Commande invisible : le caractère placé devant une commande
empêche l’affichage de l’intitulé de la commande à la console.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
12 / 54
Les variables
Il y a plusieurs types de variables pour make :
les variables passées par commande
les variables d’environnement
les variables définies dans le makefile
les variables automatiques
Variable passée par commande
make TOTO=objet.c
dans le fichier makefile, toutes les occurrences de $(TOTO) ou de
$TOTO seront remplacées par objet.c.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
13 / 54
Les variables d’environnement
Toutes les variables du shell lançant make sont accessibles
echo \ $ ( VARIABLE ) # renvoie la valeur de la variable d ’ envi
␣ ␣ ␣ ␣ ␣ ␣ VARIABLE .
␣␣␣␣
Si la commande make est lancée par un shell donné (bash, zsh,
sh, ...), toutes les variables d’environnement de ce shell peuvent
être utilisées dans le makefile.
La seule exception est la variable SHELL qui, par défaut, vaut
toujours
/bin/sh, mais qui peut être modifiée dans le makefile.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
14 / 54
Les variables définies dans le Makefile
Définition : var = valeur
Mécanisme : la substitution de la variable var
I
toutes les occurrences de $(var) ou de $var seront remplacées par
valeur
Attention, la substitution est récursive !
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
15 / 54
Les variables
$variable correspond à une variable du makefile
le $$ peut être utilisé pour passer une expression de variable
commençant par $ au shell.
affiche :
<TAB >
for fic in *. c ; do ls $$fic ; done
$ make affiche
for fic in *. c ; do ls $fic ; done
convert2sens . c convertir . c outils . c
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
16 / 54
Les variables
Pour pouvoir ajouter quelque chose à une variable (à substitution
récursive ou simple), on utilise l’opérateur binaire + = :
variable = valeur
variable+ = davantage
est équivalent à :
temp = valeur
variable = $(temp) + davantage
sauf qu’aucune variable temp n’est définie
CC = gcc
CFLAGS = -c
OBJS = convertir . o outils . o convert2sens . o
convertir : $ ( OBJS )
$ ( CC ) $ ( OBJS ) -o convertir
convert2sens . o : convert2sens . c convertir . h outils . h
$ ( CC ) $ ( CFLAGS ) convert2sens . c
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
17 / 54
Les variables
* et ?, [a-z] et autres peuvent être utilisés dans :
I
I
I
les commandes shell (comme d’habitude)
les cibles
les prérequis
on peut ainsi créer des règles à motifs :
*. o : *. c
<TAB > gcc -c *. c
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
18 / 54
Les variables
Les variables automatiques
Ces variables sont définies et remises à jour par make.
Elles ne peuvent être utilisées que dans une règle et désignent
une des cibles, les prérequis, un sous-ensemble de prérequis, . . .
$ : remplacé par le nom du fichier cible.
I
s’il y a plusieurs noms dans la cible, alors $ est remplacé par celui
des noms dans la cible qui a déclenché l’application de la règle.
convertir : $ ( OBJS )
<TAB >
$ ( CC ) $ ( OBJS ) -o $@
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
19 / 54
Les variables
Les variables automatiques
$* : préfixe de la cible
$ˆ : remplacé par la liste des prérequis, chaque nom étant séparé
par une espace :
I
I
si un certain prérequis a été répété plusieurs fois, alors il n’apparaît
qu’une seule fois dans $ˆ.
si on veut que l’ordre des éléments et le nombre des répétitions
soient préservés, il faudra utiliser $+ au lieu de $ˆ.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
20 / 54
Les variables
Les variables automatiques
$< désigne le premier prérequis.
I
nom du fichier qui a causé l’action associée à la cible (celui qui
serait utilisé par la règle implicite)
convert2sens . o : convert2sens . c
<TAB >
$ ( CC ) -c $ <
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
21 / 54
Les variables
Les variables automatiques
$? est remplacé par la liste des prérequis qui sont plus jeunes
qu’au moins une des cibles.
I
en fait $? désigne la liste des prérequis qui sont responsables de
l’application de la commande de la règle.
print : *. c
<TAB >
@echo $ ? : fichiers C
$ make print
convert2sens . c convertir . c outils . c : fichiers C
il existe d’autres variables automatiques ($
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
22 / 54
Les règles explicites
convert2sens . o : convert2sens . c
<TAB >
$ ( CC ) -c $ <
La règle ci-dessus est intéressante mais on pourrait l’appliquer à tout
fichier .c pour le lier au .o correspondant.
Il existe en fait une telle règle, dite implicite :
.c.o:
<TAB > $ ( CC ) -c $ <
ou
%. o : %. c
<TAB > $ ( CC ) -c $ <
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
23 / 54
Un exemple complet
CC = gcc
CFLAGS = - Wall - ansi
LDFLAGS = - Wall - ansi
EXEC = hello
all : $ ( EXEC )
hello : hello . o main . o
$ ( CC ) -o $@ $ ^ $ ( LDFLAGS )
main . o : hello . h
%. o : %. c
$ ( CC ) -o $@ -c $ < $ ( CFLAGS )
clean :
rm - rf *. o
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
24 / 54
Plan
1
Make
2
CMake
3
CTest et Boost
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
25 / 54
CMake
C’est quoi ?
outil d’aide au processus de compilation (build), multi
plates-formes et open source
développé depuis 2001 par Kitware (VTK – Visualization ToolKit)
adopté par les développeurs de KDE
Pour faire quoi ?
capable de générer des makefile/unix, des projets MS Visual
Studio, Borland, . . . qui seront utilisés par les outils natifs lors de la
compilation
nombreuses commandes permettant de localiser les fichiers
d’entêtes, les bibliothèques, les executables, . . .
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
26 / 54
CMake
Pour faire quoi ? - suite
propose de nombreuses extensions pour localiser X, Qt, OpenGL,
Swig, . . .
propose des interfaces de test (CTest) et de packaging (CPack)
Liens et installation
site Web : http://www.cmake.org
paquet Debian - unstable : version 2.8.2
installation : apt-get install cmake
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
27 / 54
CMake
avec Make
main . o : main . c main . h
<TAB >
cc -c main . c
MyProgram : main . o
<TAB >
cc -o MyProgram main . o - lm - lz
avec CMake
PROJECT ( MyProject C )
ADD_E XECUTABL E ( MyProgram main . c )
T A R G E T _ L I N K _ L I B R A R I E S ( MyProgram z m )
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
28 / 54
CMake
Schéma de compilation
capable de gérer le processus de compilation indépendamment
du système d’exploitation et du compilateur
connaissance de très nombreuses plates-formes et outils
l’utilisateur configure son build avec CMake
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
29 / 54
CMake
Structure et répertoires
L’arborescence des sources contient :
fichier d’entrée de CMake (CMakeLists.txt)
fichiers sources du programme (*.cpp, par exemple)
L’arborescence des produits de la compilation contient :
fichiers natifs de compilation (Makefile, *.dsp pour Visual Studio)
les bibliothèques et les exécutables (*.exe, par exemple)
Les deux arborescences peuvent être :
dans le même répertoire (in-source build)
dans des répertoires différents (out-of-source build) :
I
I
src : les sources (cpp, hpp, java, py, . . . ) et les CMakeLists.txt
build : les produits de la compilation (.so, .a, .exe, . . . )
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
30 / 54
CMake
Eléments de syntaxe
CMake dispose d’un langage de type script :
commentaire : # commentaire jusqu’à la fin de la ligne
commande : COMMAND (arg1 arg2 ...)
liste : A;B;C
variable : ${VAR}
structure de contrôle : IF (CONDITION) FOREACH(v A B C)
détection de bibliothèques : FIND_LIBRARY(...)
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
31 / 54
CMake
Le cache de CMake
résume l’ensemble de la configuration du build
fichier CMakeCache.txt situé à la racine du projet
créé et mis à jour lors des phases de configuration réalisées par
CMake
Les variables incontournables
CMAKE_BUILD_TYPE=[Debug, Release]
CMAKE_INSTALL_PREFIX=[/usr/local]
CMAKE_VERBOSE_MAKEFILE=[OFF, ON]
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
32 / 54
CMake
Un exemple - les fichiers
Attention, les sources des sous-répertoires ne sont inclus dans le
projet que si un CMakeLists.txt n’est présent dans le répertoire
FOO-code :
I
I
I
ADD_SUBDIRECTORY(foo)
ADD_SUBDIRECTORY(bar)
ADD_SUBDIRECTORY(example)
ou : SUBDIRS(foo bar example)
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
33 / 54
CMake
Un exemple - les CMakeLists.txt
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
34 / 54
CMake
Installation
par défaut, les éléments (.h, .so, les exécutables, ...) sont installés
dans /usr/local/
dans le cas de la séparation du build des sources (construction
dans le répertoire build) :
cmake - D C M A K E _ I N S T A L L _ P R E F I X =/ home / eric / usr / ..
la variable ${CMAKE_INSTALL_PREFIX} est modifiée
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
35 / 54
CMake
Installation
la commande d’installation des résultats de la compilation :
INSTALL ( TARGETS example DESTINATION $ { C M A K E _ I N S T A L L _ P R E F I
installation des headers :
SET ( BAR_H bar1 . h bar2 . h )
INSTALL ( FILES $ { BAR_H } DESTINATION $ { C M A K E _ I N S T A L L _ P R E F I X }/ includ
la même technique peut être utilisé pour n’importe quel fichier
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
36 / 54
CMake
Librairies et pkgconfig
toutes les librairies ne sont pas reconnus par CMake
à l’installation de bibliothèques, on peut avoir à notre disposition
des .pc : informations sur l’emplacement des fichiers (.h, .a, .so,
...)
Exemple
$ pkg - config -- libs glibmm -2.4
- lglibmm -2.4 - lgobject -2.0 - lsigc -2.0 - lglib -2.0
$ pkg - config -- cflags glibmm -2.4
-I / usr / include / glibmm -2.4 -I / usr / lib / glibmm -2.4/ include
-I / usr / include / sigc ++ -2.0 -I / usr / lib / sigc ++ -2.0/ include
-I / usr / include / glib -2.0 -I / usr / lib / glib -2.0/ include
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
37 / 54
CMake
Recherche des paquets
# chargement du paquet CMake prenant en charge PkgConfig
FIND_PACKAGE ( PkgConfig )
# recheche de la librairie glibmm -2.4
PK G _ C H E C K _ M O D U L E S ( GLIBMM glibmm -2.4)
Utilisation des informations
# utilisation des informations de chemins
I N C L U D E _ D I R E C T O R I E S ( $ { G L I B M M _ I N C L U D E _ D I R S })
LI N K _ D I R E C T O RI E S ( $ { G L I B M M _ L I B R A R Y _ D I R S })
ADD_E XECUTABL E ( example example1 . cpp example2 . cpp )
# utilisation des informations de nommage des librairies
T A R G E T _ L I N K _ L I B R A R I E S ( example $ { G L I B M M _ L I B R A R I E S })
les sources example1.cpp et example2.cpp peuvent maintenant
inclure des headers de la glibmm
les variables créées par la commande PKG_CHECK_MODULES
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
38 / 54
Plan
1
Make
2
CMake
3
CTest et Boost
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
39 / 54
CTest
Qu’est ce que c’est ?
fait partie de la distribution CMake
peut-être utilisé avec ou sans CMake
permet de réaliser plusieurs types de test sur le code source :
I
I
exécution de tests prédéfinis,
exécution de tests avancés:
F
F
couverture de code : uniquement avec g++ -fprofile-arcs
-ftest-coverage
état de la mémoire : utilisation de purify ou valgrind
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
40 / 54
CTest
Comment faire ?
les tests doivent être activés dans le CMakeLists.txt principal :
ENABLE_TESTING()
le programme de tests est un exécutable comme les autres
ADD_E XECUTABL E ( test1 test1 . cpp )
T A R G E T _ L I N K _ L I B R A R I E S ( test1 $ { B o o s t _ U N I T T E S T F R A M E W O R K })
ADD_TEST ( apptest1 test1 )
ici, on linke l’exécutable avec une bibliothèque de tests unitaires :
Boost::UnitTestFramework
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
41 / 54
CTest
Les commandes
liste des tests : ctest -N
exécution des tests : make test ou ctest ; tous tests sont
exécutés et un rapport est généré
exécution d’un sous-ensemble des tests : ctest -I 2,3 ; les tests
2 et 3 sont exécutés
un répertoire Testing/Temporary est crée dans le build avec les
rapports : LastTest.log et LastTestsFailed.log
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
42 / 54
Les tests unitaires et Boost
Le test unitaire est une technique qui permet de s’assurer du
fonctionnement correct d’une partie déterminée d’un logiciel ou d’une
portion d’un programme.
le code du test est indépendant du reste du programme.
→ utilise uniquement les interfaces fonctionnelles.
il couvre le maximum de code : couverture de code.
→ tout n’est cependant pas testable, il faut parfois émuler : bases de
données, fichiers, web, etc.
nécessite un framework :
→ JUnit (java),
→ CPPunit (C++),
→ Pyunit (Python), etc.
→
E. Ramat (ULCO)
Boost::Test
Make/CMake/CTest
21 septembre 2010
43 / 54
Suite de test
Les tests sont, en général, de simples assertions inclues dans des
suites de tests : test cases et test suites.
test case : de simple tests, A == B, str == "toto" etc.
BOOST_CHECK (0 == 1);
B O O S T _ C H E C K _ T H R O W ( openfile ( " test . dat " ) , std :: exception );
test suite : dirige les tests, réaction fasse aux erreurs, où sortir les
erreurs, etc.
std :: ofstream out ( " output . log " );
unit_test_log :: instance (). set_l og_outpu t ( out );
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
44 / 54
Test case : les types d’erreurs
Les trois types de cas de tests :
Type
WARN
CHECK
REQUIRE
Définition
avertissement
erreur
erreur fatale
Compteur
non affecté
affecté
affecté
Comportement
continue
continue
annulé
Note
Le compteur décris le nombre d’erreurs dans une suite de test.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
45 / 54
Boost::test : API
BOOST_[type](test) : s’assure que le test est vrai
BOOST_[type]_MESSAGE(str) : affiche la chaîne de caractères str
BOOST_[type]_EQUAL(x, y) : s’assure que x égal y
BOOST_[type]_CLOSE(x, y, z) : test d’égalité entre des réels x
et y avec une tolérance z
BOOST_[type]_THROW(fct, expt) : s’assure que l’appel à la
fonction fct lève une exception expt
BOOST_[type]_NO_THROW(fct, expt) : s’assure que l’appel à la
fonction fct ne lève pas une exception expt
BOOST_CHECKPOINT(str) : capture la levée de signaux, division
par zéro, boucle infinie, etc.
Remarque
À noter l’existence de la macro BOOST_MESSAGE(str) qui montre une
chaîne de caractères.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
46 / 54
Description de l’exemple
Dans la méthode Extrem Programming, il est recommandé
d’écrire les tests avant le code afin de forcer à définir des
interfaces de programmation propres.
Dans l’exemple suivant nous considérons les tests unitaires de
type fonctions :
I
I
test.cc contient une suite de tests qui exécute un ensemble de
fonction représentant les tests.
moyenne.cc la fichier contenant la fonction à tester.
Remarque
Les gestionnaires de projets tel que les autotools, cmake ou encore
scons gèrent les makefile de tests. Pour gérer l’exemple suivant, nous
écrivons un makefile « maison ».
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
47 / 54
Écriture d’un makefile
Makefile
CFLAGS = - Wall -g - O2
LDFLAGS =
LDFLAGSTEST = - l b o o s t _ u n i t _ t e s t _ f r a m e w o r k
# construction de l ’ executable
all : exe
exe : moyenne . o
g ++ -o exe moyenne . o $ ( LDFLAGS )
moyenne . o : moyenne . cc
g ++ -c moyenne . cc $ ( CFLAGS )
c
# construction et exà cution
du test
check : test1
./ test1
test1 : test1 . o moyenne . o
g ++ -o test1 test1 . o moyenne . o $ ( LDFLAGSTEST )
test1 . o : test1 . cc
g ++ -c test1 . cc $ ( CFLAGS )
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
48 / 54
Exemple 1
Fichier de test : test.cc
# include < boost / test / unit_test . hpp >
using n a m e s p a c e boost :: u n i t _ t e s t _ f r a m e w o r k ;
/* la fonction de test */
void test_moyenne ()
{
std :: vector < float > tab ;
BOOST_REQUIRE ( moyenne ( tab ) == 0.0);
tab += 1.0 , 2.0 , 3.0;
BOOST_REQUIRE ( moyenne ( tab ) == 2.0);
}
/* encapsulation du main par boost :: unit */
boost :: u n i t _ t e s t _ f r a m e w o r k :: test_suite *
i n i t _ u n i t _ t e s t _ s u i t e ( int , char * [])
{
boost :: u n i t _ t e s t _ f r a m e w o r k :: test_suite * test ;
test = B O O S T _ T E S T _ S UI T E ( " test " );
test - > add ( BO O ST _T EST_ C AS E (& test_moyenne ));
return test ;
}
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
49 / 54
Exemple 2
Fichier de calcul
float moyenne ( const std :: vector < float >& tab )
{
float sum = 0.0;
for ( std :: vector < float >:: con st_itera tor it = tab . begin ();
it != tab . end (); ++ it ) {
sum += * it ;
}
return sum / tab . size ();
}
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
50 / 54
Exemple 2
Fichier de calcul
float moyenne ( const std :: vector < float >& tab )
{
float sum = 0.0;
for ( std :: vector < float >:: con st_itera tor it = tab . begin ();
it != tab . end (); ++ it ) {
sum += * it ;
}
return sum / tab . size ();
}
Problème
À l’exécution des tests, le premier test plante sur une division par zéro !
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
50 / 54
Exemple 3
Modification du fichier de calcul
float moyenne ( const std :: vector < float >& tab )
{
if ( not tab . empty ()) {
float sum = 0.0;
for ( std :: vector < float >:: con st_itera tor it = tab . begin ();
it != tab . end (); ++ it ) {
sum += * it ;
}
return sum / tab . size ();
} else {
return 0.0;
}
}
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
51 / 54
Une autre façon de faire les tests
Utilisation des auto-tests
# define B O OS T_ TE ST _ MA IN
# define B O O S T _ A U T O _ T E S T _ M A I N
# define B O O S T _ T E S T_ M O D U L E moyenne_test
# include < boost / test / unit_test . hpp >
# include < boost / test / auto_un it_test . hpp >
B O O S T _ A U T O _ T E S T _ C A S E ( moyenne )
{
std :: vector < float > tab ;
B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 0.0);
tab . push_back (1.0); tab . push_back (2.0); tab . push_back (3.0);
B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 2.0);
}
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
52 / 54
Une autre façon de faire les tests
Utilisation des auto-tests
# define B O OS T_ TE ST _ MA IN
# define B O O S T _ A U T O _ T E S T _ M A I N
# define B O O S T _ T E S T_ M O D U L E moyenne_test
# include < boost / test / unit_test . hpp >
# include < boost / test / auto_un it_test . hpp >
B O O S T _ A U T O _ T E S T _ C A S E ( moyenne )
{
std :: vector < float > tab ;
B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 0.0);
tab . push_back (1.0); tab . push_back (2.0); tab . push_back (3.0);
B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 2.0);
}
Auto-tests
Cette technique permet de réduire le code des tests. La création de la
suite de tests est automatique.
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
52 / 54
Boost::Test et CMake
Le CMakeLists.txt - racine
PROJECT ( MOYENNE CXX C )
ENABL E_TESTIN G ()
FIND_PACKAGE ( Boost )
IF ( Boost_FOUND )
FIND_LIBRARY ( B o o s t _ U N I T T E S T F R A M E W O R K
boost_unit_test_framework - mt PATHS
IF ( B o o s t _ U N I T T E S T F R A M E W O R K )
SET ( H A V E _ U N I T T E S T F R A M E W O R K 1 CACHE
ELSE ( B o o s t _ U N I T T E S T F R A M E W O R K )
SET ( H A V E _ U N I T T E S T F R A M E W O R K 0 CACHE
ENDIF ( B o o s t _ U N I T T E S T F R A M E W O R K )
ENDIF ( Boost_FOUND )
NAMES b o o s t _ u n i t _ t e s t _ f r a m e w o r k
Boost_LIBRARY_DIRS )
INTERNAL " " FORCE )
INTERNAL " " FORCE )
A D D _ S U B D I R E C TO R Y ( src )
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
53 / 54
Boost::Test et CMake
Le CMakeLists.txt - du répertoire src
I N C L U D E _ D I R E C T O R I E S ( $ { B o o s t _ I N C L U D E _ D I R S })
L I N K _ D I R E C T O RI E S ( $ { B o o s t _ L I B R A R Y _ D I R S })
ADD_E XECUTABL E ( test1 test . cpp moyenne . cpp )
ADD_TEST ( moyenne_test test1 )
T A R G E T _ L I N K _ L I B R A R I E S ( test1 $ { B o o s t _ U N I T T E S T F R A M E W O R K })
E. Ramat (ULCO)
Make/CMake/CTest
21 septembre 2010
54 / 54