Symfony – Comment faire des tests unitaires

Symfony – Comment faire des tests unitaires

  • Post comments:5 commentaires
  • Reading time:4 mins read

L’intérêt de faire des tests unitaires, c’est de pouvoir tester son application pendant son développement. Cet article cible les développeurs web qui n’ont peu ou jamais fait de test unitaire sur un projet Symfony.

Qu’est-ce qu’un test unitaire ?

Un test unitaire est une procédure qui permet de tester les fonctions dans des entités, des services etc. Afin de vérifier le bon fonctionnement de ce dernier.

Cependant, les tests sont faits à la charge du développeur pendant son développement en testant lui-même les fonctionnalités. Ce qui peut être amené à faire de la régression.

Cela permet aussi d’établir des règles métiers spécifique pour valider à chaque fois votre application avant chaque déploiement en production.

Pour créer un test unitaire sur un projet Symfony, on va utiliser PhpUnit.

Qu’est-ce que PhpUnit ?

PhpUnit est un framework PHP qui permet de faire des tests d’assertions. A savoir qu’un test d’assertion est une expression qui doit être évaluée vrai. PhpUnit est le plus utiliser et recommander dans plusieurs frameworks (Symfony, Laravel, Zend … ).

Comment ça marche ?

Dans un premier temps, il faut l’installer sur notre projet Symfony :

 composer require --dev symfony/phpunit-bridge

Désormais dans votre dossier bin, vous avez le binaire phpunit.

L’ensemble de nos tests seront écrites dans le dossier tests qui est prévus à cette effet.

Pour la configuration de PhpUnit, il y a un fichier à la racine du projet nommé : phpunit.xml.dist

Test sur une entité

Passons désormais à un exemple, on souhaite tester l’entité Article de notre projet Blog.

// src/Entity/Article.php
namespace App/Entity;

class Article
{
    private $uri;

    private $title;

    public function setUri(string $uri) 
    {
        $this->uri = strtolower(str_replace(' ', '_', $uri));

        return $this;
    }
    
    public function getUri()
    {
        return $this->uri;
    }

    public function setTitle(string $title) 
    {
        $this->title = $title;

        return $this;
    }

    public function getTitle()
    {
        return $this->title;
    }
    
}

Pour des tests unitaires, il n’est pas important de tester des champs non modifiés dans une entité.

Maintenant je vais tester notre entité Article. Pour cela, je vais créer dans le dossier tests, le fichier ArticleTest.

Conseil de bonne pratique, le dossier tests doit avoir la même architecture que le dossier src pour faciliter la compréhension.

Exemple : src/Entity/Article.php son fichier de tests sera ici : tests/Entity/ArticleTest.php

// tests/Entity/ArticleTest.php
namespace App\Tests\Entity;

use App\Entity\Article;
use PHPUnit\Framework\TestCase;

class ArticleTest extends TestCase
{
    public function testUri()
    {
        $article = new Article();
        $uri = "Test 2";
        
        $article->setUri($uri);
        $this->assertEquals("test_2", $article->getUri());
    }
}

Test sur un service

Autre exemple de test unitaire, je vais créer un calculateur qui va uniquement retourner un résultat simple :

// src/Utils/Calculator.php
namespace App\Utils;

class Calculator
{
    public function add($a, $b)
    {
        return $a + $b;
    }
}

Passons désormais à un exemple, on souhaite tester un service de notre projet Blog.

Pour tester ce calculateur, je vais créer le fichier test correspondant.

// tests/Utils/CalculatorTest.php
namespace App\Tests\Utils;

use App\Utils\Calculator;
use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    public function testAdd()
    {
        $calculator = new Calculator();
        $result = $calculator->add(10, 32);
        
        $this->assertEquals(42, $result);
    }
}

Pour lancer le test, il y a plusieurs façons de faire, soit l’ensemble des tests, soit dans un dossier spécifique ou un fichier de test spécifique.

# Lance l'ensemble des tests
$ php bin/phpunit

# Lance l'ensemble des tests dans le dossier Entity. 
$ php bin/phpunit tests/Entity

# Lance l'ensemble des tests dans le fichier ArticleTest.php
$ php bin/phpunit tests/Entity/ArticleTest.php

Conclusion

Désormais, vous pouvez créer des tests unitaires afin de tester votre application web. Un conseil, prioriser les tests sur les fonctionnalités métier.

Cet article a 5 commentaires

  1. geoffrey

    Bonjour, j’ai fait un test pour mettre un username à mon entity Utilisateur mais j’ai une erreur.

    λ php bin/phpunit tests/Entity
    #!/usr/bin/env php
    PHP Fatal error: App\tests\Entity\UtilisateurTest cannot implement PHPUnit\Framework\TestCase – it is not an interface in C:\xampp\htdocs\Projet-Oh-Chti-Breizh\tests\Entity\UtilisateurTest.php on line 8

    Fatal error: App\tests\Entity\UtilisateurTest cannot implement PHPUnit\Framework\TestCase – it is not an interface in C:\xampp\htdocs\Projet-Oh-Chti-Breizh\tests\Entity\UtilisateurTest.php on line 8

    Voici mon code :

    public function testUri()
    {
    $utilisateur = new Utilisateur();
    $username = “Test 2”;

    $utilisateur->setUsername($username);
    $this->assertEquals(“test_2”, $utilisateur->setUsername());
    }

    1. Gary Houbre

      Bonjour,

      Pouvez-vous m’envoyer la classe entièrement svp.

      Cordialement,

      Gary

  2. geoffrey

    Alors j’ai tout repris à zero, et suivis un cours sur OCRoom, cepandant avant de faire des test, je veux tester le test qui est mis en exemple :

    request(‘GET’, ‘/produits’);

    $this->assertSame(200, $client->getResponse()->getStatusCode());
    $this->assertGreaterThan(
    0,
    $crawler->filter(‘html:contains(“menu”)’)->count()
    );

    }
    }

    Mais j’ai beaucoup d’erreur quand je lance un coverage :
    λ vendor\bin\phpunit –coverage-html web/code-coverage
    PHP Fatal error: Uncaught ReflectionException: Class does not exist in C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php:533
    Stack trace:
    #0 C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php(533): ReflectionClass->__construct(”)
    #1 C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php(689): PHPUnit_Util_Test::parseTestMethodAnnotations(NULL, NULL)
    #2 C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\phpunit-bridge\DeprecationErrorHandler.php(148): PHPUnit_Util_Test::getGroups(NULL, NULL)
    #3 [internal function]: Symfony\Bridge\PhpUnit\DeprecationErrorHandler::Symfony\Bridge\PhpUnit\{closure}(16384, NULL, ‘C:\\xampp\\htdocs…’, 16, Array)
    #4 C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\debug\DebugClassLoader.php(16): trigger_error(‘The “Symfony\\Co…’, 16384)
    #5 C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\composer\ClassLoader.php(444): include(‘C:\\xampp\\htdocs…’)
    #6 C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\composer\ClassLo in C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php on line 533

    Fatal error: Uncaught ReflectionException: Class does not exist in C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php on line 533

    ReflectionException: Class does not exist in C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php on line 533

    Call Stack:
    0.0004 410752 1. {main}() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\phpunit:0
    0.3042 1013272 2. PHPUnit_TextUI_Command::main() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\phpunit:52
    0.3043 1016432 3. PHPUnit_TextUI_Command->run() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\TextUI\Command.php:116
    0.6735 2820792 4. PHPUnit_TextUI_TestRunner->doRun() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\TextUI\Command.php:186
    0.6735 2820816 5. PHPUnit_TextUI_TestRunner->handleConfiguration() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\TextUI\TestRunner.php:163
    0.7162 2922904 6. Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV5->__construct() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\TextUI\TestRunner.php:952
    0.7256 2987216 7. Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait->__construct() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\phpunit-bridge\Legacy\SymfonyTestsListenerForV5.php:27
    0.7353 2996560 8. class_exists() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\phpunit-bridge\Legacy\SymfonyTestsListenerTrait.php:56
    0.7353 2996640 9. spl_autoload_call() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\phpunit-bridge\Legacy\SymfonyTestsListenerTrait.php:56
    0.7354 2996720 10. Composer\Autoload\ClassLoader->loadClass() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\phpunit-bridge\Legacy\SymfonyTestsListenerTrait.php:56
    0.7363 2996848 11. Composer\Autoload\includeFile() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\composer\ClassLoader.php:322
    0.7479 3112264 12. include(‘C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\debug\DebugClassLoader.php’) C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\composer\ClassLoader.php:444
    0.7480 3112584 13. trigger_error() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\debug\DebugClassLoader.php:16
    0.7480 3113648 14. Symfony\Bridge\PhpUnit\DeprecationErrorHandler::Symfony\Bridge\PhpUnit\{closure:C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\phpunit-bridge\DeprecationErrorHandler.php:107-182}() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\debug\DebugClassLoader.php:16
    0.7481 3123528 15. PHPUnit_Util_Test::getGroups() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\symfony\phpunit-bridge\DeprecationErrorHandler.php:148
    0.7481 3123528 16. PHPUnit_Util_Test::parseTestMethodAnnotations() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php:689
    0.7481 3123672 17. ReflectionClass->__construct() C:\xampp\htdocs\Projet-Oh-Chti-Breizh\vendor\phpunit\phpunit\src\Util\Test.php:533

    Désoler, je n’ai plus la même erreur depuis hier.. Mais c’est peut-etre lier !

  3. geoffrey

    Désormais je ne peut plus lancer mes tests, taper vendor\bin\phpunit ou vendor\bin\phpunit –help il m’ecris exatement la même chose..

    1. Gary Houbre

      D’accord, est-ce qu’en lancant la commande avec php bin/phpunit . Avez vous une erreur ? Sinon contactez moi par email je vais voir avec vous plus simplement l’erreur 😀

Laisser un commentaire