By the end, issuing an invoice fails the suite when the feature breaks. A feature test checks one thing a person can do, through the same door they use. For an invoice, that door is an HTTP request. The test does not call a private method, and it does not care which line of the controller wrote the row.
Test-driven Laravel · Lesson 1
What a feature test is for
Video
01 Name it for the outcome
If the feature disappeared, this test would fail. That is the check that the test is aimed at the behaviour rather than at the framework.
it('issues an invoice for the signed-in team', function () {
$user = User::factory()->create();
$this->actingAs($user)
->post('/invoices', [
'number' => 'INV-1042',
'issued_on' => '2026-10-22',
])
->assertRedirect();
});One test, one outcome. A second behaviour, such as “a guest is redirected to login”, is a second test. Mixing them makes a failure tell you less about what broke.
02 A guest is a second test
The signed-in test above never sees the login redirect. A guest test leaves actingAs() off and asserts the redirect Laravel’s auth middleware actually returns. It does not assert a saved invoice, because the interesting fact is that no invoice was written.
it('sends a guest to login', function () {
$this->post('/invoices', [
'number' => 'INV-1042',
'issued_on' => '2026-10-22',
])->assertRedirect('/login');
$this->assertDatabaseCount('invoices', 0);
});If this test fails on the redirect, the route lost its middleware. If it fails on the count, the controller stored a row before the middleware ran. Those are different bugs, which is why they are not folded into the test that checks a team’s invoice number. A feature test that never makes an HTTP call is a unit test of a class. This series is about the request.
Recap
You can name a test for one outcome a person would notice, and send the HTTP request they would send.
- One behaviour per test. A guest redirect is a second test.
- A feature test that never makes a request is a unit test of a class.
- The count and the redirect fail for different bugs. Keep them where the failure is readable.
Check yourself · 3 questions
Question 1 of 3The guest test and the signed-in test are one method. It fails. What do you know?