Introduction au test logiciel/Intégration dans le processus de développement

Un livre de Wikilivres.

Jusqu'ici, nous avons vu comment vous pouviez développer dans votre coin des tests portant sur le code que vous écrivez. Cependant, le développement d'un logiciel est un processus plus global : voyons comment les tests s'intègre avec les autres tâches à effectuer et comment on peut travailler en équipe.

Développer avec les tests[modifier | modifier le wikicode]

Bien que ce ne soit pas systématique, la pratique courante est que le code et les tests sont écrits par la même personne.

Écrire des tests prend du temps qu'on pourrait passer à écrire du code apportant de nouvelles fonctionnalités. Cela peut paraître frustrant, mais il faut renoncer à la course à la fonctionnalité pour préférer avancer plus lentement mais plus sûrement. En particulier, on est tenté de négliger l'écriture des tests après plusieurs semaines passées sur un projet, surtout en phase de bouclage où « on a plus le temps pour ça ». Appliquer une démarche de tests rigoureuse tout au long du projet permet de modifier le code aussi sereinement en fin de projet qu'au début (les tests assurant la non-régression). La solution réside dans l'équilibre, c'est en fonction des contraintes du projet et du sentiment de maîtrise des développeurs qu'il convient de placer le curseur entre deux extrêmes qu'il faut éviter : « pas de temps pour les tests » et « 100 % de couverture, peu importe le temps que ça prendra ! ».

Après plusieurs mois de pratique, un développeur peut se demander « À quoi bon écrire des tests, on ne trouve jamais de bogues ». On peut le comprendre étant donné qu'après la mise en place d'une démarche des tests, les bogues se raréfient : on peut alors avoir l'impression que les tests ne servent à rien. Ce serait se tromper. Pour s'en convaincre, il suffit d'abandonner les tests pour voir ressurgir des bogues à retardement.

Les tests et la gestion de version[modifier | modifier le wikicode]

Si vous travaillez à plusieurs sur le développement du projet, vous utilisez probablement un outil de gestion de version de code-source (comme CVS, Git ou Subversion). Vous pouvez l'utiliser pour stocker vos classes de tests aux côtés des classes.

Vous pouvez adopter des règles strictes :

  • Ne jamais envoyer une classe qui n'est pas accompagnée d'un test
  • Toujours faire passer les tests lorsqu'on récupère un projet
  • Avant de faire un commit :
    1. Relancer tous les tests
    2. Mettre à jour le code
    3. Repasser tous les tests
    4. Faire le commit

Le développement piloté par les tests[modifier | modifier le wikicode]

Le développement piloté par les tests (ou « Test-Driven Development » ou « TDD ») est une pratique souvent utilisée dans les méthodes agiles (on trouve son origine dans l'extreme programming). Elle consiste à développer l'application selon le cycle suivant :

  1. Écrire les tests
  2. Vérifier que ceux-ci ne passent pas
  3. Écrire le code manquant
  4. Vérifier que le test passe
  5. Remanier le code

1. Écrire les tests[modifier | modifier le wikicode]

Dans le développement piloté par les tests, les tests sont écrit avant le code. Il faut donc commencer par écrire un test ou un petit ensemble de tests qui représente les nouvelles fonctionnalités qu'on va implémenter durant le cycle.

Il faut pour cela se baser sur la spécification, les cas d'utilisation ou les user stories. Écrire les tests d'abord permet au développeur de voir vraiment le comportement qui est attendu avant de toucher au code.

2. Vérifier que les nouveaux tests échouent[modifier | modifier le wikicode]

Il est important de lancer les tests pour s'assurer que les autres passent toujours et que les nouveaux tests ne passe pas. Dans le cas contraire, deux possibilités :

  • Le test n'est pas bon
  • La fonctionnalité est déjà implémentée. Cela peut arriver étant donné qu'un développeur zélé peut, lorsqu'il touche une partie du code, ajouter dans la foulée un petit peu de plus de fonctionnalité que prévu.

Toutefois, si ce dernier cas se présente plusieurs fois, il faut se poser des questions sur la gestion du projet. Les tâches ont-elles bien été réparties ?

3. Écrire le code[modifier | modifier le wikicode]

Il est important d'essayer de n'écrire strictement que le code nécessaire au passage du test, pas plus. Vous pouvez relancer le test écrit à l'étape 1 autant de fois que nécessaire. Peu importe si le code n'est pas élégant pour l'instant tant qu'il permet de passer le test.

4. Vérifier que tous les tests passent[modifier | modifier le wikicode]

C'est le moment de vérifier que tous les tests passent, ceci afin de vérifier qu'avec les modifications faites on n'a pas créé de régressions dans le code.

5. Remanier le code[modifier | modifier le wikicode]

Enfin, refactorisez le code pour améliorer la conception tout en vérifiant que les tests passent toujours.

Intégrer les tests à la construction automatique du projet[modifier | modifier le wikicode]

Avec Ant[modifier | modifier le wikicode]

Si vous utilisez Ant pour construire vos projets, il existe la tâche junit. Attention, elle dépend des fichiers junit.jar et ant-junit.jar qu'il faut télécharger et indiquer dans le fichier build.xml. Référez vous à la documentation de la tâche junit dans la documentation officielle de Ant.

Avec Maven[modifier | modifier le wikicode]

Si vous utilisez maven pour construire et gérer les dépendances de votre projet. Vous pouvez lui demander de faire passer tous les tests.

mvn test

Maven intègre une convention pour placer les tests dans l'arborescence du projet. Vous pouvez déclarer JUnit et vos autres outils comme des dépendances. Vous pouvez également intégrer à la génération du site, la génération et la publication des rapports sur le respect de conventions et la couverture.

Gardez l'essentiel des tests rapidement exécutables[modifier | modifier le wikicode]

Quoi qu'il en soit, la construction du projet doit rester légère, et dérouler les tests ne doit pas prendre plus de quelques minutes. Le risque, en laissant le temps de construction s'allonger indéfiniment au fur et à mesure que les tests s'accumulent, est de lasser les développeurs qui seront tentés de sauter la phase de test de la construction.

Une bonne pratique consiste à laisser les tests unitaires dans la construction du projet et à ignorer les tests d'intégration dans le build par défaut. Une petite option (un profil Maven) permettant d'activer le passage des tests d'intégration. Le serveur d'intégration, lui, pourra construire systématiquement en repassant tous les tests.

Profitez des ressources du serveur d'intégration continue[modifier | modifier le wikicode]

Sonar donne une vue d'ensemble de l'évolution des métriques d'un projet

Si vous faites de l'intégration continue, vous utilisez un système de gestion de version et vous avez sûrement un serveur chargé de construire régulièrement le projet. Vous pouvez faire en sorte que chaque construction rejoue l'ensemble des tests pour vérifier que tout va bien. Cette construction automatique régulière peut donner lieu à la génération de rapports. Votre serveur d'intégration peut donc vous permettre de suivre l'évolution des métriques et de la complexité du projet.

Coupler le serveur d'intégration continu avec un outils de panneau de contrôle tel que Sonar vous permettra de suivre l'évolution du succès des tests et de la couverture du code en fonction du temps et de l'évolution de la complexité de l'application. Sonar permet de voir où se trouvent les portions de codes les moins testées.

Rapprocher les tests de l'utilisateur[modifier | modifier le wikicode]

Si les méthodes agiles recommandent les tests, elle recommandent également d'intégrer l'utilisateur au processus de développement afin que les réalisations des développeurs collent au plus près des véritables attentes qu'on peut avoir du logiciel.

Les tests sont d'abord une discipline technique mais nous allons voir que par différentes façon, nous pouvons rapprocher ces travaux des utilisateurs. Les trois approches suivantes tentent de mêler les tests avec la documentation utilisateur (le cas doctest) ou avec les spécifications du logiciel (Fit et BDD). L'objectif est d'avoir des tests écrit dans un langage compréhensible par l'utilisateur, voire de permettre à l'utilisateur d'écrire les tests lui-même sous forme de tableau de valeurs dans un tableur (Fit) ou en langage simili-naturel (BDD). Idéalement, ces technologies permettrait de confronter l'implémentation du logiciel aux spécifications attendues, décrites en langue naturelle : on peut parler de spécification exécutable (anglais executable spec).

Mêler tests et documentation, l'approche doctest[modifier | modifier le wikicode]

doctest est un outil livré avec Python qui permet, dans une documentation au format texte brut ou rST, d'ajouter des lignes qui permettent de vérifier ce qui vient d'être dit. L'exemple suivant montre un fichier texte d'exemple, il pourrait s'agir d'un fichier README.txt.

======================
Demonstration doctests
======================

This is just an example of what a README text looks like that can be used with
the doctest.DocFileSuite() function from Python's doctest module.

Normally, the README file would explain the API of the module, like this:

   >>> a = 1
   >>> b = 2
   >>> a + b
   3

Notice, that we just demonstrated how to add two numbers in Python, and 
what the result will look like.

En lisant ce fichier, doctest va interpréter les lignes préfixées par >>> et vérifier que ce qui est retourné par l'évaluation de l'expression correspond à ce qui est écrit (ici, doctest va vérifier que l'évaluation de a + b renvoie bien 3).

Des tests orientés données, l'approche Fit[modifier | modifier le wikicode]

Ward Cunningham propose dans son outil « fit » de rédiger les tests de validation dans un document, sans code. Son outil comprend un lanceur de test mais aussi un wiki embarqué, accessible via une interface Web. Dans ce wiki, les utilisateurs peuvent entrer, dans des tableaux, les jeux de données à fournir en entrée ainsi que les résultats attendus en sortie. Une autre possibilité, donnée aux utilisateurs, est d'entrer les jeux de données dans un tableur.

Java
Fit, FitNesse (avec trinidad), Concordion
PHP
phpfit

Des tests fonctionnels en phase avec les attentes de l'utilisateur, l'approche BDD[modifier | modifier le wikicode]

C'est en essayant d'enseigner l'approche TDD que Dan North s'est rendu compte que la plupart des développeurs acceptent volontiers d'écrire les tests avant le code mais se contentent de percevoir cette technique comme une façon de tester en même temps qu'on développe, sans percevoir ce qu'il s'agit en fait d'une méthode de développement. Pour faciliter cette compréhension de TDD, Dan North a étendu les notions de bases pour former Behavior Driven Development, une méthode sensée apporter aux développeurs tous les bénéfices d'une véritable approche de TDD.

Des tests bien nommés[modifier | modifier le wikicode]

Notion de « Comportement »[modifier | modifier le wikicode]

Les attentes utilisateurs sont aussi des comportements[modifier | modifier le wikicode]

Frameworks de BDD[modifier | modifier le wikicode]

Groovy
GSpec, Spock, easyb
Java
Cucumber-JVM, un port officiel de Cucumber pour les différents langages de la JVM, Instinct, JBee, JBehave, JDave, Robot Framework, Narrative
JavaScript
Jasmine
PHP
behat
Python
Freshen, Lettuce, Pyccuracy, Pyhistorian, PyCukes
Ruby
RSpec, Cucumber
Scala
ScalaTest, specs

Pour aller plus loin[modifier | modifier le wikicode]

Tests de non-régression[modifier | modifier le wikicode]

Il s'agit de tests qui visent à assurer la non-régression d'une application. C'est à dire qu'une modification apportée à l'application ne rend pas erronés les comportements d'une application qui fonctionnaient avant la modification.

« Beta test »[modifier | modifier le wikicode]

Le beta-test consiste à fournir une version quasi-finale de l'application (dite « version Beta ») à un large échantillon d'utilisateurs finaux. Ceci afin qu'ils rapportent les derniers bogues résiduels ou dans le cas d'une interface graphique, quelques améliorations ergonomique. La version livrée est estampillée « Beta » afin que les utilisateurs soient conscient qu'il ne s'agit pas le version finale et que le version présentée peut encore contenir des erreurs.

On parle de bêta ouverte ou de bêta fermée selon que cette version du logicielle soit accessible à tous les utilisateurs potentiels ou seulement à un groupe restreint.