Stratégies pour écrire des tests unitaires

Objectifs

  • Découvrir les tests unitaires,

  • Rédiger un test unitaire simple,

  • Découvrir les conventions de nommage de classes et méthodes de test,

  • Exécuter un ou plusieurs tests unitaires.

Contexte

Cette partie vise à décrire comment rédiger un test unitaire afin de valider le bon comportement d'une méthode issue d'une de nos classes PHP.

Les tests unitaires permettent de s'assurer que les unités du code source de notre application sont conformes à leur conception et se comportent comme attendu.

On appelle unité une méthode spécifique d'une classe donnée.

Notez que l'écriture de tests unitaires Symfony n'est pas différente de l'écriture de tests unitaires standards PHPUnit. Ainsi, en comprenant et en maîtrisant la syntaxe et la logique au sein d'un projet Symfony, vous serez à même de réaliser des tests unitaires au sein de n'importe quel projet PHP.

Méthode

Supposons une classe « HelloWorld » située dans le répertoire « src/Util » de votre application Symfony. Sa seule méthode « hello() » renvoie une chaîne de caractères contenant « Hello ... » avec le nom passé en paramètre.

ExempleCode : PHP

La classe à tester :

1
<?php
2
# src/Util/HelloWorld.php
3
namespace App\Util;
4
5
class HelloWorld {
6
    public function hello($name) {
7
        return 'Hello ' . $name;
8
    }
9
}

Pour tester cette méthode, nous créerons une nouvelle classe PHP « HelloWorldTest » dans un dossier « tests/Util ».

Par convention, nous nommons cette classe en concaténant le nom de la classe testée (ici, HelloWorld) et le mot-clé « Test ». En toute logique, nous obtenons « HelloWorldTest ».

Toujours par convention, nous reproduisons le chemin menant à notre classe testée au sein du répertoire « tests ». Ainsi, étant donné que la classe « HelloWorld » se situe dans le dossier « src/Util », sa classe de test doit être placée dans le répertoire « tests/Util ».

Notez également que cette classe de test doit absolument étendre la classe « TestCase » de PHPUnit. Cette dernière permet d'avoir accès aux méthodes propres aux tests unitaires comme assertEquals() que nous utiliserons par la suite.

C'est donc au sein de cette classe de test que nous réaliserons notre première méthode de test nommée en concaténant le mot-clé « test » au nom de la méthode testée (ici, « hello »). Nous obtenons ainsi la méthode « testHello() ».

Dans cette méthode, nous créons une nouvelle instance de la classe HelloWorld afin de stocker le résultat renvoyé par la méthode hello() dans une variable subtilement nommée $resultat.

Nous utilisons, enfin, la méthode assertEquals(), héritée de la classe TestCase pour s'assurer que le résultat obtenu est bien égal à « Hello Chris ».

La classe de test :

1
<?php
2
# tests/Util/HelloWorldTest.php
3
namespace Tests\Util;
4
5
use App\Util\HelloWorld;
6
use PHPUnit\Framework\TestCase;
7
8
class HelloWorldTest extends TestCase {
9
    public function testHello() {
10
        $helloWorld = new HelloWorld();
11
        $resultat = $helloWorld->hello("Chris");
12
        $this->assertEquals("Hello Chris", $resultat);
13
    }
14
}

Remarque

Le mot assert issu de la méthode assertEquals() fait référence à assertion. Une assertion représente un énoncé considéré comme vrai. Ici, on affirme donc que la chaîne de caractères « Hello Chris » sera la valeur retournée par l'appel de la méthode hello(‘Chris').

Pour exécuter ce test et ainsi vérifier qu'il est réussi, nous utiliserons la commande $ php bin/phpunit tests/Util/HelloWorldTest.php en prenant soin de bien être situé dans le répertoire de notre projet Symfony.

Dans notre cas, la commande $ php bin/phpunit tests/Util fonctionne également et teste toutes les classes de test présentes dans le dossier « tests/Util » :

Ici, notre unique test a été réalisé en 128 ms. La sortie en console indique également que le test a été une réussite.

Je modifie maintenant mon test pour générer volontairement une erreur. Admettons, que l'on s'attende à obtenir la chaîne de caractères « Hello Fanny » en retour de la fonction testée.

Voici le résultat obtenu en console :

Ici, on découvre que le seul test exécuté rencontre un échec. PHPUnit précise également qu'il s'attendait à recevoir la chaîne de caractères « Hello Fanny » alors que la méthode testée a renvoyé « Hello Chris ».

SyntaxeÀ retenir

Pour cette partie, il est essentiel de retenir que votre classe de test doit être nommée en reprenant le nom de la classe à tester suffixée avec le mot-clé « Test ». Cette dernière devra également étendre la classe « TestCase » du framework PHPUnit afin d'avoir accès aux méthodes de tests tel que assertEquals(. Retenez également que cette méthode prend deux arguments qu'elle compare :

  • La valeur qui doit être retournée par la méthode testée,

  • La valeur réellement retournée par la méthode testée,

  • Si ces deux valeurs sont égales, le test est une réussite.

Notez que j'aurai pu directement renvoyer la chaîne de caractère « HelloChris » et que le test aurait été un succès. C'est pour cette raison qu'il est important de faire plusieurs appels à la méthode assertEquals() avec des valeurs différentes pour s'assurer que la méthode testée renvoie toujours la bonne valeur, quels que soient ses arguments.