Tests Unitaires

En anglais Unit Test => test de chaque composant séparément.

Never in the field of software development was so much owed by so many to so few lines of code Martin Fowler

Pour assurer la fiabilité d'une application, il est nécessaire que chaque composant soit contrôlé par un ensemble de tests qui en vérifie le bon fonctionnement, indépendamment de l'usage de ce composant dans une application spécifique. L'existence même de ces tests permettra d'être audacieux et de faire évoluer l'application. Cette manière de faire impose d'écrire simultanément le composant et son jeu de test. Compte-tenu des délais toujours trop courts au goût des développeurs et trop longs pour les clients, il est nécessaire de disposer d'une structure (Framework) simple et efficace.

Les Tests Unitaires ne sont pas :

  • Exécutés sous contrôle d'un opérateur humain. Ils doivent pouvoir être lancés pendant la pause café ou se dérouler la nuit. Ils se déroulent sans poser de questions à un être humain.
  • Des tests exécutés sous contrôle d'un Automate simulant les actions de l'utilisateur.
  • Coûteux. Ils ne demandent ni outils, ni personnel supplémentaire.
  • Compliqués. Le code doit être une procédure séquentielle.
  • Couplés avec le monde extérieur. Ils ne dépendent que de l'Unité testée et des fichiers de données éventuellement nécessaires.

Les Tests Unitaires sont :

  • Des méthodes écrites de manière à pouvoir être déroulés de manière automatique
  • Chaque test doit vérifier un point important du code. Le but n'est pas de fournir un volume de code de test en vérifiant le code trivial, mais de garantir le bon fonctionnement du module.
  • Chaque test va demander un service à l'Unité testée (module, classe, algorithme, ..) puis vérifier que le service a été rendu (valeur rendue par la fonction, contenu d'un fichier modifié, ..).
  • Chaque test va rendre un résultat booléen : Réussi/Raté.
  • Réunis en ensembles (TestCase) et déroulés par un Cadre de Test (Testing Framework).

Cadre de Test

J'utilise des Cadre de Test issus du modèle xUnit simple et élégant défini par Kent Beck et Erich Gamma.

Il existe des implémentations pour Smalltalk, Java, .NET et une foultitude d'autres langages que je ne parle pas.

Each is the de facto standard unit testing framework for its respective language.

PyUnit supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework.

Chaque module doit disposer d'un jeu de Tests Unitaires. Ce jeu :

  • Est écrit en même temps ou avant que le module lui-même. Car le fait que le module doive être testé influe sur sa conception. Il est typiquement impossible d'écrire de vrais tests Unitaires pour un module qui est trop fortement couplé avec le reste du système, qui emploie des variables globales à profusion, ..
  • Doit pouvoir être lancé séparément des autres jeux, de manière à vérifier rapidement le code au fur et à mesure de l'écriture du module.
  • Doit passer à 100 % avant que l'on intègre le module dans l'application.

Lors de l'intégration d'un nouveau module au Prototype, et avant de livrer l'application, les développeurs lancent l'exécution de tous les Tests Unitaires, pas simplement ceux du module modifié, sur la machine d'intégration. Les tests doivent passer à 100 %. Si un test ne passe pas, le problème vient certainement du code modifié (parfois parce que l'on utilise un service de manière différente), parce que le jeu de Tests passait à 100 % avant les modifications.

Bien évidemment il arrive que les tests laissent passer une anomalie (bug), qui sera découverte par un utilisateur. Dans ce cas, les développeurs doivent commencer par modifier (en général ajouter un Test Unitaire) qui signale l'anomalie. C'est alors et seulement alors qu'ils peuvent corriger l'anomalie. De cette manière ce problème, ou un autre problème similaire ne se produira plus chez le client.


Quelques exemples en Python :


Quelques exemples en C++ :

En cours de rédaction