Testen in PHP: Unit, Integration, E2E – der vollständige Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Tests in PHP notwendig sind

Entwicklung in PHP bedeutet nicht nur, Code zu schreiben, der "funktioniert". In der modernen Webentwicklung stehen Anwendungsstabilität und Vorhersagbarkeit im Vordergrund. Ohne Tests riskiert jede Codeänderung, bereits funktionierende Funktionalität zu beeinträchtigen, und die manuelle Fehlersuche entwickelt sich zu einer endlosen "Bug-Jagd". Genau hier kommen Tests zur Rettung.

In diesem Artikel werden wir drei Schlüsselebenen des Testens von PHP-Anwendungen aufschlüsseln: Unit, Integration und E2E (End-to-End). Sie erfahren, wie sie sich unterscheiden, welche Tools verwendet werden und wie Sie eine effektive Teststrategie für Ihr Projekt aufbauen.

Unit-Tests: Die Basis der Pyramide

Unit-Tests sind die schnellste und isolierteste Testebene. Ihr Ziel ist es, die Funktionsweise einer einzelnen "Einheit" (Klasse, Methode oder Funktion) isoliert von externen Abhängigkeiten wie Datenbank, Dateisystem oder API zu überprüfen.

Tools für PHP

Das bekannteste Framework ist PHPUnit. Eine modernere Alternative ist Pest, das eine prägnantere Syntax bietet.

Beispiel eines Unit-Tests in PHPUnit

Angenommen, wir haben eine einfache Rechner-Klasse:

<?php
// src/Calculator.php
class Calculator
{
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }

    public function divide(int $a, int $b): float
    {
        if ($b === 0) {
            throw new \\InvalidArgumentException('Division by zero');
        }
        return $a / $b;
    }
}

Der Test dafür sieht wie folgt aus:

<?php
// tests/Unit/CalculatorTest.php
use PHPUnit\\Framework\\TestCase;

class CalculatorTest extends TestCase
{
    private Calculator $calculator;

    protected function setUp(): void
    {
        $this->calculator = new Calculator();
    }

    public function testAddReturnsCorrectSum(): void
    {
        $result = $this->calculator->add(2, 3);
        $this->assertEquals(5, $result);
    }

    public function testDivideThrowsExceptionOnZero(): void
    {
        $this->expectException(\\InvalidArgumentException::class);
        $this->calculator->divide(10, 0);
    }
}

Wichtige Prinzipien von Unit-Tests:

  • Isolation: Alle externen Abhängigkeiten (DB, API) werden durch Mocks oder Stubs ersetzt.
  • Geschwindigkeit: Sie werden in Millisekunden ausgeführt.
  • Sie überprüfen ein bestimmtes Szenario (ein Assert pro Test ist gute Praxis).

Ausführungsbefehl: ./vendor/bin/phpunit tests/Unit

Integrationstests: Überprüfung der Interaktion

Integrationstests gehen eine Ebene höher. Sie überprüfen, wie verschiedene Teile des Systems zusammenarbeiten: eine Klasse mit einer Datenbank, ein Controller mit einem Modell, ein Service mit einer externen API (echt oder simuliert).

Wann werden Integrationstests benötigt?

  • Überprüfung der Korrektheit von SQL-Abfragen.
  • Validierung der Verbindung zwischen Anwendungsschichten (z. B. Repository + Entity).
  • Testen von Middleware oder Events.

Beispiel: Testen eines Repositorys mit einer echten Datenbank

Für Integrationstests wird oft eine Testdatenbank verwendet (SQLite im Arbeitsspeicher oder Transaktionen in PostgreSQL). Sehen wir uns ein Beispiel mit PHPUnit und einem Trait zum Zurücksetzen der Datenbank an:

<?php
// tests/Integration/UserRepositoryTest.php
use PHPUnit\\Framework\\TestCase;

class UserRepositoryTest extends TestCase
{
    private PDO $pdo;
    private UserRepository $repository;

    protected function setUp(): void
    {
        // Erstelle eine SQLite-Datenbank im Arbeitsspeicher für Isolation
        $this->pdo = new PDO('sqlite::memory:');
        $this->pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)');                

Blogs

Buchempfehlungen