Testen in PHP: Unit, Integration, E2E von A bis Z

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 Testing in PHP keine Option, sondern Standard ist

In der modernen PHP-Entwicklung ist Testing längst kein „guter Ton“ mehr, sondern ein obligatorischer Schritt für Production-Projekte. Ohne Codeabdeckung durch Tests riskieren Sie, einen Fehler in die Produktion zu bringen, der das Unternehmen Geld und Reputation kosten kann. In diesem Artikel betrachten wir drei Testebenen: Unit (Modultests), Integration (Integrationstests) und E2E (End-to-End-Tests). Sie erfahren, worin sie sich unterscheiden, welche Tools Sie verwenden sollten (PHPUnit, Pest, Laravel Dusk, Codeception) und wie Sie eine richtige Teststrategie für Ihr PHP-Projekt aufbauen.



1. Unit-Tests: Isolierte Code-Einheiten testen

Unit-Tests prüfen die Arbeit einzelner Klassen, Funktionen oder Methoden isoliert von externen Abhängigkeiten (DB, API, Dateisystem). Dies ist die schnellste und günstigste Testart. Das wichtigste Tool in PHP ist PHPUnit (der De-facto-Standard) und seine „modische“ Alternative Pest.



1.1. Installation und erster Test mit PHPUnit

Installieren Sie PHPUnit über Composer:

composer require --dev phpunit/phpunit

Erstellen Sie einen Test für eine einfache Rechner-Klasse:

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

// tests/CalculatorTest.phpuse PHPUnit\\Framework\\TestCase;

class CalculatorTest extends TestCase { public function testAddition(): void { $calc = new Calculator(); $result = $calc->add(2, 3); $this->assertEquals(5, $result); }}

Führen Sie den Test aus:

./vendor/bin/phpunit tests


1.2. Verwendung von Mock-Objekten

Um die zu testende Klasse zu isolieren, „ersetzen“ wir ihre Abhängigkeiten mit Mocks. Beispiel mit einem User-Repository:

<?phpclass UserService {    private UserRepository $repo;    public function __construct(UserRepository $repo) {        $this->repo = $repo;    }    public function getUserName(int $id): string {        $user = $this->repo->findById($id);        return $user ? $user->getName() : 'Guest';    }}

// Im Test$mockRepo = $this->createMock(UserRepository::class);$mockRepo->method('findById') ->with(1) ->willReturn(new User('Alice'));

$service = new UserService($mockRepo);$this->assertEquals('Alice', $service->getUserName(1));

Best Practice: Schreiben Sie Unit-Tests für die gesamte Geschäftslogik. Sie sollten in Sekunden ausführbar sein und nicht von der Umgebung abhängen.



2. Integrationstests: Interaktion mit DB, API und externen Diensten prüfen

Integrationstests prüfen, wie Ihre Klassen mit echten Komponenten zusammenarbeiten: Datenbank, Cache, externe HTTP-Dienste. Sie sind langsamer als Unit-Tests, geben aber mehr Sicherheit, dass das System als Ganzes funktioniert.



2.1. Testen der Datenbankarbeit (Laravel + RefreshDatabase)

Wenn Sie Laravel verwenden, werden Integrationstests dank des Traits RefreshDatabase sehr einfach:

<?phpnamespace Tests\\Feature;

use Tests\\TestCase;use Illuminate\\Foundation\\Testing\\RefreshDatabase;

class UserRegistrationTest extends TestCase { use RefreshDatabase;

public function test_user_can_register(): void { $response = $this->post('/register', [ 'name' => 'John', 'email' => 'john@example.com', 'password' => 'secret123', ]);

$response->assertStatus(302); // Weiterleitung nach Erfolg $this->assertDatabaseHas('users', [ 'email' => 'john@example.com' ]); }}

Der Trait RefreshDatabase migriert die Datenbank automatisch vor den Tests und

Blogs

Buchempfehlungen