Test Unitaire - Wikipédia

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 10

Test unitaire

Pour les articles homonymes, voir Test.

En programmation informatique, le test unitaire (ou « T.U. », ou « U.T. » en anglais) est une
procédure permettant de vérifier le bon fonctionnement d'une partie précise d'un logiciel ou d'une
portion d'un programme (appelée « unité » ou « module »).

Dans les applications non critiques, l'écriture des tests unitaires a longtemps été considérée
comme une tâche secondaire. Cependant, les méthodes Extreme programming (XP) ou Test
Driven Development (TDD) ont remis les tests unitaires, appelés « tests du programmeur », au
centre de l'activité de programmation.

Origine et histoire

Les test unitaires, en tant que principe de tester séparément des parties plus élémentaires d'un
logiciel complexe, remonte aux débuts de l'ingéniérie logicielle. En Juin 1956, H.D. Benington
présente en effet le projet SAGE au symposium sur les méthodes de programmation avancée
organisé par la marine américaine. L'approche utilisée prévoyait à l'issue de la phase de codage
une étape de "tests de paramètres" pour valider la conformité des sous-programmes et
composants à leur spécifications, avant de procéder à un "test d'assemblage" de ces
composants[1],[2].

En 1964, une approche similaire est décrite pour les logiciels du programme Mercury : les unités
individuelles développées par différentes organisations étaient soumises à des "tests unitaires"
avant d'être intégrées entre elles. En 1969, les methodologies de tests sont structurées encore
davantage, avec des tests unitaires, des tests de composants, et des tests d'intégration, dans le
but de valider des parties élémentaires du logiciel séparément, puis de vérifier le bon
fonctionnement des assemblages progressif en blocs plus larges[3]. Des normes publiques
adoptées à la fin des années 60, telles que les standards militaires MIL-STD-483[4] et MIL-STD-
490 de l'armée américaine contribuent à une large reconnaissance et adoption des tests
unitaires au sein de gros projets.

Les tests unitaires étaient alors interactifs[2], ou automatisés[5], utilisant soit des tests
programmés ou des outils de capture et répétition automatisés. En 1994 Kent Beck décrit un
environnement cadre de test pour le langage Smalltalk, qui deviendra SUnit[6] par la suite[7],[8]. En
1997, Kent Beck rencontre Erich Gamma avec lequel il crée JUnit qui, par sa popularité,
entraînera la création de nombreux frameworks de tests unitaires, cet ensemble se nomme
xUnit[9].
À la même époque, ATTOL Unit test est développé, puis utilisé par Sextant Avionique en 1998[10]

Utilité[11]

On écrit un test pour confronter une réalisation à sa spécification. Le test définit un critère d'arrêt
(état ou sorties à l'issue de l'exécution) et permet de statuer sur le succès ou sur l'échec d'une
vérification. Grâce à la spécification, on est en mesure de faire correspondre un état d'entrée
donné à un résultat ou à une sortie. Le test permet de vérifier que la relation d'entrée / sortie
donnée par la spécification est bel et bien réalisée.

Trouver les erreurs rapidement

La méthode XP préconise d'écrire les tests en même temps, ou même avant la fonction à tester
(Test Driven Development). Ceci permet de définir précisément l'interface du module à
développer. Les tests sont exécutés durant tout le développement, permettant de visualiser si le
code fraîchement écrit correspond au besoin.

Sécuriser la maintenance

Lors d'une modification d'un programme, les tests unitaires signalent les éventuelles
régressions. En effet, certains tests peuvent échouer à la suite d'une modification, il faut donc
soit réécrire le test pour le faire correspondre aux nouvelles attentes, soit corriger l'erreur se
situant dans le code.

Documenter le code

Les tests unitaires peuvent servir de complément à l'API, il est très utile de lire les tests pour
comprendre comment s'utilise une méthode. De plus, il est possible que la documentation ne
soit plus à jour, mais les tests eux correspondent à la réalité de l'application.

Fonctionnement

On définit généralement 4 phases dans l'exécution d'un test unitaire :

1. Initialisation (fonction setUp ) : définition d'un environnement de test complètement


reproductible (une fixture).

2. Exercice : le module à tester est exécuté.


3. Vérification (utilisation de fonctions assert ) : comparaison des résultats obtenus avec
un vecteur de résultat défini. Ces tests définissent le résultat du test : SUCCÈS ( SUCCESS )
ou ÉCHEC ( FAILURE ). On peut également définir d'autres résultats comme ÉVITÉ
( SKIPPED ).

4. Désactivation (fonction tearDown ) : désinstallation des fixtures pour retrouver l'état initial
du système, dans le but de ne pas polluer les tests suivants. Tous les tests doivent être
indépendants et reproductibles unitairement (quand exécutés seuls).

Utilisation

Il s'agit pour le programmeur de tester un module, indépendamment du reste du programme,


ceci afin de s'assurer qu'il réponde aux spécifications fonctionnelles et qu'il fonctionne
correctement en toutes circonstances. Cette vérification est considérée comme essentielle, en
particulier dans les applications critiques. Elle s'accompagne couramment d'une vérification de
la couverture de code (évaluation de la couverture structurelle), qui consiste à s'assurer que
l'ensemble des tests conduit à exécuter l'ensemble (ou une fraction déterminée) des instructions
présentes dans le code.

L'ensemble des tests unitaires doit être rejoué après une modification du code afin de vérifier
qu'il n'y a pas de régressions (l'apparition de nouveaux dysfonctionnements). L'emploi d'une
« stratégie de test » particulière peut limiter les tests à rejouer, par exemple : une analyse
d'impact des modifications, corrélée à une preuve d'indépendance des modules, permet de cibler
les cas de test unitaire à rejouer.

Commencer par les tests

Un test doit correspondre aux spécifications de l'application, il faut donc écrire les tests en
premier puis les faire passer par la suite plutôt que d'écrire le code avant et de prendre le risque
d'être influencé par celui-ci lors de la rédaction des tests[12]. Bob Martin[13], grand défenseur de la
méthode TDD, propose un modèle simple pour l'écriture des tests unitaires :

1. Écrire une fonction de test qui doit obtenir un résultat défini dans les spécifications. Ce
code appelant un code qui n'existe pas encore, celui-ci doit échouer. Ceci a pour but de
définir une fonction qui teste « quelque chose ».

2. Écrire le code (le minimum de « quelque chose ») pour faire réussir le test.

3. Une fois le test en succès, rajouter un autre test pour obtenir un résultat légèrement
différent, en faisant varier les entrées par exemple. Ce nouveau test fera faillir le code
principal.

4. Modifier le code principal pour faire réussir les tests.


5. Recommencer, en éliminant et refactorisant les éventuelles redondances dans le code des
tests. On refactorise en même temps le code principal que le code des tests.

6. Un test unitaire doit tester une caractéristique et une seule. On ne définit pas un « scénario »
de test complexe dans un test unitaire.

7. Il est déconseillé de tester les détails d'implémentation telles que les fonctions privées
d'une classe, on se concentrera à tester les fonctions publiques, c'est-à-dire les interfaces
avec lesquelles les acteurs extérieurs interagissent. Ainsi, on découple les tests de
l'implémentation et on se concentre sur la vérification du comportement attendu tout en
gardant une flexibilité sur la manière d'arriver au résultat souhaité.

Utiliser des mocks

Les mocks sont des objets permettant de simuler un objet réel de façon contrôlée. Dans certains
cas, l'utilisation de mock est primordiale, pour un gain de temps de couverture de code, et de
fiabilité des tests[14]

pour simuler une base de données, un service web, etc., les interactions entre l'application et
ces outils prennent du temps, l'utilisation de mock pour simuler leurs fonctionnements peut
être un gain de temps considérable ;

certains cas d'erreurs sont très difficile à reproduire, l'utilisation de mock permet ici de simuler
une erreur pour pouvoir traiter ce cas et donc améliorer la couverture de code, par exemple le
catch d'une exception ;

sans l'utilisation de mock, le test peut retourner une erreur ne provenant pas du code qui est
testé (par exemple une base de données).

Cependant, une utilisation abusive de mock peut avoir l'effet inverse, notamment allonger le
temps d'exécution des tests, rendre les tests compliqués à comprendre et à maintenir.

Génération

La plupart des frameworks de la famille xUnit permettent la génération des classes de test
unitaire. Cependant ces frameworks ne fournissent que le squelette des classes. Les tests
devront donc être écrits par le développeur.

La génération de tests unitaires est un sujet important pour les chercheurs et plusieurs
conférences s'intéressent à cette problématique, telles que International Symposium on
Software Testing and Analysis (ISSTA), International Conference on Software Engineering (ICSE)
et Automated Software Engineering (ASE).
Correction de test unitaire

Lors d'une modification dans le code d'un programme, il se peut que certains tests ne passent
plus ; dans ce cas, le développeur doit déterminer si cela vient du code en lui-même ou du test :
si cela vient du test, le développeur doit modifier son test car la suppression de celui-ci
entraînerait une augmentation des chances de régression du programme. Certains chercheurs
ont développé des outils pour résoudre ce problème.

ReAssert[15] est un outil suggérant des réparations pour un test qui échoue, il analyse les tests à
modifier et suggère des changements au développeur, si cette suggestion convient au
développeur, il peut effectuer le changement en cliquant sur un bouton.

Test unitaire paramétrable

Les tests unitaires paramétrables sont des tests unitaires qui prennent des paramètres. Ils
peuvent ensuite utiliser des outils comme QuickCheck pour générer des paramètres. Ces tests
sont supportés par JUnit, TestNG et NUnit.

En s'appuyant sur des cas concrets d'entrée et sortie, la génération d'Oracle et sur la couverture
de test pour minimiser les cas, des chercheurs ont réussi à générer des tests unitaires
paramétrables[16]. Les résultats de cette méthode sont prometteurs.

Environnements de développement

Il existe une multitude de cadriciels (framework) permettant de réaliser facilement des tests
unitaires. Il en existe dans les principaux langages de programmation. Par exemple
[17]
Test::More pour le Perl.

Frameworks xUnit

Le terme générique « xUnit » désigne un outil permettant de réaliser des tests unitaires dans un
langage donné (dont l'initiale remplace « x » le plus souvent).

AUnit[18] pour Ada ;

ASUnit[19] pour ActionScript ;

Cppunit[20] pour C++ ;

CUnit[21] pour C ;

DUnit pour Delphi ;


FLEXunit pour Adobe Flex ;

Google Test[22] et Boost Test[23] pour C++ ;

HUnit[24] pour Haskell ;

JSUnit[25], QUnit[26], Unit.js[27] et Jest[28] pour JavaScript ;

JUnit[29] et TestNG[30] pour Java ;

NUnit[31] pour .NET ;

Microsoft Unit Test[32] pour .NET ;

xUnit[33] pour .NET ;

NUnitASP[34] pour ASP.NET (support interrompu depuis le 31 janvier 2008) ;

OUnit[35] pour OCaml ;

OCunit pour Objective C ;

PBUnit pour PowerBuilder ;

PHPUnit[36], SimpleTest[37] et Atoum[38] pour PHP ;

plunit pour Prolog ;

utPLSQL[39] pour PL/SQL ;

Unittest et PyUnit pour Python ;

Tape pour JavaScript ;

Test::Unit pour Ruby ;

Test::More pour Perl ;

Typemock pour .NET, C++, C#. Avec Typemock vous pouvez travailler sur legacy code aussi.

SUnit[40] pour Smalltalk ;

RPGUnit[41] pour RPG ;

ScalaTest pour Scala

SASUnit[42] pour SAS.

Outils commerciaux

Divers outils permettent l'automatisation des tests unitaires :

Le module TBrun de la suite d'outils LDRA ;

Tessy (distribution : Hitex Development Tools/Allemagne).


Ponicode, génération de tests unitaires en Javascript[43].

Articles connexes

Cycle en V

Test

Extreme programming

Test Driven Development

Notes

1. (en) Benington, Herbert D., « Production of large computer programs », Proceedings of the
Symposium on Advanced Programming Methods for Digital Computers, Washington, D.C.,
June 28-29, 1956, Office of Naval Research, Department of the Navy,‎1956, p. 15-28

2. H. D. Benington, « Production of large computer programs », Proceedings of the 9th


international conference on Software Engineering, IEEE Computer Society Press, iCSE '87,‎
1er mars 1987, p. 299–310 (ISBN 978-0-89791-216-7,
DOI 10.5555/41765.41799 (https://dx.doi.org/10.5555/41765.41799) , lire en ligne (https://dl.acm.org/doi/1

0.5555/41765.41799) [archive], consulté le 3 avril 2024)

3. Norman A. Zimmerman, « System integration as a programming function », Proceedings of


the 1969 24th national conference, Association for Computing Machinery, aCM '69,‎
26 août 1969, p. 459–467 (ISBN 978-1-4503-7493-4,
DOI 10.1145/800195.805951 (https://dx.doi.org/10.1145/800195.805951) , lire en ligne (https://dl.acm.org/

doi/10.1145/800195.805951) [archive], consulté le 3 avril 2024)

4. (en) Gouvernement des Etats Unis d'Amérique, Département de la Défence, MIL-STD-483


Military standard: configuration management practices for systems, equipment, munitions,
and computer programs, 31 décembre 1970, Section 3.4.7.2. "The contractor shall then code
and test software Units, and enter the source and object code, and associated listings of
each successfully tested Unit into the Developmental Configuration"

5. (en) Michael F. Tighe, « The value of a proper software quality assurance methodology »,
ACM SIGMETRICS Performance Evaluation Review, vol. 7, nos 3-4,‎novembre 1978, p. 165–
172 (ISSN 0163-5999 (https://portal.issn.org/resource/issn/0163-5999) ,
DOI 10.1145/1007775.811118 (https://dx.doi.org/10.1145/1007775.811118) , lire en ligne (https://dl.acm.or

g/doi/10.1145/1007775.811118) [archive], consulté le 3 avril 2024)

6. Camp Smalltalk SUnit (http://sunit.sourceforge.net/) [archive]


7. Simple Smalltalk Testing:With Patterns (http://www.xprogramming.com/testfram.ht
m) [archive], in Smalltalk Report octobre 1994, Kent Beck

8. (en) Ward Cunningham, « Testing Framework (http://wiki.c2.com/?TestingFramewor


k) [archive] » , sur http://wiki.c2.com [archive]

9. Xunit, Martin Fowler (http://www.martinfowler.com/bliki/Xunit.html) [archive]

10. GNU Based Compilation System for Space Embedded Applications, Blondin, J. P. &
Martignano, M., DASIA 98 - Data Systems in Aerospace, Proceedings of the conference held
25-28 May, 1998 in Athens, Greece, Edited by B. Kaldeich-Schü.rmann. ESA SP-422. Paris:
European Space Agency, 1998., p.137, "1998ESASP.422..137B", page 138
http://adsbit.harvard.edu//full/1998ESASP.422..137B/0000138.000.html [archive]

11. 10 Reasons to Write Unit Tests (http://blog.typemock.com/2011/11/28/10-reasons-to-write


-unit-tests) [archive]

12. Unit Testing Best Practices, Roy Osherove.

13. Test First, bob Martin (http://blog.8thlight.com/uncle-bob/2013/09/23/Test-first.htm


l) [archive].

14. Robert Martin, When to Mock.

15. (en) Brett Daniel, Danny Dig, Tihomir Gvero, Vilas Jagannath, Johnston Jiaa, Damion
Mitchell, Jurand Nogiec, Shin Hwei Tan et Darko Marinov, « ReAssert: a tool for repairing
broken unit tests », ICSE,‎2011 (lire en ligne (http://dl.acm.org/citation.cfm?doid=1985793.198597
8) [archive]).

16. (en) Gordon Fraser et Andreas Zeller, « Generating Parameterized Unit Tests », ISSTA,‎2011
(lire en ligne (http://dl.acm.org/citation.cfm?doid=2001420.2001464) [archive]).

17. Test::More sur CPAN (https://metacpan.org/module/Test::More) [archive], entre autres


modules de tests (https://metacpan.org/search?q=Test) [archive]. Voir aussi les articles de
l'association des mongueurs de Perl dans Linux Magazine France disponibles sur
http://articles.mongueurs.net/magazines [archive]

18. AUnit (https://libre.adacore.com/aunit/main.html) [archive]

19. AsUnit (http://www.asunit.org/) [archive]

20. CppUnit (http://cppunit.sourceforge.net/) [archive] et en version 2 (https://launchpad.net/c


ppunit2) [archive]

21. CUnit (http://cunit.sourceforge.net/) [archive]

22. GoogleTest (https://code.google.com/p/googletest/) [archive]

23. Boost.Test (http://www.boost.org/doc/libs/release/libs/test/index.html) [archive]


24. HUnit (http://hunit.sourceforge.net/) [archive]

25. JsUnit (http://www.jsunit.net/) [archive]

26. http://qunitjs.com [archive] Unit testing for Javascript made by the jQuery Foundation

27. (en) Unit JS (http://unitjs.com) [archive] : « Unit testing framework for Javascript ».

28. (en) « Jest · 🃏 Delightful JavaScript Testing (https://jestjs.io/) [archive] », sur jestjs.io
(consulté le 2 mars 2020)

29. Welcome to The New JUnit.org! | JUnit.org (http://junit.org/) [archive].

30. (en) « TestNG Documentation (http://testng.org/) [archive] », sur testng.org (consulté le


21 mai 2024).

31. NUnit - Home (http://www.nunit.org/) [archive]

32. (en-US) erickson-doug, « Writing Unit Tests for the .NET Framework with the Microsoft Unit
Test Framework for Managed Code - Visual Studio (https://docs.microsoft.com/fr-fr/visual
studio/test/writing-unit-tests-for-the-dotnet-framework-with-the-microsoft-unit-test-framew
ork-for-managed-code?view=vs-2015) [archive] », sur docs.microsoft.com (consulté le
4 septembre 2018)

33. (en) « Home > xUnit.net (https://xunit.github.io/) [archive] », sur xunit.github.io (consulté le
4 septembre 2018)

34. NUnitAsp - ASP.NET unit testing (http://nunitasp.sourceforge.net/) [archive]

35. OUnit (http://ounit.forge.ocamlcore.org/) [archive]

36. PHPUnit - Trac (https://www.phpunit.de/) [archive]

37. SimpleTest - Unit Testing for PHP (http://www.simpletest.org/) [archive]

38. Atoum (http://www.atoum.org/) [archive]

39. utPLSQL (http://utplsql.sourceforge.net/) [archive]

40. Simple Smalltalk Testing: With Patterns (http://www.xprogramming.com/testfram.ht


m) [archive]

41. http://rpgunit.sourceforge.net/ [archive]

42. (en) « SASUnit (https://sourceforge.net/projects/sasunit/) [archive] », sur SourceForge

(consulté le 24 février 2020)

43. (en) « Ponicode - Quick and easy Javascript unit testing (https://ponicode.com/) [archive] »,
sur ponicode.com (consulté le 23 juin 2020)

Portail de l’informatique

Vous aimerez peut-être aussi