Why write tests?
Tests verify that your code behaves as expected and alert you when changes break existing functionality. In team projects, a good test suite lets everyone refactor and ship with confidence. Laravel has first-class support for testing built in. Every new project ships with aphpunit.xml configuration file and a tests/ directory, and supports both Pest and PHPUnit.
The tests/ directory
Feature/— Tests that cover larger units of functionality, including HTTP requests. Most of your tests will live here.Unit/— Tests for individual classes or methods in isolation. The Laravel application is not booted, so these tests cannot use the database or other framework features.
Creating tests
Use themake:test Artisan command to generate a new test file:
Running tests
Run all tests with:vendor/bin/pest or vendor/bin/phpunit directly, but php artisan test produces more readable output.
Useful options:
Writing tests
Basic assertions
Common assertions
| Pest | PHPUnit | Description |
|---|---|---|
expect($x)->toBe($y) | $this->assertSame($y, $x) | Strictly equal |
expect($x)->toEqual($y) | $this->assertEquals($y, $x) | Equal (type-coerced) |
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) | String contains value |
expect($x)->toHaveCount($n) | $this->assertCount($n, $x) | Collection has N items |
HTTP tests
Laravel’s HTTP testing tools let you simulate requests to your application without running a real HTTP server. This is done insideFeature/ tests.
Testing a page response
Testing CRUD operations
Using aPost model as an example:
Useful response assertions
| Method | Description |
|---|---|
assertStatus(200) | Assert the response has the given status code |
assertOk() | Assert status code is 200 |
assertRedirect('/path') | Assert a redirect to the given URL |
assertSee('text') | Assert the response body contains the given text |
assertDontSee('text') | Assert the response body does not contain the text |
assertJson([...]) | Assert the JSON response contains the given data |
assertDatabaseHas('table', [...]) | Assert a record exists in the database |
assertDatabaseMissing('table', [...]) | Assert a record does not exist in the database |
The
RefreshDatabase trait resets the database after each test, preventing data from one test leaking into another.Testing authenticated routes
UseactingAs() to authenticate a user for a test:
Test environment configuration
phpunit.xml
The phpunit.xml file at the project root configures the test environment. By default, the session and cache use the array driver so data is not persisted between requests:
.env.testing
Create a .env.testing file at the project root to override environment variables specifically for the test environment. Laravel loads this file instead of .env when running tests:
Running tests in parallel
As your test suite grows, execution time increases. The--parallel flag runs tests across multiple processes simultaneously. First install the brianium/paratest package, then use the flag:
--processes:
Next steps
HTTP testing
Explore advanced HTTP testing — authenticated requests, JSON assertions, file uploads, and more.