Tests unitaires avec Check, Gcov et Lcov

GNU/Linux Magazine n° 154 | novembre 2012 | Damien Balima
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
Réalisez des tests unitaires avec Check et vérifiez leur couverture de code avec Gcov et Lcov.

1. Introduction

Qu'il s'agisse de développer un logiciel, un site web, ou même un script, aucune application n'est à l'abri d'un défaut, d'une erreur, d'un plantage à l'utilisation. Pour réduire ces risques, une bonne pratique est de tester l'application classe par classe, fonction par fonction, ligne de code par ligne de code, par des jeux de tests appropriés : les tests unitaires (l'unité étant la partie de code testée). Ceux-ci, contrairement aux tests d'intégration et de validation, ne visent que le code interne de l'application, et non son comportement durant l'exécution : ils se situent au niveau du développement applicatif.

Le test logiciel a fortement évolué ces dernières années et fait l'objet à présent d'une certification internationale, l'International Software Testing Qualifications Board (ISTQB). Un projet de développement nécessite de multiples phases de tests, qui vont des tests unitaires aux tests de montée en charge, en passant par les tests d'assemblage, d'intégration, de compatibilité, les tests fonctionnels, les tests nominaux, les tests aux valeurs clés, aux limites, hors domaine, tests de robustesse, de configuration matérielle, de performance, tests d'homologation (ou VABF, Vérification d'Aptitude au Bon Fonctionnement), les tests de déploiement, voire une certification (Common Criteria, par exemple). Les testeurs sont ainsi les contrôleurs de code, indépendants des développeurs, disposant d'une pléthore de méthodes pour tester et valider les développements. [1, 2, 3]

Ces tests ont pour but de détecter le maximum de défauts, bien qu'ils ne peuvent être exhaustifs (ce qui impliquerait de tester une infinité de combinaisons). Lorsqu'un défaut est détecté, les développeurs en sont avertis et déboguent la partie du programme concernée. Les tests unitaires réalisés au plus tôt, durant la phase même de développement, sont plus économiques que la détection a posteriori qui implique une livraison d'un correctif (ou patch), d'une nouvelle version. Aussi, certaines méthodes agiles comme la méthode XP (Extreme Programming) implémentent directement la programmation en binôme développement - tests unitaires. Les tests unitaires sont réutilisables pour les tests de non-régression et, de par leurs indications sur le fonctionnement des composants, facilitent également la reprise de code. [4]

S'agissant de tester des bouts de code, les tests unitaires peuvent se réaliser durant le développement, quand bien même l'application ne serait pas encore exécutable. Ce sont des tests statiques, qui concernent le code, et non des tests dynamiques de l'exécutable. Ensuite ils peuvent être de type boîte blanche, lorsque l'on vérifie les instructions internes de l'unité, ou de type boîte noire, lorsqu'il s'agit de tester l'unité d'après ses spécifications (valeurs retours) sans vérifier le code intrinsèque. Les tests boîtes blanches permettent également la couverture de code (code coverage), c'est-à-dire de connaître le taux de lignes de code couvert par les tests. Ainsi, certaines normes de qualité logicielles intègrent un taux de couverture de code pouvant être total, selon le niveau de criticité de l'application, comme la norme aéronautique ED-12B(ou DO-178B), la norme industrielleIEC 61508, ou la norme spatiale européenne ECSS-E-40. [5]

Si les langages de programmation diffèrent, le principe des tests unitaires reste le même, à savoir l'utilisation d'assertions pour vérifier la validité d'une expression, d'une fonction, d'une unité de code. On obtient ainsi du code de qualité assez rapidement, tout en évitant bon nombre de correctifs ultérieurs et le mécontentement des utilisateurs. Il existe également d'autres méthodes pour obtenir du code de qualité, telles que les vérifications formelles et le model checking, mais de prime abord plus complexes et réservées aux projets les plus critiques.

Dans la suite de cet article, nous nous intéresserons au framework de tests unitaires Check, pour tester un petit programme en C, puis nous utiliserons l'outil Gcov pour vérifier la couverture de code testée, et avec l'application Lcov, nous afficherons un rendu HTML dynamique des résultats de couverture de code Gcov.

2. Tests unitaires avec Check

Pour ces tests, nous allons créer une bibliothèque contenant les fonctions du programme, qui sera utilisée par Check pour créer un exécutable de jeux de tests unitaires. Pour cela, on créera une arborescence avec les autotools (voir schéma), un répertoire tests contenant les tests unitaires, et un répertoire src pour le code source. On ajoutera également des fichiers Makefile.am et configure.ac pour la configuration automatique et le lancement des tests unitaires. En effet, un avantage d'utiliser le framework Check est qu'il soit intégré aux autotools, ce qui facilite les tests unitaires dans un projet structuré par ceux-ci.

2.1. Codage du programme source

Le programme en C que l'on va tester vise à calculer le rayon de Schwarzschild d'un astre. Si le rayon d'une étoile devient inférieur ou égal à son rayon de Schwarzschild, alors elle devient un trou noir, et tout objet qui s'approche en deçà du rayon de Schwarzschild d'un trou noir ne peut plus s'en échapper. [6]

Sa formule, sans entrer dans la géométrie de Schwarzschild, est la suivante :

RS est le rayon de Schwarzschild, G la constante de gravitation, M la masse de l'astre en kilogrammes et c la vitesse de la lumière.

Le programme prend en entrée une masse et affiche son rayon de Schwarzschild. On place la fonction de calcul dans un fichier astro.c pour en créer une bibliothèque libastro que l'on testera. On crée ainsi trois fichiers sources : main.c, astro.c et astro.h, à placer dans un répertoire src, comme indiqué sur le schéma précédent.

2.1.1. Le fichier d'en-tête astro.h

Il contient les prototypes des fonctions de la bibliothèque. Pour notre programme, on aura besoin d'une fonction getScwarzschild qui prend en paramètre une masse et retourne un rayon.

#ifndef ASTRO_H

#define ASTRO_H

#define LIGHT_SPEED 299792458

#define CONSTANTE_G 6.67300e-11

/* paramètre : masse en kilogramme

   retourne : le rayon de Schwarzschild en mètre */

double getSchwarzschild(double masse);

#endif

2.1.2. Le fichier source astro.c

Il fournit les définitions, le code des fonctions déclarées précédemment. Si la masse est strictement positive, la fonction retourne le rayon de Schwarzschild, sinon elle retourne zéro.

#include "astro.h"

#include <math.h>

double getSchwarzschild(double masse)

{

    if(masse > 0){

        return 2 * CONSTANTE_G * masse / (pow( LIGHT_SPEED, 2));

    }else{

        return 0.;

    }    

}

2.1.3. Le fichier source main.c

Il contient la fonction principale main() appelée à l'exécution du programme, prenant la masse en paramètre, avec quelques vérifications sur le format du paramètre (cf. man strtod, strtol).

#include "astro.h"

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

int main(int argc, char *argv[])

{

    char *pFin = NULL, *pStr = NULL;

    double masse = 0.;

    double schwarzschild = 0.;

    

    if(argc < 2){

        fprintf(stderr, "Usage: %s [masse en kilogrammes]\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    pStr = argv[1];

    masse = strtod(pStr, &pFin);

    /* vérification des erreurs de paramètre */

    if ((errno == ERANGE && (masse == HUGE_VALL || masse == HUGE_VALF))

            || (errno != 0 && masse == 0)) {

        perror("strtod");

        exit(EXIT_FAILURE);

    }

    if (pFin == pStr) {

        fprintf(stderr, "Pas de chiffre trouvé\n");

        exit(EXIT_FAILURE);

    }

    /* calcul du rayon de Swartzschild */

    schwarzschild = getSchwarzschild(masse);

    fprintf(stdout, "Schwarzschild(%.2e kg) = %.2e m\n", masse, schwarzschild);

    exit(EXIT_SUCCESS);

}   

Bien que pour les tests unitaires, nous n'ayons pas besoin de l'exécutable, on peut cependant le compiler afin de vérifier les erreurs de syntaxe par la commande suivante :

$ gcc -o astro astro.c main.c -lm -Wall

$ ./astro 2.3e10

$ Schwarzschild(2.30e+10 kg) = 3.42e-17 m

2.2. Les fichiers pour automake et autoconf

La structure des répertoires doit correspondre à celle indiquée sur le schéma, pour faciliter la configuration automatique. Si ce n'est déjà fait, créez un répertoire src et un répertoire tests à la racine du paquet. Le répertoire src devrait contenir les fichiers sources précédents, et le répertoire tests être vide pour l'instant. Ajoutez-y des fichiers Makefile.am qui seront utilisés par automake pour générer des fichiers Makefile.in. Le processus est le suivant : automake se sert du fichier de propriétés Makefile.am pour générer un fichier de script Makefile.in qui sera utilisé à son tour par autoconf pour générer un Makefile standard.

2.2.1. Le fichier Makefile.am du répertoire src

Il contient les renseignements pour qu'automake puisse générer le Makefile.in de création de la bibliothèque et de l'exécutable astro. Le fichier src/Makefile.am est le suivant :

lib_LTLIBRARIES = libastro.la

libastro_la_SOURCES = astro.c astro.h

libastro_la_LDFLAGS = -lm

bin_PROGRAMS = astro

astro_SOURCES = main.c astro.h

astro_LDFLAGS = -lm

astro_LDADD = libastro.la

On y trouve les paramètres automake, tels que lib_LTLIBRARIESindiquant la bibliothèque à créer – ici une bibliothèque libtool(par défaut libtool créera une bibliothèque portable, à la fois bibliothèque statique et dynamique) –, puis une suite de paramètres commençant par le nom underscoré de la bibliothèque et se terminant par des indicateurs automake (SOURCES pour les fichiers sources, CFLAGS pour les options de compilation, LDFLAGS pour les options d'édition des liens). Idem pour le programme binaire, bin_PROGRAMS, avec en plus l'indicateur LDADD pour l'ajout de bibliothèques à l'édition de liens.

2.2.2. Le fichier Makefile.am du répertoire tests

Comme précédemment, il générera un fichier Makefile.in, mais pour les tests unitaires. On y indique le nom du fichier de tests que l'on utilisera, tests.c, ainsi que la bibliothèque source libastro.la. Le fichier tests/Makefile.am :

TESTS = tests        

check_PROGRAMS = tests

tests_SOURCES = tests.c $(top_builddir)/src/astro.h

tests_CFLAGS = @CHECK_CFLAGS@

tests_LDADD = $(top_builddir)/src/libastro.la @CHECK_LIBS@

2.2.3. Les autres fichiers

Dans le répertoire racine du paquet, créez des fichiers AUTHORS, NEWS, INSTALL, README et ChangeLog.

$ touch AUTHORS NEWS INSTALL README ChangeLog

$ ls

$ AUTHORS ChangeLog INSTALL NEWS README src/ tests/

Ajoutons-y également des fichiers configure.ac et Makefile.am. On indique les sous-répertoires du paquet dans ce fichier Makefile.am.

Le fichier Makefile.am :

SUBDIRS = src . tests

Le fichier configure.ac sera utilisé par autoconf pour réaliser le script de configuration, qui permettra la fameuse commande ./configure qui produira les Makefile standards à partir des Makefile.in. Ce fichier configure.ac peut être généré par la commande autoscan qui vérifiera le contenu des fichiers sources pour identifier les ressources nécessaires.

$ autoscan

$ mv configure.scan configure.ac

Vérifiez le fichier généré et ajoutez les lignes manquantes (AM_INIT_AUTOMAKE, AM_PATH_CHECK, AM_PROG_CC_C_O et LT_INIT).

Le fichier configure.ac :

#                                               -*- Autoconf -*-

# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])

AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])

AC_CONFIG_SRCDIR([src/astro.h])

AC_CONFIG_HEADERS([config.h])

AM_INIT_AUTOMAKE([FULL-PACKAGE-NAME], [VERSION])

LT_INIT()

# Checks for programs.

AC_PROG_CC

AM_PROG_CC_C_O

# Checks for libraries.

AM_PATH_CHECK()

# Checks for header files.

AC_CHECK_HEADERS([float.h stdlib.h])

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_FUNC_STRTOD

AC_CHECK_FUNCS([pow])

AC_CONFIG_FILES([Makefile

                               src/Makefile

                               tests/Makefile])

AC_OUTPUT

2.3. Le fichier de tests unitaires

Pour tester la bibliothèque astro, nous ajoutons un fichier de tests unitaires tests.c dans le répertoire tests.

2.3.1. Syntaxe

Un test unitaire avec Check (inclure check.h) est balisé au début par START_TEST, qui prend en paramètre le nom du test, et à la fin par END_TEST. Une suite de tests est définie par une balise Suite, contenant des ensembles de tests unitaires TCase et gérée par un SRunner.

Pour valider une méthode, une fonction, une unité de code, plusieurs assertions sont disponibles, à l'instar de la macro assert du C mais en plus spécifique. Les assertions disponibles sont les suivantes (macros ck y compris, voir check.h) :

Assertion Résultat
fail_unless Échoue si le test booléen est faux
fail_if Échoue si le test booléen est vrai
fail Échec inconditionnel (utile dans un bloc d'erreur)
ck_abort() Comme fail mais sans message
ck_assert(condition) Comme fail_unless mais sans message
ck_assert_int_eq(X, Y) Échoue si les deux entiers X et Y ne sont pas égaux
ck_assert_int_ne(X, Y) Échoue si les deux entiers X et Y sont égaux
ck_assert_str_eq(X, Y) Échoue si les deux chaînes de caractères X et Y ne sont pas identiques
ck_assert_str_ne(X, Y) Échoue si les deux chaînes de caractères X et Y sont identiques

Durant le make check, si une assertion échoue, le déroulement du test unitaire s'arrête, un message d'erreur est affiché, puis le programme passe au test unitaire suivant.

2.3.2. Les tests unitaires

Un premier test non_zero vérifie que la fonction retourne des rayons non nuls. On ajoute également des tests pour les valeurs nulles, maximales et minimales (inclure float.h). Ajoutons également un test de véracité, sachant que pour la Terre, de masse égale à 5,9736×1024 kg, le rayon de Schwarzschild est à peu près égal à 8,87 millimètres.

Pour exécuter l'ensemble des tests, on crée une suite de tests astro_suite, que l'on appellera dans la fonction principale main() par un SRunner.

Le fichier tests/tests.c est le suivant :

#include "../src/astro.h"

#include <check.h>

#include <float.h>

#include <stdlib.h>

#define MTERRE 5.9736e24

START_TEST (non_zero)

{

   fail_if(getSchwarzschild(0.00001)==0., "doit retourner une valeur non nulle");

   fail_if(getSchwarzschild(1000000)==0., "doit retourner une valeur non nulle");

}

END_TEST

START_TEST (zero)

{

   fail_unless(getSchwarzschild(0.0)==0., "doit retourner une valeur nulle");

   fail_unless(getSchwarzschild(0)==0., "doit retourner une valeur nulle");

}

END_TEST

START_TEST (max)

{

   fail_unless(getSchwarzschild(DBL_MAX)>0., "maximum flottant positif");                    

}

END_TEST

START_TEST (min)

{

   fail_unless(getSchwarzschild(-DBL_MAX)==0., "minimum flottant négatif");

}

END_TEST

START_TEST (terre)

{

    fail_unless(getSchwarzschild(MTERRE)<=8.88e-03, "doit etre a peu pres egale a 8.87 millimetres");

   fail_unless(getSchwarzschild(MTERRE)>=8.86e-03, "doit etre a peu pres egale a 8.87 millimetres");

}

END_TEST

Suite * astro_suite()

{

    Suite *s = suite_create("Astro");

    TCase *tc_tests = tcase_create("Tests");

   tcase_add_test (tc_tests, non_zero);

   tcase_add_test (tc_tests, zero);

   tcase_add_test (tc_tests, max);

   tcase_add_test (tc_tests, min);

   tcase_add_test (tc_tests, terre);

   suite_add_tcase (s, tc_tests);

   return s;

}

int main()

{

   int erreurs = 0;

   Suite *s = astro_suite();

   SRunner *sr = srunner_create(s);

   srunner_run_all(sr, CK_NORMAL);

   erreurs = srunner_ntests_failed(sr);

   srunner_free(sr);

   return (erreurs == 0) ? EXIT_SUCCESS : EXIT_FAILURE;

}

2.4. Compilation et exécution des tests

L'arborescence du paquet devrait, à cette étape, ressembler à celle-ci :

$ du -a

4 ./tests/tests.c

4 ./tests/Makefile.am

12 ./tests

4 ./Makefile.am

4 ./configure.ac

4 ./src/astro.c

4 ./src/Makefile.am

4 ./src/astro.h

4 ./src/main.c

12 ./src/astro

32 ./src

136 ./autom4te.cache/output.0

16 ./autom4te.cache/traces.0

4 ./autom4te.cache/requests

160 ./autom4te.cache

0 ./README

0 ./AUTHORS

4 ./autoscan.log

0 ./NEWS

0 ./INSTALL

0 ./ChangeLog

220 .

Dans le répertoire racine du paquet, la commande aclocal va produire un aclocal.m4en examinant le fichier configure.ac et qui contiendra des macros pour la configuration.

$ aclocal

Ensuite, autoreconf va générer le fichier de configuration et les Makefile.in en utilisant, entre autres, automake et libtoolize.

$ autoreconf --install

configure.ac:14: installing `./compile'

Le répertoire racine du paquet contient à présent de nombreux ajouts, en particulier le script configure qui crée les Makefile standards :

$ ./configure

checking for a BSD-compatible install... /usr/bin/install -c

checking whether build environment is sane... yes

[...]

config.status: creating Makefile

config.status: creating src/Makefile

config.status: creating tests/Makefile

config.status: creating config.h

config.status: executing depfiles commands

config.status: executing libtool commands

À présent, lançons un premier make pour générer la bibliothèque astrolib, toujours depuis ce répertoire :

$ make

Le répertoire src doit à présent contenir une bibliothèque libastro.la

$ file src/libastro.la

src/libastro.la: libtool library file,

Il ne reste plus qu'à lancer les tests, par la commande make check

$ make check

[...]

Running suite(s): Astro

100%: Checks: 5, Failures: 0, Errors: 0

PASS: tests

=============

1 test passed

=============

Les résultats nous indiquent que les 5 tests unitaires ont été passés avec succès (100% de réussite), que la suite de test Astro est vérifiée (1 test passed). Plusieurs suites de tests peuvent être définies afin de disposer d'un éventail de jeux de tests et d'éviter de tous les rejouer. De plus, les résultats peuvent être exportés sous forme de journaux (srunner_set_log), de rapport au format XML (srunner_set_xml) ou au format Subunit. [7]

3. Couverture de code avec Gcov

Gcov est un programme de couverture de code associé au compilateur Gcc. Il permet de vérifier quelles instructions ont été exécutées, celles qui ne l'ont pas été, et celles qui ne pourront pas l'être (code inaccessible, ou code mort). Il peut également être utilisé de concert avec Gprof, pour détecter les parties de code qui requièrent le plus de temps processeur (man gcov). L'avantage d'utiliser Gcov avec Check, c'est qu'en ayant mis en place la structure autotools, l'essentiel est déjà prêt. Il suffit ensuite d'utiliser l'option coverage pour générer les informations de couverture de test.

3.1. Comment ça marche ?

L'option --coverage du compilateur Gcc, qui est synonyme de -fprofile-arcs et -ftest-coverage pour la compilation et -lgcov pour l'édition de lien, permet de générer les fichiers de données de couverture de code après exécutiondu programme. Après les tests effectués avec Check, l'exécutable de test produit un fichier .gcno (notes Gcov) et un fichier .gcda (data Gcov) pour chaque fichier compilé avec l'option -fprofile-arcs et utilisé durant le test (man gcc).

Avant de passer à la suite, si vous avez des objets compilés dans les étapes précédentes, faites un make clean pour les supprimer, car on aura besoin de les compiler avec d'autres options.

$ make clean

Pour compiler avec les options de couverture de code, il est possible d'utiliser la variable CFLAGS au moment de la compilation des sources, avec les options O0 (sans optimisation) et coverage (une autre façon aurait été de modifier le configure.ac ou, peu recommandé, de l'ajouter au Makefile.am) :

$ make CFLAGS="-O0 --coverage"

Et pour lancer les tests :

$ make CFLAGS="-O0 --coverage" check

Une fois les tests effectués avec la couverture de code, les fichiers Gcov sont générés dans le répertoire src (ou src/.lib). Pour lire ces données, on peut directement utiliser la commande gcov en se plaçant dans le répertoire src du paquet. Avec la version de Gcc (4.6) utilisée pour ces tests, les fichiers de données gcda et .gcno sont générés dans un sous-répertoire .lib (on trouve aussi des .gcno dans le src), aussi il est important de bien indiquer un .gcno se trouvant dans le même répertoire des gcda avec l'option -o (object directory).

La commande gcov pour obtenir les données de couverture de code du fichier astro.c utilisé par la bibliothèque libastro (en indiquant le .gcno pour lequel existe un .gcda correspondant) :

$ cd src

$ gcov -o .libs/libastro_la-astro.gcno astro.c

File 'astro.c'

Lines executed:100.00% of 5

astro.c:creating 'astro.c.gcov'

Un fichier texte astro.c.gcov est généré, contenant en première colonne le nombre de fois qu'une ligne a été exécutée durant les tests et dans la seconde le code source correspondant :

        -:    0:Source:astro.c

        -:    0:Graph:.libs/libastro_la-astro.gcno

        -:    0:Data:.libs/libastro_la-astro.gcda

        -:    0:Runs:6

        -:    0:Programs:1

        -:    1:#include "astro.h"

        -:    2:#include <math.h>

        -:    3:

        -:    4:

        8:    5:double getSchwarzschild(double masse)

        -:    6:{

        8:    7:    if(masse > 0){

        5:    8:        return 2 * CONSTANTE_G * masse / (pow( LIGHT_SPEED, 2));

        -:    9:    }else{

        3:   10:        return 0.;

        -:   11:    }

        -:   12:}

On s'aperçoit que le cas où la masse était négative ou nulle a été testé trois fois, et que toutes les lignes de code ont été testées (code couvert à 100%). Les lignes non exécutées auraient été indiquées par des caractères #####.

Après modifications, pour réinitialiser Gcov, faites un make clean pour effacer les objets et supprimez les fichiers .gcno et .gcda.

Pour finir, avec Lcov, nous allons générer un rapport Gcov au format HTML.

3.2. Rapport graphique avec Lcov

Lcov construit des rapports graphiques des résultats de couverture de code obtenus avec Gcov.

Ce rapport se génère en deux brèves étapes.

Première étape, génération d'un fichier rapport.info recensant les infos de tous les fichiers .gcda du répertoire src et de ses sous-répertoires :

$ cd src

$ lcov --directory . -c -o rapport.info

Capturing coverage data from .

Found gcov version: 4.6.3

Scanning . for .gcda files ...

Found 1 data files in .

Processing astro.gcda

Finished .info-file creation

Puis deuxième étape, création d'un rapport HTML basé sur ce fichier rapport.info vers un répertoire rapport avec l'outil genhtml de Lcov :

$ genhtml -o ../rapport -t "couverture de code des tests" rapport.info

Reading data file rapport.info

Found 1 entries.

Found common filename prefix "/home/user/astro/"

Writing .css and .png files.

Generating output.

Processing file astro/src/astro.c

Writing directory view page.

Overall coverage rate:

  lines......: 100.0% (4 of 4 lines)

  functions..: 100.0% (1 of 1 function)

  branches...: 100.0% (2 of 2 branches)

Il ne reste plus qu'à afficher le rapport dans un navigateur :

$ firefox ../rapport/index.html

Conclusion

Les tests unitaires, phase essentielle d'un projet de développement, permettent d'améliorer la qualité du logiciel, d'éviter de nombreux correctifs à l'utilisateur et sont réutilisables pour les tests de non-régression. Certaines normes et méthodes en font même un élément obligatoire, les tests unitaires devant couvrir tout ou partie du code.

Dans cet article, nous aurons expérimenté les tests unitaires avec le framework Check, en testant des unités de code au moyen d'assertions, et nous aurons également utilisé les autotools pour obtenir une structure de paquet standard. Il existe assez peu de documentation sur le framework Check, mais la commande info check ainsi que le site officiel sont assez bien fournis. Vous trouverez également des exemples de code dans le répertoire d'installation de Check.

Avec Gcov, nous avons obtenu le taux de couverture de code de ces tests pour, avec Lcov, les afficher dans un rapport graphique. Le taux de couverture de code est un critère important de qualité logicielle et de vérification de code.

Il existe de nombreux frameworks de tests unitaires, et cela pour la plupart des langages de programmation, comme Cunit pour le C, CppUnit pour le C++, Junit pour le Java, mais également PHPUnit pour PhP, PyUnit pour Python, Hunit pour Haskell, Test::Unit pour Ruby, Test::Simple et Test::More pour Perl. Après les avoir expérimentés à travers divers projets, les tests unitaires devraient également vous sembler absolument nécessaires et indispensables.

Références

[1] E. ITIÉ, Gestion des tests logiciels, DataPro, ENI, 2011

[2] B. HOMÈS, Les tests logiciels, Lavoisier, Hermes Science, 2011

[3] W. E. PERRY, Effective Methods for Software Testing, WILEY, 2000

[4] J.-F. PRADAT-PEYRE, J. PRINTZ, Pratique des tests logiciels, DUNOD, 2009

[5] WIKIPEDIA, DO-178B, http://fr.wikipedia.org/wiki/DO-178B, 2012

[6] WIKIPEDIA, Rayon de Schwarzschild, http://fr.wikipedia.org/wiki/Rayon_de_Schwarzschild, 2012

[7] Sourceforge, Check : A unit testing framework for C, http://check.sourceforge.net, 2012