Tests en PHP : Unit, Integration, E2E au niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Tests en PHP : Unit, Integration, E2E au niveau avancé



Dans le développement web moderne en PHP, la qualité du code n'est plus une option — c'est une condition essentielle à la survie du projet. Les tests unitaires de base sont familiers à chaque développeur, mais dès que le projet dépasse le cadre du "Hello World", le besoin d'approches plus complexes se fait sentir : tests d'intégration, vérification des interactions entre composants et tests de bout en bout des scénarios utilisateur (E2E).



Cet article est destiné aux développeurs PHP de niveau Middle et supérieur, déjà familiers avec PHPUnit et souhaitant approfondir leurs connaissances. Nous aborderons des techniques avancées : tests avec dépendances externes, travail avec des conteneurs de test, isolation de l'infrastructure et construction d'une stratégie de test complète.



1. Tests Unitaires avancés : Objets Mock et Stubs



Au niveau avancé, les tests unitaires ne se limitent plus à la vérification de fonctions mathématiques. Ils testent la logique métier, isolée du monde extérieur. Les outils clés sont Mock et Stub.



Stub renvoie des données prédéfinies. Mock vérifie comment les méthodes ont été appelées (nombre d'appels, ordre des arguments).



Prenons un exemple : un service de paiement qui envoie une requête à une passerelle de paiement.



<?phpclass PaymentService {    public function __construct(        private PaymentGatewayInterface $gateway,        private LoggerInterface $logger    ) {}

public function processPayment(Order $order): bool { $result = $this->gateway->charge( $order->getAmount(), $order->getCurrency() );

if ($result->isSuccess()) { $this->logger->info('Payment processed', ['order_id' => $order->getId()]); return true; }

$this->logger->warning('Payment failed', ['error' => $result->getError()]); return false; }}

// Test avec PHPUnitclass PaymentServiceTest extends TestCase { public function testSuccessfulPaymentLogsInfo(): void { // Création d'un Stub pour la passerelle $gatewayStub = $this->createStub(PaymentGatewayInterface::class); $gatewayStub->method('charge') ->willReturn(new PaymentResult(true));

// Création d'un Mock pour le logger (vérification de l'appel) $loggerMock = $this->createMock(LoggerInterface::class); $loggerMock->expects($this->once()) ->method('info') ->with('Payment processed', $this->arrayHasKey('order_id'));

$service = new PaymentService($gatewayStub, $loggerMock); $result = $service->processPayment(new Order(100, 'USD'));

$this->assertTrue($result); }}


Technique avancée : utilisez willReturnCallback() pour des réponses dynamiques et withConsecutive() pour vérifier la séquence des appels.



2. Tests d'intégration : Base de données et API externes



Les tests d'intégration vérifient comment votre code interagit avec des composants réels : base de données, système de fichiers, cache. Ici, on ne peut pas compter sur des mocks — une infrastructure réelle est nécessaire.



Problème : les tests deviennent lents et fragiles. Solution : utiliser des conteneurs de test (Testcontainers) ou des bases de données SQLite intégrées.



Exemple de test d'intégration pour un dépôt d'utilisateurs avec Doctrine :



<?phpclass UserRepositoryIntegrationTest extends KernelTestCase {    private EntityManagerInterface $entityManager;    private UserRepository $repository;

protected function setUp(): void { self::bootKernel(); $this->entityManager = self::$kernel->getContainer() ->get('doctrine

Blogs

Book Recommendations