Zum Hauptinhalt springen

Was sind Tests

Tests prüfen automatisiert, ob Ihr Code so funktioniert wie erwartet. Wenn Sie neue Features hinzufügen oder Bugs beheben, sehen Sie mit Tests schnell, ob bestehendes Verhalten beschädigt wurde. Im Team lassen sich Änderungen dank Tests entspannter durchführen und reviewen. Laravel bringt Test-Unterstützung von Anfang an mit – wahlweise Pest oder PHPUnit. Nach einer Neuinstallation existieren phpunit.xml und das Verzeichnis tests/ bereits.
Pest basiert auf PHPUnit und bietet eine kompaktere, gut lesbare Syntax. Wenn Sie neu einsteigen, ist Pest eine gute Wahl.

Aufbau des Verzeichnisses tests/

tests/
├── Feature/      # Feature-Tests
│   └── ExampleTest.php
├── Unit/         # Unit-Tests
│   └── ExampleTest.php
└── TestCase.php
  • Feature/ – Feature-Tests. Größere Tests mit HTTP-Anfragen, die mehrere Komponenten oder API-Endpunkte prüfen. Die meisten Ihrer Tests landen hier.
  • Unit/ – Unit-Tests. Testen einzelne Klassen oder Methoden. Die Laravel-App wird nicht gebootet – Datenbank und andere Framework-Funktionen stehen nicht zur Verfügung.

Test erzeugen

Neue Testklassen erzeugen Sie mit make:test.
# Feature-Test (Default)
php artisan make:test TodoTest

# Unit-Test
php artisan make:test TodoTest --unit
Ergebnis: tests/Feature/TodoTest.php.

Tests ausführen

Mit php artisan test.
php artisan test
vendor/bin/pest oder vendor/bin/phpunit funktionieren genauso; php artisan test liefert die schönere Ausgabe. Optionen zum Filtern:
# Nur Feature-Tests
php artisan test --testsuite=Feature

# Sofort bei erstem Fehler stoppen
php artisan test --stop-on-failure

Einfache Tests schreiben

Beispiele für einfache Assertions:
<?php

test('true is true', function () {
    expect(true)->toBeTrue();
});

test('string enthält Laravel', function () {
    $message = 'Hello, Laravel!';

    expect($message)->toContain('Laravel');
});
<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    public function test_true_is_true(): void
    {
        $this->assertTrue(true);
    }

    public function test_string_contains_laravel(): void
    {
        $message = 'Hello, Laravel!';

        $this->assertStringContainsString('Laravel', $message);
    }
}

Häufige Assertions

PestPHPUnitBedeutung
expect($x)->toBe($y)$this->assertSame($y, $x)Streng identisch
expect($x)->toEqual($y)$this->assertEquals($y, $x)Gleich (ohne Typprüfung)
expect($x)->toBeTrue()$this->assertTrue($x)Ist true
expect($x)->toBeFalse()$this->assertFalse($x)Ist false
expect($x)->toBeNull()$this->assertNull($x)Ist null
expect($x)->toContain($y)$this->assertStringContainsString($y, $x)Enthält
expect($x)->toHaveCount($n)$this->assertCount($n, $x)Anzahl Elemente

HTTP-Tests

Laravels HTTP-Tests simulieren Requests, ohne dass ein echter HTTP-Server läuft. Sie kommen in Feature/-Tests zum Einsatz.

Seite anzeigen

get() sendet einen GET-Request und Sie prüfen die Antwort.
<?php

test('Startseite wird angezeigt', function () {
    $response = $this->get('/');

    $response->assertStatus(200);
});
<?php

namespace Tests\Feature;

use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function test_top_page_is_displayed(): void
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

Beispiel: HTTP-Tests einer ToDo-App

Angenommen, Sie haben ein Todo-Modell. So testen Sie CRUD:
<?php

use App\Models\Todo;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('ToDo-Liste wird angezeigt', function () {
    Todo::factory()->count(3)->create();

    $response = $this->get('/todos');

    $response->assertStatus(200);
    $response->assertSee('Liste');
});

test('ToDo lässt sich erstellen', function () {
    $response = $this->post('/todos', [
        'title' => 'Laravel lernen',
    ]);

    $response->assertRedirect('/todos');
    $this->assertDatabaseHas('todos', ['title' => 'Laravel lernen']);
});

test('ToDo lässt sich löschen', function () {
    $todo = Todo::factory()->create();

    $response = $this->delete("/todos/{$todo->id}");

    $response->assertRedirect('/todos');
    $this->assertDatabaseMissing('todos', ['id' => $todo->id]);
});
<?php

namespace Tests\Feature;

use App\Models\Todo;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class TodoTest extends TestCase
{
    use RefreshDatabase;

    public function test_todo_list_is_displayed(): void
    {
        Todo::factory()->count(3)->create();

        $response = $this->get('/todos');

        $response->assertStatus(200);
        $response->assertSee('Liste');
    }

    public function test_todo_can_be_created(): void
    {
        $response = $this->post('/todos', [
            'title' => 'Laravel lernen',
        ]);

        $response->assertRedirect('/todos');
        $this->assertDatabaseHas('todos', ['title' => 'Laravel lernen']);
    }

    public function test_todo_can_be_deleted(): void
    {
        $todo = Todo::factory()->create();

        $response = $this->delete("/todos/{$todo->id}");

        $response->assertRedirect('/todos');
        $this->assertDatabaseMissing('todos', ['id' => $todo->id]);
    }
}

Häufige Response-Assertions

MethodeBedeutung
assertStatus(200)HTTP-Statuscode
assertOk()Status ist 200
assertRedirect('/path')Redirect zu URL
assertSee('Text')Response enthält Text
assertDontSee('Text')Response enthält Text nicht
assertJson([...])JSON-Response prüfen
assertDatabaseHas('table', [...])Datensatz existiert
assertDatabaseMissing('table', [...])Datensatz existiert nicht
Der Trait RefreshDatabase setzt die Datenbank nach jedem Test zurück, damit sich Tests nicht gegenseitig beeinflussen.

Testumgebung

phpunit.xml

Die Testumgebung konfigurieren Sie in phpunit.xml im Projekt-Root. Standardmäßig sind Session und Cache auf array gesetzt, sodass keine Daten überleben.
<env name="APP_ENV" value="testing"/>
<env name="CACHE_STORE" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
Als Datenbank ist ein SQLite-In-Memory-Setup üblich:
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>

Datei .env.testing

Wenn Sie im Root eine .env.testing anlegen, wird sie bei Testläufen anstelle von .env geladen. Praktisch für spezielle Testdatenbanken oder externe Dienste.
APP_ENV=testing
DB_CONNECTION=sqlite
DB_DATABASE=:memory:
Ist der Konfigurations-Cache aktiv, führen Sie vor dem Testen php artisan config:clear aus, sonst greifen alte Werte.

Parallele Testausführung

Mit --parallel verkürzen Sie Laufzeiten, indem mehrere Prozesse gleichzeitig testen. Zuerst brianium/paratest installieren:
composer require brianium/paratest --dev
Dann:
php artisan test --parallel
Standardmäßig entstehen so viele Prozesse wie CPU-Kerne. Anzahl mit --processes steuern:
php artisan test --parallel --processes=4
Bei parallelen Tests benötigt jeder Prozess eine eigene Datenbank. RefreshDatabase in Kombination mit In-Memory-SQLite funktioniert dafür sehr gut.

Nächste Schritte

HTTP-Tests

Details zu Request-Simulation, authentifizierten Tests und JSON-Assertions.
Zuletzt geändert am 13. Juli 2026