SPIP-Contrib

SPIP-Contrib

عربي | Deutsch | English | Español | français | italiano | Nederlands

286 Plugins, 197 contribs sur SPIP-Zone, 235 visiteurs en ce moment

Accueil > Outils pour plugins > Tests Unitaires > Les tests unitaires

Les tests unitaires

Pour un code plus solide vis à vis des évolutions

6 décembre 2008 – par Matthieu Marcillaud – commentaires

5 votes

Ecrire des « tests unitaires » est un moyen de s’assurer à chaque évolution d’un logiciel que la série de tests fonctionne toujours. On peut ainsi être sûr que des bugs ne sont pas revenus, et que le programme se comporte toujours comme attendu.

Test unitaire et programmation extrème dans SPIP

SPIP, assez récemment, poussé par Fil, s’était mis à écrire des tests unitaires. Un script passe en revue et lance tous les tests, et le nombre d’erreur, de réussite s’affiche alors.

Un article paru sur SPIP Blog parlait même à l’époque de « programmation extrème » [1] bien que ce concept ne s’intéresse pas qu’aux simples tests unitaires [2].

D’autres méthodes de programmation

Moins connu que l’extrème programming, la méthode La Rache, conçue par Iilar est souvent employée, bien que peu citée. C’est une méthode fonctionnelle et empirique qui fait et a fait ses preuves. Elle a de nombreux adeptes et est très bien décrite sur le site de référence [3].

Revenons donc aux tests unitaires.

Le test avant le code

En XP (Extreme Progamming), on écrit souvent les tests avant de coder les méthodes. On commence donc par dire « voilà ce que je souhaite faire » (le test pour l’instant echoue), puis on s’arrange à coder la méthode pour que le test se mette à fonctionner.

Au fur et a mesure de l’avancement, les tests deviennent de plus en plus nombreux, et l’introduction d’un bug est aussitôt repéré : un test échoue alors. Par conséquent, reprendre du code, le remodeler, devient plus facile, puisqu’on sait par avance que les tests nous diront si l’on obtient le résultat escompté.

La librairie « simpleTest »

Simple Test est une librairie PHP (et même un ensemble de librairies) qui permet de produire facilement des tests unitaires. Elle est facilement extensible pour d’autres projets.

Simple Test dispose d’un certain nombre de fonctions de tests de base, appelés « assertions » pour valider les codes. Dans Simple Test, chaque fonction commençant par ’test’ (on parle souvent de ’méthode’ dans la cas d’une classe php) d’une classe héritée de l’objet ’UnitTestCase’ devient un jeu de test potentiel.

Voici un exemple pour mieux comprendre l’écriture des tests :

  1. function testChaineHelloWorld() {
  2. $hw = 'Hello World';
  3. $this->assertTrue($hw == 'Hello World');
  4.  
  5. $this->assertEqual($hw,'Hello World');
  6. $this->assertNotEqual($hw,'Hello Kitty');
  7.  
  8. $this->assertPattern('/hello world/i', $hw);
  9. $this->assertNoPattern('/hello kitty/i', $hw);
  10.  
  11. // ...
  12. }

Télécharger

On comprendra que toutes les méthodes commençant par « assert » sont des méthodes de test. Le reste est de l’anglais compréhensible pour un programmeur php.

Quelques méthodes fournies par Simple Test

Le plus simple est d’aller étudier la documentation anglaise de SimpleTest (la française n’est pas tout à fait actualisée).

On découvrira les assertions suivantes :

  • assertTrue($x) vérifie $x vrai
  • assertFalse($x) vérifie $x faux
  • assertNull($x) vérifie $x inexistant
  • assertNotNull($x) vérifie que $x existe
  • assertIsA($x, $t) vérifie que l’objet $x est de type $t
  • assertNotA($x, $t) vérifie que l’objet $x n’est pas de type $t
  • assertEqual($x, $y) vérifie $x == $y
  • assertNotEqual($x, $y) vérifie $x != $y
  • assertWithinMargin($x, $y, $m) vérifie (abs($x - $y) < $m) est faux
  • assertOutsideMargin($x, $y, $m) vérifie (abs($x - $y) < $m) est vrai
  • assertIdentical($x, $y) vérifie $x === $y
  • assertNotIdentical($x, $y) vérifie $x !== $y
  • assertReference($x, $y) vérifie $x référence de $y
  • assertClone($x, $y) vérifie $x copie de $y
  • assertPattern($p, $x) vérifie que $pattern (expression régulière) capture $x
  • assertNoPattern($p, $x) vérifie que $pattern ne capture pas $x
  • expectError($x) vérifie qu’il y a une erreur php générée

Plugin Simple Test pour SPIP

Un plugin pour SPIP a été développé depuis pour utiliser les avantages de la librairie Simple Test.

Pour créer des tests unitaires pour votre projet SPIP, il suffit d’installer le plugin, de créer un dossier « tests » dans votre plugin, et d’y copier a minima le fichier « lanceur_spip.php » contenu dans le répertoire « tests/ » du plugin simpleTests.

Ce fichier permet de démarrer SPIP (et simpleTest) depuis le répertoire test de votre plugin (exemple http://localhost/mon_spip/plugins/mon_plugin/tests/)

Il vous faudra aussi inclure ce fichier dans tous les sous dossiers de votre répertoire « tests » où vous placez des tests unitaires.

Vous pourrez aussi éventuellement copier le fichier « all_tests.php » qui permet d’executer tous les fichiers de tests d’un répertoire et de ses sous répertoires (il faut par contre l’éditer pour créer un nom de classe unique).

Créons un premier fichier de test

On supposera qu’on a bien copié « lanceur_spip.php » dans son répertoire tests. Créons un fichier de test « testMaBaliseAutoriser.php » comme ceci :

  1. <?php
  2. require_once('lanceur_spip.php');
  3. include_spip('inc/autoriser');
  4.  
  5. class Test_ma_balise_autoriser extends SpipTest{
  6.  
  7. function testAutoriserOkNiet(){
  8. $this->assertFalse(autoriser('niet'));
  9. $this->assertTrue(autoriser('ok'));
  10. }
  11. }

Télécharger

On remarquera qu’on étend une classe appelée « SpipTest » (elle-même étend des tests de Simple Test), qui permet d’ajouter un certain nombre de fonctions et d’assertions à celles prévues par défaut. On y reviendra plus tard.

Le nom de la classe doit être unique et explicite sur ce qu’il va faire, comme celui du fichier d’ailleurs. Il est possible, et souvent utile, de mettre plusieurs classes dans un fichier, et plusieurs méthodes de tests dans une classe.

Les noms des méthodes doivent aussi être explicite sur ce qu’elles font, particulièrement dans les tests, car en cas d’erreur, ce sont ces noms qui vont apparaître (nom du fichier, de la classe, de la méthode, puis erreur particulière à l’assertion avec le numéro de ligne de l’erreur).

Il est donc conseillé d’écrire plein de petites méthodes pour les tests, plutôt d’une grosse regroupant tous les tests à faire.

  1. function testAutoriserOkNiet(){
  2. $this->assertFalse(autoriser('niet'));
  3. $this->assertTrue(autoriser('ok'));
  4. }

Télécharger

Ici, la fonction teste que autoriser('niet') retourne bien la valeur qui est attendu.

Exécuter les tests

En se rendant sur http://localhost/mon_spip/plugins/mon_plugin/tests/testMaBaliseAutoriser.php , nous devons voir le nom de notre fichier, et un message de réussite (ou d’echec des opérations pourquoi pas).

PNG

Si vous avez copié « all_tests.php », http://localhost/mon_spip/plugins/mon_plugin/tests/all_tests.php doit à peu près indiquer les mêmes choses.

PNG

De la même manière, si vous avez copié les anciens tests unitaires de SPIP [4] dans un répertoire tests/ à la racine de votre SPIP, aller sur http://localhost/mon_spip/tests/ doit lancer les tests de SPIP et ceux des plugins ensuite (vers la fin).

PNG

Méthodes fournies par SpipTest

  • assertOk($x) vérifie $x == ’ok’ (casse indiférente)
  • assertNotOk($x) vérifie $x != ’ok’ (casse indiférente)
  • recuperer_code($code, $contexte, ...) crée un squelette pour le code donné, et le calcule avec le contexte passé
  1. $x = $this->recuperer_code("#ENV{troll}",array('troll'=>'interface'));
  2. $this->assertEqual('interface',$x);

Télécharger

  • assertOkCode($code, $contexte,...) que la compilation du code $code et son calcul avec le contexte $contexte retourne ’ok’ (casse indiférente)
  • assertNotOkCode($code, $contexte,...)
  1. function testAutoriserSqueletteOkNiet(){
  2. $this->assertOkCode('[(#AUTORISER{ok})ok]');
  3. $this->assertOkCode('[(#AUTORISER{niet}|sinon{ok})]');
  4. }

Télécharger

  • asserEqualCode($value, $code, $contexte,...)
  • asserNotEqualCode($value, $code, $contexte,...)
  • asserPatternCode($pattern, $code, $contexte,...)
  • recuperer_infos_code($code, $contexte, ...) retourne un tableau d’infos sur la compilation, ainsi que les erreurs de compilation générée

Subtilités Non Applicables

Parfois, pour une raison particulière, certains tests ne peuvent pas être appliqués. Par exemple parce qu’un contenu adéquat manque dans la base de donnée de test.

Pour le signaler, il est possible dans les tests de faire envoyer une chaine commençant par NA. Celle ci sera vu par assertOk() et assertOkCode() comme une exception de type ’Non applicable’, et le texte suivant NA est alors affiché.

Exemple :

De la même manière, il faut parfois forcer un affichage de type non applicable plutôt que d’executer un test que l’on va savoir faux. Deux fonctions peuvent nous aider : isNa() (renvoie vrai si la chaine passée commence par NA) et exceptionSiNa() (ajoute une exception Non Applicable, et retourne false). Exemple :

Enfin, on peut forcer l’envoi d’une exception de la sorte :

Transmettre des fonctions aux squelettes

Avec la méthode options_recuperer_code(array()) il est possible de transmettre certaines options à la fonction recuperer_code(). L’argument est un tableau clé=>valeur

  • ’avant_code’ : pour ajouter systematiquement un code avant
  • ’apres_code’ : pour ajouter systematiquement un code apres
  • ’fonctions’ : pour ajouter un fichier de fonctions au squelette.

Exemples :

Attention : Ces options sont persistantes entre les méthodes de tests. Pour les annuler/effacer, il faut executer la fonction sans argument.

Tester des erreurs de compilation

Parfois, on aimerait vérifier que la compilation génère bien des erreurs attendues.

Pour cela, on peut attraper les erreurs générées avec la fonction
infos_recuperer_code() qui renvoie le tableau des erreurs generées (et bien d’autres informations)

Tester le site public

Il est possible de faire appeler les codes générées par un navigateur interne à Simple Test (qui n’est donc pas logé par défaut)

Pour cela, il faut inclure les librairies qui vont bien, et faire par exemple :

Notes

[2Lire par exemple : Extreme Programming (Wikipedia)

[3Méthode La Rache (Grand merci Ashazin pour le lien pertinent)

[4

Dernière modification de cette page le 6 décembre 2008

Retour en haut de la page

Vos commentaires

Répondre à cet article

Qui êtes-vous ?
  • [Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici Les choses à faire avant de poser une question (Prolégomènes aux rapports de bugs. )
Ajouter un document

Retour en haut de la page

Ça discute par ici

  • Champs Extras 3

    16 janvier 2012 – 524 commentaires

    Ce plugin permet de créer et/ou de gérer des champs supplémentaires dans les objets éditoriaux de SPIP. Il permet donc de prendre en compte et d’afficher de nouveaux éléments dans n’importe quel objet éditorial de SPIP. Screencast Vous n’aimez pas (...)

  • Réservation d’événements

    16 mars 2015 – 188 commentaires

    Ce plugin permet d’offrir aux visiteurs de s’inscrire pour un évènement du plugin Agenda et de gérer les réservations enregistrées. Installation Le plugin s’installe comme n’importe quel plugin. il nécessite : Agenda API de vérification (...)

  • Les crayons

    23 avril 2008 – 815 commentaires

    Ce plugin permet d’éditer les contenus sur les pages publiques du site, sans passer par l’espace privé de SPIP.

  • LESS pour SPIP : Less-CSS (anciennement LESSpip)

    5 novembre 2010 – 43 commentaires

    Less-CSS (Anciennement LESSpip) est un plugin intégrant facilement le logiciel LESS dans SPIP. LESS est une extension de CSS ajoutant les variables, les classes, les opérations, les imbrications au langage. Facilitant ainsi l’écriture de (...)

  • Recommander

    3 avril 2011 – 16 commentaires

    Ce plugin propose une manière simple de suggérer de recommander par email un article à un ami. Fonction « recommander un article à un ami ». On l’ajoute dans n’importe quel squelette sous la forme : #RECOMMANDERtitre de la page,url de la page,intro (...)

Ça spipe par là