DEV Community

Brice Favre
Brice Favre

Posted on • Edited on

Revenir à la base : Tester une fonction de 4 lignes (et oui!)

Cet exemple est tiré d'un cas réel de développement. Il n'a rien de très compliqué, hormis le fait que la classe testée soit abstraite mais est assez courant dans le développement.

Imaginons que, dans la class Stats, nous voulions rajouter une fonction isStatusAll qui permet de vérifier que la propriété status de la classe contient all, si c'est un tableau, ou bien est égal à "all" si c'est une chaine de caractère.

Création de la classe de test

La première chose à vérifier est la présence ou non de la classe de tests. Elle doit avoir le même nom que la classe suivi de tests, soit StatsTest

Si elle est présente alors nous rajouterons nos tests à celle ci.

Si elle n'existe pas, il suffit de la créer dans le répertoire approprié. Il suffit de suivre les conventions que l'équipe ou le responsable des tests se sont données. Dans ce répertoires nous créerons un fichier StatsTest.php contenant le code suivant :

<?php

use PHPUnit\Framework\TestCase;

class StatsTest extends TestCase
{

}
Enter fullscreen mode Exit fullscreen mode

Que doit on tester et comment ?

C'est une question qui se pose à chaque fois que l'on va écrire des tests unitaires.
La bonne question à se poser est "Que cherche t'on à faire?" Une question qu'il convient de découper en plusieurs étapes.

La première est que l'on cherche à écrire une fonction isStatusAll donc nous allons écrire, dans notre classe de test, une fonction testIsStatusAll, puis écrire la fonction elle même dans la classe Stats :

Dans la classe de tests :

    function testIsStatusAll()
    {
    }
Enter fullscreen mode Exit fullscreen mode

Dans la classe Stats :

    public function isStatusAll() {
        // On code un simple retour pour le moment 
        // pour valider la liaison entre le code et la classe de test
        return false;
    }
Enter fullscreen mode Exit fullscreen mode

Ensuite il suffit d'appeler la nouvelle fonction dans la classe de test. Généralement il suffit de faire quelque chose comme ça :

   $object = new MyClass();
   $this->assertTrue($object->MyFunction());
Enter fullscreen mode Exit fullscreen mode

Dans notre cas, la classe Stats est une classe abstraite, il faudra donc la simuler afin de la tester. Heureusement PHPUnit pense à nous et prévoit un système pour cela. Dans notre cas la fonction testIsStatusAll la création de l'objet se fera dans la manière suivante.

    function testIsStatusAll()
    {
        // Le deuxième argument permet de passer des paramètres au 
        // constructeur de l'objet car, 
        // Fun Fact, le constructeur de Stats prend des paramètres.
        $statsItem = $this->getMockForTrait(StatsItem::class, [1]);
        $this->assertTrue($statsItem->isStatusAll());
    }
Enter fullscreen mode Exit fullscreen mode

Si on lance les tests alors ils échouent... ce qui est normal :-)

Une fois ce point de départ, il ne vous reste plus qu'à coder la fonction et les tests afférents. Pour des raisons pratiques, il est conseillé de faire une fonction par assertion. Dans notre cas il en existe quatre :

  • IsStatusAll renvoie faux si status est nul (soit la condition par défaut)
  • IsStatusAll renvoie vrai si status est égal à "all"
  • IsStatusAll renvoie vrai si status est un tableau et que ce tableau contient "all"
  • IsStatusAll renvoie faut si status est un tableau et que ce tableau ne contient pas "all"

Ce qui donne dans notre cas :

   function testIsStatusAllWithoutDocStatus()
   {
        $stats = $this->getMockForTrait(Stats::class, [1]);
        $this->assertFalse($stats->isStatusAll());
   }

   function testIsStatusAllWhereStatusIsAll()
   {
        $stats = $this->getMockForTrait(Stats::class, [1]);
        $stats->setStatus('all');
        $this->assertTrue($statsItem->isStatusAll());
   }

   function testIsStatusAllWhereStatusIsAnArrayWithAllinIt()
   {
        $stats = $this->getMockForTrait(Stats::class, [1]);
        $stats->setStatus(['all']);
        $this->assertTrue($statsItem->isStatusAll());
   }

   function testIsStatusAllWhereStatusIsAnEmptyArray()
   {
        $stats = $this->getMockForTrait(Stats::class, [1]);
        $stats->setStatus(['']);
        $this->assertFalse($statsItem->isStatusAll());
   }
Enter fullscreen mode Exit fullscreen mode

Les tests vous montreront si la fonction correspond à ce qu'elle doit faire... ou pas.

Conclusion

Cet exemple montre comment, en quelques tests ont peut faire le tour d'une fonction simple. J'invite tous ceux qui n'ont pas encore franchi le pas, a commencer par ce genre de fonction. Outre l'aspect qualité, le fait de revenir sur son code permet d'éviter les erreurs bêtes et de se libérer l'esprit. Une fois les tests faits, il est très simple de coder, de se tromper, de se corriger et de délivrer une fonction conforme à ce que l'on voulait.

Ce sera autant de temps de cerveau disponible pour des fonctions plus complexes, pour des problématiques plus ardues.

Top comments (0)