Bird
Raised Fist0
Laravelframework~15 mins

Feature tests in Laravel - Deep Dive

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Overview - Feature tests
What is it?
Feature tests in Laravel are automated tests that check if different parts of your application work together correctly. They simulate user actions like visiting pages, submitting forms, or interacting with APIs to ensure the app behaves as expected. These tests cover multiple layers, including routes, controllers, middleware, and views. They help catch bugs before users do.
Why it matters
Without feature tests, developers might miss bugs that only appear when different parts of the app interact. This can lead to broken pages, failed user actions, or security holes in production. Feature tests give confidence that the app works as a whole, saving time and frustration by catching problems early. They make maintaining and updating the app safer and faster.
Where it fits
Before learning feature tests, you should understand basic PHP and Laravel fundamentals like routing, controllers, and views. Knowing unit testing basics helps but is not required. After mastering feature tests, you can explore advanced testing topics like browser tests with Laravel Dusk or continuous integration setups. Feature tests sit between unit tests and full browser tests in the testing journey.
Mental Model
Core Idea
Feature tests simulate real user actions to verify that multiple parts of a Laravel app work together correctly.
Think of it like...
Feature tests are like a dress rehearsal for a play, where actors practice together to make sure the whole performance runs smoothly before the audience sees it.
┌───────────────┐
│ User Action   │
└──────┬────────┘
       │ Simulate
       ▼
┌───────────────┐
│ Feature Test  │
│ (HTTP Request)│
└──────┬────────┘
       │ Triggers
       ▼
┌───────────────┐
│ Laravel App   │
│ (Routes,      │
│ Controllers,  │
│ Middleware)   │
└──────┬────────┘
       │ Returns
       ▼
┌───────────────┐
│ Response      │
│ (View, JSON)  │
└───────────────┘
Build-Up - 7 Steps
1
FoundationWhat are Feature Tests in Laravel
🤔
Concept: Introduce the idea of feature tests as tests that check the app's behavior from the user's perspective.
Feature tests send HTTP requests to your Laravel app and check the responses. They test routes, controllers, middleware, and views working together. For example, a feature test can visit the homepage and check if it shows the welcome message.
Result
You understand that feature tests simulate user requests and check the app's full response.
Understanding that feature tests cover multiple parts of the app together helps you see why they catch bugs unit tests might miss.
2
FoundationSetting Up Feature Tests in Laravel
🤔
Concept: Learn how to create and run a basic feature test using Laravel's built-in testing tools.
Laravel uses PHPUnit for testing. You create feature tests in the tests/Feature folder. Use the artisan command: php artisan make:test ExampleTest --feature. Inside the test, you write methods that send HTTP requests using $this->get('/'). Then use assertions like assertStatus(200) to check the response.
Result
You can create and run a simple feature test that checks a page loads successfully.
Knowing how to set up tests and run them is the first step to building reliable apps with automated checks.
3
IntermediateUsing Assertions to Verify Responses
🤔Before reading on: do you think assertSee checks HTML content or JSON data? Commit to your answer.
Concept: Learn how to use different assertions to check the content and status of HTTP responses in feature tests.
Laravel provides many assertions like assertStatus(200) to check HTTP status, assertSee('text') to check if response contains text, assertJson() to check JSON structure, and assertRedirect() to verify redirects. Combining these lets you test exactly what the user would see or receive.
Result
You can write tests that confirm pages show correct content, APIs return expected data, and redirects happen properly.
Understanding assertions lets you precisely verify app behavior from the user's view, making tests meaningful and reliable.
4
IntermediateTesting Form Submissions and Validation
🤔Before reading on: do you think feature tests can simulate submitting forms and checking validation errors? Commit to yes or no.
Concept: Feature tests can simulate POST requests with form data and check if validation works and data is saved.
Use $this->post('/route', ['field' => 'value']) to simulate form submission. Then assert the response redirects or shows errors with assertSessionHasErrors(). You can also check database changes with assertDatabaseHas() to confirm data saved correctly.
Result
You can test user input handling, validation feedback, and database updates through feature tests.
Knowing how to test forms ensures your app handles user input safely and correctly, preventing bugs and bad data.
5
IntermediateUsing Factories and Seeders in Feature Tests
🤔Before reading on: do you think feature tests require real database data or can use fake data? Commit to your answer.
Concept: Feature tests often use model factories and seeders to create fake data for testing without affecting real data.
Laravel factories let you generate fake model instances with fake data. In tests, you can create users or posts with User::factory()->create(). This data is used during the test and rolled back after. Seeders can prepare common data sets for tests.
Result
You can write tests that rely on realistic data without manual setup, making tests faster and cleaner.
Using factories and seeders in tests helps simulate real app scenarios while keeping tests isolated and repeatable.
6
AdvancedHandling Authentication in Feature Tests
🤔Before reading on: do you think feature tests can simulate logged-in users easily? Commit to yes or no.
Concept: Feature tests can simulate authenticated users to test protected routes and actions.
Laravel provides actingAs($user) to simulate a logged-in user in tests. You create a user with a factory, then call $this->actingAs($user)->get('/dashboard'). This lets you test pages or actions that require login without manual login steps.
Result
You can test user-specific features and permissions reliably in feature tests.
Knowing how to simulate authentication in tests lets you cover security and user experience scenarios fully.
7
ExpertOptimizing Feature Tests for Speed and Reliability
🤔Before reading on: do you think running many feature tests slows down development? Commit to yes or no.
Concept: Learn techniques to keep feature tests fast and reliable in large Laravel projects.
Feature tests can be slow because they touch many parts of the app and database. Use in-memory SQLite for faster tests. Use RefreshDatabase trait to reset state. Avoid unnecessary database writes. Group related tests and run only changed tests during development. Mock external services to avoid delays.
Result
You maintain a fast test suite that developers trust and run often.
Understanding test optimization prevents slow feedback loops and keeps testing practical in real projects.
Under the Hood
Feature tests work by simulating HTTP requests inside Laravel's testing environment. When a test sends a request, Laravel boots the application, processes the request through routing, middleware, controllers, and views, then returns a response. The test captures this response and runs assertions on it. The database is usually reset between tests to keep state clean. This process mimics a real user interaction but runs entirely in code without a browser.
Why designed this way?
Laravel's feature tests were designed to provide a balance between speed and realism. Unit tests are fast but isolated; browser tests are realistic but slow. Feature tests simulate real HTTP requests without a browser, giving a practical way to test app behavior end-to-end. This design helps developers catch integration bugs early while keeping tests fast enough for daily use.
┌───────────────┐
│ Test Method   │
│ (Sends HTTP)  │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Laravel App   │
│ Bootstraps    │
│ Request Flow  │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Middleware    │
│ Controllers   │
│ Views         │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Response      │
│ Captured by   │
│ Test          │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do feature tests only check one function or method at a time? Commit to yes or no.
Common Belief:Feature tests only test single functions or methods in isolation.
Tap to reveal reality
Reality:Feature tests check how multiple parts of the app work together by simulating full HTTP requests and responses.
Why it matters:Believing this limits test scope and leads to missing bugs that happen when components interact.
Quick: Do you think feature tests require a real browser to run? Commit to yes or no.
Common Belief:Feature tests need a real browser to simulate user actions.
Tap to reveal reality
Reality:Feature tests run HTTP requests inside Laravel without a browser; browser tests (like Laravel Dusk) use real browsers.
Why it matters:Confusing these leads to unnecessary complexity and slower tests when simpler feature tests suffice.
Quick: Do you think feature tests always slow down development significantly? Commit to yes or no.
Common Belief:Feature tests are too slow to run often during development.
Tap to reveal reality
Reality:With proper setup like in-memory databases and test optimization, feature tests can run quickly and be part of daily workflows.
Why it matters:Avoiding feature tests due to speed fears reduces test coverage and increases risk of bugs.
Quick: Do you think feature tests automatically clean up database changes after each test? Commit to yes or no.
Common Belief:Feature tests do not reset database state between tests automatically.
Tap to reveal reality
Reality:Laravel provides traits like RefreshDatabase to reset the database after each test, keeping tests isolated.
Why it matters:Not resetting database state causes flaky tests and false failures.
Expert Zone
1
Feature tests can be combined with mocking to isolate external services while still testing app integration.
2
Using database transactions in tests can speed up resets but may not work with some database drivers or external services.
3
The order of middleware can affect feature test results, so tests can reveal subtle bugs in middleware stacking.
When NOT to use
Feature tests are not ideal for testing very small units of code where unit tests are faster and clearer. For full browser interaction like JavaScript-heavy UI, use Laravel Dusk or other browser testing tools instead. When testing external APIs, prefer mocking or integration tests to avoid flaky network calls.
Production Patterns
In real projects, feature tests cover critical user flows like login, registration, and purchases. They run in CI pipelines on every code push to catch regressions early. Teams use database factories and seeders to prepare test data. Tests are grouped by feature areas and tagged for selective runs. Mocking external APIs is common to keep tests reliable.
Connections
Unit Testing
Feature tests build on unit testing by combining multiple units to test their interaction.
Understanding unit tests helps grasp how feature tests cover broader app behavior beyond isolated functions.
Continuous Integration (CI)
Feature tests are often run automatically in CI pipelines to ensure app stability after code changes.
Knowing CI workflows shows how feature tests fit into professional development and deployment processes.
System Testing in Software Engineering
Feature tests are a form of system testing focused on verifying complete user scenarios within the app.
Recognizing feature tests as system tests helps appreciate their role in quality assurance beyond code correctness.
Common Pitfalls
#1Writing feature tests that depend on real external APIs causing flaky failures.
Wrong approach:$this->get('/api/data')->assertStatus(200); // calls real API
Correct approach:Http::fake(); $this->get('/api/data')->assertStatus(200); // mocks API
Root cause:Not isolating tests from external dependencies leads to unreliable test results.
#2Not resetting database state between tests causing tests to fail unpredictably.
Wrong approach:class ExampleTest extends TestCase { public function testA() { User::factory()->create(); } public function testB() { $this->assertDatabaseCount('users', 0); } }
Correct approach:use RefreshDatabase; class ExampleTest extends TestCase { public function testA() { User::factory()->create(); } public function testB() { $this->assertDatabaseCount('users', 0); } }
Root cause:Missing database reset trait causes leftover data to affect other tests.
#3Testing too many things in one feature test making failures hard to diagnose.
Wrong approach:public function testFullUserFlow() { $this->post('/register', [...]); $this->post('/login', [...]); $this->get('/dashboard')->assertSee('Welcome'); }
Correct approach:Separate tests for registration, login, and dashboard access each focusing on one behavior.
Root cause:Lack of test focus reduces clarity and maintainability.
Key Takeaways
Feature tests simulate real user requests to verify that multiple parts of a Laravel app work together correctly.
They help catch bugs that unit tests miss by testing routes, controllers, middleware, and views as a whole.
Laravel makes writing feature tests easy with built-in HTTP request simulation and many helpful assertions.
Using factories, authentication helpers, and database reset traits keeps feature tests reliable and maintainable.
Optimizing feature tests for speed and isolation ensures they remain practical for daily development and CI pipelines.

Practice

(1/5)
1. What is the main purpose of Feature tests in Laravel?
easy
A. To test how the application behaves from the user's perspective
B. To check the syntax of PHP code
C. To test database migrations only
D. To optimize application performance

Solution

  1. Step 1: Understand the role of feature tests

    Feature tests simulate user actions and check the app's responses to ensure it works as expected.
  2. Step 2: Compare with other test types

    Unlike unit tests or migration tests, feature tests focus on user experience and request handling.
  3. Final Answer:

    To test how the application behaves from the user's perspective -> Option A
  4. Quick Check:

    Feature tests = user behavior testing [OK]
Hint: Feature tests simulate user requests and responses [OK]
Common Mistakes:
  • Confusing feature tests with unit tests
  • Thinking feature tests only check database
  • Assuming feature tests optimize performance
2. Which of the following is the correct way to start a feature test method in Laravel?
easy
A. public testUserCanLogin()
B. function testUserCanLogin()
C. public function testUserCanLogin()
D. def testUserCanLogin()

Solution

  1. Step 1: Recall Laravel test method syntax

    Laravel feature test methods must be public and start with 'test' or have the @test annotation.
  2. Step 2: Identify correct PHP method declaration

    Only 'public function testUserCanLogin()' is valid PHP syntax for a test method in Laravel.
  3. Final Answer:

    public function testUserCanLogin() -> Option C
  4. Quick Check:

    Test methods are public functions [OK]
Hint: Test methods must be public functions starting with 'test' [OK]
Common Mistakes:
  • Omitting 'public' keyword
  • Using wrong function declaration syntax
  • Using Python style 'def' keyword
3. Given this Laravel feature test code:
public function testHomePageReturnsOk()
{
    $response = $this->get('/');
    $response->assertStatus(200);
}

What does this test check?
medium
A. The home page returns a 404 error
B. The home page returns a 200 OK status
C. The home page redirects to login
D. The home page returns JSON data

Solution

  1. Step 1: Analyze the HTTP request in the test

    The test sends a GET request to '/' (home page).
  2. Step 2: Check the assertion

    The test asserts the response status is 200, meaning OK.
  3. Final Answer:

    The home page returns a 200 OK status -> Option B
  4. Quick Check:

    assertStatus(200) means success [OK]
Hint: assertStatus(200) means page loaded successfully [OK]
Common Mistakes:
  • Confusing 200 with 404 or redirect codes
  • Assuming JSON response without checking
  • Misreading the URL path
4. What is wrong with this Laravel feature test code?
public function testUserRegistration()
{
    $response = $this->post('/register', [
        'email' => 'user@example.com',
        'password' => 'secret',
    ]);
    $response->assertRedirect('/home');
}
medium
A. Missing CSRF token in the post request
B. Password should be hashed before sending
C. Password field should be 'password_confirmation' instead of 'password'
D. The test method is missing the 'public' keyword

Solution

  1. Step 1: Understand Laravel's CSRF protection

    Laravel requires a CSRF token for POST requests to prevent attacks.
  2. Step 2: Check test request handling

    Feature tests use the 'web' middleware group by default, which includes CSRF protection. The $this->post() method does not automatically include a CSRF token, so the test will fail unless the token is provided or middleware is disabled.
  3. Step 3: Identify the actual issue

    Since the test does not disable middleware, missing CSRF token causes failure.
  4. Final Answer:

    Missing CSRF token in the post request -> Option A
  5. Quick Check:

    POST requests need CSRF token unless middleware disabled [OK]
Hint: Remember CSRF token is needed for POST requests [OK]
Common Mistakes:
  • Assuming password must be hashed in test input
  • Confusing password and password_confirmation fields
  • Ignoring middleware effects on tests
5. You want to test a feature where a logged-in user can update their profile. Which sequence correctly sets up the test in Laravel feature tests?
hard
A. Assert redirect -> Create user -> Send POST request -> Act as user
B. Send POST request to update route -> Create user -> Assert redirect -> Act as user
C. Act as user -> Assert redirect -> Create user -> Send POST request
D. Create user -> Act as user -> Send POST request to update route -> Assert redirect

Solution

  1. Step 1: Create a user to simulate logged-in state

    First, create a user instance in the database for authentication.
  2. Step 2: Use actingAs() to simulate logged-in user

    Use $this->actingAs($user) to run requests as that user.
  3. Step 3: Send POST request to update profile route

    Send the update request while acting as the user.
  4. Step 4: Assert the response redirects as expected

    Check that the response redirects to the correct page after update.
  5. Final Answer:

    Create user -> Act as user -> Send POST request to update route -> Assert redirect -> Option D
  6. Quick Check:

    Setup user then act as user before request [OK]
Hint: Create user first, then act as user before request [OK]
Common Mistakes:
  • Sending request before acting as user
  • Not creating user before acting as user
  • Asserting redirect before sending request