> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Einstieg in Tests

> Wie Sie Laravel-Anwendungen mit Pest und PHPUnit testen

## 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](https://pestphp.com) oder [PHPUnit](https://phpunit.de).
Nach einer Neuinstallation existieren `phpunit.xml` und das Verzeichnis `tests/` bereits.

<Tip>
  Pest basiert auf PHPUnit und bietet eine kompaktere, gut lesbare Syntax. Wenn Sie neu einsteigen, ist Pest eine gute Wahl.
</Tip>

## 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`.

```shell theme={null}
# 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`.

```shell theme={null}
php artisan test
```

`vendor/bin/pest` oder `vendor/bin/phpunit` funktionieren genauso; `php artisan test` liefert die schönere Ausgabe.

Optionen zum Filtern:

```shell theme={null}
# 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:

<CodeGroup>
  ```php Pest theme={null}
  <?php

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

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

      expect($message)->toContain('Laravel');
  });
  ```

  ```php PHPUnit theme={null}
  <?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);
      }
  }
  ```
</CodeGroup>

### Häufige Assertions

| Pest                          | PHPUnit                                     | Bedeutung                |
| ----------------------------- | ------------------------------------------- | ------------------------ |
| `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.

<CodeGroup>
  ```php Pest theme={null}
  <?php

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

      $response->assertStatus(200);
  });
  ```

  ```php PHPUnit theme={null}
  <?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);
      }
  }
  ```
</CodeGroup>

### Beispiel: HTTP-Tests einer ToDo-App

Angenommen, Sie haben ein `Todo`-Modell. So testen Sie CRUD:

<CodeGroup>
  ```php Pest theme={null}
  <?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 PHPUnit theme={null}
  <?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]);
      }
  }
  ```
</CodeGroup>

### Häufige Response-Assertions

| Methode                                 | Bedeutung                   |
| --------------------------------------- | --------------------------- |
| `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   |

<Info>
  Der Trait `RefreshDatabase` setzt die Datenbank nach jedem Test zurück, damit sich Tests nicht gegenseitig beeinflussen.
</Info>

## 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.

```xml theme={null}
<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:

```xml theme={null}
<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.

```ini theme={null}
APP_ENV=testing
DB_CONNECTION=sqlite
DB_DATABASE=:memory:
```

<Warning>
  Ist der Konfigurations-Cache aktiv, führen Sie vor dem Testen `php artisan config:clear` aus, sonst greifen alte Werte.
</Warning>

## Parallele Testausführung

Mit `--parallel` verkürzen Sie Laufzeiten, indem mehrere Prozesse gleichzeitig testen.

Zuerst `brianium/paratest` installieren:

```shell theme={null}
composer require brianium/paratest --dev
```

Dann:

```shell theme={null}
php artisan test --parallel
```

Standardmäßig entstehen so viele Prozesse wie CPU-Kerne. Anzahl mit `--processes` steuern:

```shell theme={null}
php artisan test --parallel --processes=4
```

<Tip>
  Bei parallelen Tests benötigt jeder Prozess eine eigene Datenbank. `RefreshDatabase` in Kombination mit In-Memory-SQLite funktioniert dafür sehr gut.
</Tip>

## Nächste Schritte

<Card title="HTTP-Tests" icon="arrow-right" href="/de/http-tests">
  Details zu Request-Simulation, authentifizierten Tests und JSON-Assertions.
</Card>


## Related topics

- [Fortgeschrittenes Testen mit Pest](/de/advanced/testing-pest.md)
- [React – Einstieg mit Inertia × Laravel](/de/blog/react-introduction.md)
- [Svelte – Einstieg mit Inertia × Laravel](/de/blog/svelte-introduction.md)
- [Laravel-Tests mit Pest PHP starten](/de/blog/pest-introduction.md)
- [Vue.js – Einstieg mit Inertia × Laravel](/de/blog/vue-introduction.md)
