Tester son application Symfony
Introduction au test logiciel
1. Les tests : un indispensable pour la qualité logicielle
Les tests logiciels garantissent la robustesse et la qualité d’une application en partant d’un principe simple : plus un problème est identifié tôt, moins il coûte cher à réparer.
Si une application ne dispose pas d’une suite de tests, il est fort probable qu’au cours de son évolution, au fur et à mesure des corrections de bogues et de l’ajout de nouvelles fonctionnalités, de nouveaux bogues apparaissent sur des fonctionnalités déjà existantes. Cela s’appelle la « régression », et les tests logiciels permettent de s’assurer de la non-régression de l’application.
Au-delà de ce concept de non-régression, il est indispensable de pouvoir valider toutes les étapes de construction d’une application, des premières lignes de code en passant par l’assemblage des fonctionnalités en classes et composants et, enfin, de pouvoir tester l’interface utilisateur de l’application.
Durant toutes ces phases de construction logicielle, différentes familles (ou catégories) de tests entrent en œuvre.
2. Les différentes catégories de tests
Dans un processus de construction logicielle, plusieurs catégories de tests vont rentrer en action, chacune à une étape plus ou moins avancée du projet. Il est réducteur de croire que seuls les tests...
Les tests unitaires avec PHPUnit
1. Mise en place des tests
Pour pouvoir mettre en place les tests dans votre application Symfony, il est tout d’abord nécessaire d’installer PHPUnit. PHPUnit s’installe via une recette Flex grâce à la commande suivante :
composer require --dev phpunit/phpunit symfony/test-pack
Une fois l’installation terminée, vous devriez pouvoir invoquer PHPUnit avec la commande suivante passée depuis votre répertoire de projet :
php ./vendor/bin/phpunit
Par défaut, cette commande exécute tous les tests présents dans le répertoire tests/ ; ici, aucun test n’est exécuté, comme l’indique la sortie de la commande.
2. Règle d’écriture des tests
Tous les tests unitaires de vos fonctionnalités doivent être stockés dans le répertoire tests/ de votre application Symfony. En effet, ce répertoire est celui qui est associé à l’environnement test du framework pouvant ainsi s’appuyer sur une configuration spécifique définie dans un fichier .env.test à la racine de votre projet. Ce fichier pourrait notamment contenir une URL de connexion à une base de données dédiée aux tests.
Prenons comme exemple la classe suivante :
namespace App\Model;
class Utilisateur ...
Les tests fonctionnels
1. Différence par rapport aux tests unitaires et d’intégration
Contrairement aux tests unitaires et d’intégration, qui sont destinés à tester les résultats des invocations des différentes méthodes de vos classes, les tests fonctionnels vérifient des comportements de l’application.
Le test fonctionnel le plus courant est le test de vos contrôleurs. Vos actions étant dépendantes d’un certain contexte HTTP, il ne s’agit pas ici de tester directement le retour des méthodes de vos contrôleurs, mais de simuler des requêtes HTTP et d’analyser les réponses retournées.
En clair, les tests fonctionnels reproduisent les conditions d’utilisation réelles de votre application. D’un certain point de vue, ils peuvent être considérés comme étant plus complexes que les tests unitaires en ce qu’ils nécessitent la création d’un certain contexte.
2. Tester une action
Introduisons les tests fonctionnels au travers d’une action basique :
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class DefaultController extends AbstractController
{
#[Route('/bonjour/{nom}')]
public function bonjour($nom)
{
return new Response('Bonjour ' . $nom . '!');
}
}
Pour cette action, il serait légitime de penser à la classe de tests suivante :
namespace App\Tests\Controller;
use App\Controller\DefaultController;
class DefaultControllerTest extends \PHPUnit\Framework\TestCase
{
public function testBonjour()
{
$controleur = new DefaultController;
$reponse = $controleur->bonjourAction('Amadou');
...