Revenir à la base : Tester une fonction de 4 lignes (et oui!)
Tags: testing, php, beginners
Published: 2018-05-24 12:27:49

---
title: Revenir à la base : Tester une fonction de 4 lignes (et oui!)
published: true
description: Voilà ce que je dis à mes dévs quand ils me demandent comment et quoi tester. 
tags: testing,basic,php,beginners
---

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
<?php
   
use PHPUnit\Framework\TestCase;
    
class StatsTest extends TestCase
{
   
}
```

## 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 :

```php
    function testIsStatusAll()
    {
    }
```

Dans la classe Stats :

```php
    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;
    }
```

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

```php
   $object = new MyClass();
   $this->assertTrue($object->MyFunction());
```

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](http://phpunit.readthedocs.io/fr/latest/test-doubles.html#mocker-les-traits-et-les-classes-abstraites) pour cela. Dans notre cas la fonction testIsStatusAll la création de l'objet se fera dans la manière suivante.

```php
    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());
    }
```

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 :

```php
   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());
   }
```

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.