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

# Introductie testen

> Hoe je tests schrijft voor Laravel-applicaties met Pest en PHPUnit

## Wat is testen

Testen is een mechanisme waarmee je automatisch verifieert of je code zich gedraagt zoals verwacht.
Door tests te schrijven controleer je snel of bestaand gedrag niet kapot is gegaan na het toevoegen van functionaliteit of het doorvoeren van fixes.
In teamverband zorgen tests ervoor dat je met vertrouwen code kunt wijzigen en reviewen.

Laravel heeft testondersteuning vanaf het begin ingebouwd; je kunt zowel [Pest](https://pestphp.com) als [PHPUnit](https://phpunit.de) gebruiken.
Bij een nieuwe installatie staan het configuratiebestand `phpunit.xml` en de map `tests/` automatisch klaar.

<Tip>
  Pest is gebouwd bovenop PHPUnit en laat je tests schrijven met een beknoptere, beter leesbare syntax. Begin je nu met testen, dan is Pest de aanbevolen keuze.
</Tip>

## De structuur van de map `tests/`

```
tests/
├── Feature/      # Featuretests
│   └── ExampleTest.php
├── Unit/         # Unittests
│   └── ExampleTest.php
└── TestCase.php
```

* **`Feature/`** — hier plaats je featuretests. Voor tests van grotere eenheden, inclusief HTTP-requests. Denk aan gedrag waarbij meerdere objecten samenwerken of het verifiëren van API-endpoints — tests die dicht bij de hele applicatie staan. **De meeste tests komen hier terecht.**
* **`Unit/`** — hier plaats je unittests. Voor tests van kleine eenheden, zoals een enkele klasse of methode. De Laravel-applicatie wordt niet opgestart, dus de database en andere frameworkfunctionaliteit zijn niet beschikbaar.

## Tests maken

Met het Artisan-commando `make:test` genereer je een nieuwe testklasse.

```shell theme={null}
# Een featuretest maken (standaard)
php artisan make:test TodoTest

# Een unittest maken
php artisan make:test TodoTest --unit
```

Er wordt een `tests/Feature/TodoTest.php` gegenereerd.

## Tests uitvoeren

Voer de tests uit met het commando `php artisan test`.

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

Rechtstreeks `vendor/bin/pest` of `vendor/bin/phpunit` uitvoeren geeft hetzelfde resultaat, maar `php artisan test` heeft overzichtelijkere output en wordt daarom aanbevolen.

Wil je alleen een specifieke testsuite uitvoeren, gebruik dan opties.

```shell theme={null}
# Alleen featuretests uitvoeren
php artisan test --testsuite=Feature

# Direct stoppen bij een mislukking
php artisan test --stop-on-failure
```

## De basis van tests schrijven

Een voorbeeld van eenvoudige assertions.

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

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

  test('controleer of de string erin zit', 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>

### Veelgebruikte assertions

| Pest                          | PHPUnit                                     | Beschrijving                      |
| ----------------------------- | ------------------------------------------- | --------------------------------- |
| `expect($x)->toBe($y)`        | `$this->assertSame($y, $x)`                 | Strikt gelijk                     |
| `expect($x)->toEqual($y)`     | `$this->assertEquals($y, $x)`               | Gelijk (type maakt niet uit)      |
| `expect($x)->toBeTrue()`      | `$this->assertTrue($x)`                     | Is `true`                         |
| `expect($x)->toBeFalse()`     | `$this->assertFalse($x)`                    | Is `false`                        |
| `expect($x)->toBeNull()`      | `$this->assertNull($x)`                     | Is `null`                         |
| `expect($x)->toContain($y)`   | `$this->assertStringContainsString($y, $x)` | Bevat de string                   |
| `expect($x)->toHaveCount($n)` | `$this->assertCount($n, $x)`                | Het aantal elementen komt overeen |

## HTTP-tests

Met de HTTP-tests van Laravel simuleer je requests naar routes zonder een echte HTTP-server op te zetten.
Krachtige functionaliteit die beschikbaar is in de testklassen van de map `Feature/`.

### Controleren of een pagina wordt weergegeven

Met de methode `get()` verstuur je een GET-request en verifieer je de response.

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

  test('de startpagina wordt weergegeven', 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>

### Voorbeeld van HTTP-tests voor een todo-app

Aan de hand van een applicatie met een `Todo`-model testen we de verschillende CRUD-operaties.

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

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

  uses(RefreshDatabase::class);

  test('de todo-overzichtspagina wordt weergegeven', function () {
      Todo::factory()->count(3)->create();

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

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

  test('een todo kan worden aangemaakt', function () {
      $response = $this->post('/todos', [
          'title' => 'Laravel leren',
      ]);

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

  test('een todo kan worden verwijderd', 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('Lijst');
      }

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

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

      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>

### Veelgebruikte response-assertions

| Methode                                 | Beschrijving                                          |
| --------------------------------------- | ----------------------------------------------------- |
| `assertStatus(200)`                     | Controleert de HTTP-statuscode van de response        |
| `assertOk()`                            | Controleert of de statuscode 200 is                   |
| `assertRedirect('/path')`               | Controleert de redirect naar de opgegeven URL         |
| `assertSee('tekst')`                    | Controleert of de tekst in de responsebody staat      |
| `assertDontSee('tekst')`                | Controleert of de tekst niet in de responsebody staat |
| `assertJson([...])`                     | Controleert de data van een JSON-response             |
| `assertDatabaseHas('table', [...])`     | Controleert of het record in de database bestaat      |
| `assertDatabaseMissing('table', [...])` | Controleert of het record niet in de database bestaat |

<Info>
  Met de trait `RefreshDatabase` wordt de database na elke test gereset. Je gebruikt deze om te voorkomen dat data tussen tests interfereert.
</Info>

## De testomgeving

### De configuratie van `phpunit.xml`

De configuratie van de testomgeving regel je in `phpunit.xml` in de projectroot.
Standaard zijn sessies en cache ingesteld op de `array`-driver, zodat er geen data achterblijft tijdens de tests.

```xml theme={null}
<env name="APP_ENV" value="testing"/>
<env name="CACHE_STORE" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
```

Voor de database is het gebruikelijk om de in-memory database van SQLite te gebruiken, die geen bestanden achterlaat.

```xml theme={null}
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
```

### Het `.env.testing`-bestand

Maak je een `.env.testing`-bestand in de projectroot, dan wordt dat bij het draaien van tests geladen in plaats van `.env`.
Handig als je een aparte databaseverbinding of configuratie van externe diensten wilt voor je tests.

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

<Warning>
  Heb je je configuratie gecachet, voer dan `php artisan config:clear` uit voordat je tests draait. Anders kan een oude cache worden gebruikt waardoor de configuratie niet doorwerkt.
</Warning>

## Tests parallel uitvoeren

Naarmate het aantal tests groeit, neemt de uitvoeringstijd toe.
Met de optie `--parallel` voer je tests gelijktijdig uit in meerdere processen en bespaar je tijd.

Installeer eerst het pakket `brianium/paratest`.

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

Voer daarna uit met de optie `--parallel`.

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

Standaard worden er evenveel processen gestart als je CPU cores heeft. Het aantal processen geef je op met de optie `--processes`.

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

<Tip>
  Bij parallel testen moet elk proces een eigen database gebruiken. De combinatie van de trait `RefreshDatabase` en de in-memory SQLite-configuratie in `phpunit.xml` werkt probleemloos.
</Tip>

## Volgende stap

<Card title="HTTP-tests" icon="arrow-right" href="/nl/http-tests">
  Bekijk meer gedetailleerde HTTP-testtechnieken, zoals het simuleren van requests, testen met authenticatie en JSON-assertions.
</Card>


## Related topics

- [Geavanceerd testen met Pest](/nl/advanced/testing-pest.md)
- [Testen](/nl/packages/laravel-bluesky/testing.md)
- [Aan de slag met Laravel-testen in Pest PHP](/nl/blog/pest-introduction.md)
- [HTTP-tests](/nl/http-tests.md)
- [⚡Introductie van Livewire 4 — reactieve UI's bouwen zonder JavaScript](/nl/blog/livewire-introduction.md)
