Feature Testing in Laravel: A Beginner's Guide

Sohag HasanSohag Hasan
3 min read

Understanding Feature Testing - The Restaurant Analogy

Think of feature testing like being a food critic at a restaurant. Before giving a review, you test everything: from walking in the door, being seated, ordering food, to paying the bill. Similarly, in Laravel, feature testing ensures your application's entire features work correctly from start to finish.

Getting Started

Let's create our first feature test. Imagine we're building a simple todo list application.

php artisan make:test TodoTest

This creates a new test file in tests/Feature/TodoTest.php. Let's write our first test:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\Todo;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

class TodoTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_can_create_todo()
    {
        // Arrange
        $user = User::factory()->create();
        $todoData = [
            'title' => 'Buy groceries',
            'description' => 'Milk, bread, and eggs'
        ];

        // Act
        $response = $this->actingAs($user)
                        ->post('/todos', $todoData);

        // Assert
        $response->assertStatus(201);
        $this->assertDatabaseHas('todos', [
            'title' => 'Buy groceries',
            'user_id' => $user->id
        ]);
    }
}

Would you like me to explain the code above?

Best Practices

  1. Use Descriptive Test Names

    • Bad: test_create()

    • Good: test_user_can_create_todo()

  2. Follow AAA Pattern

    • Arrange: Set up your test data

    • Act: Perform the action

    • Assert: Verify the results

  3. Use Database Transactions

    • Always use RefreshDatabase trait for clean test environment

    • Each test should start with a fresh database

  4. Test Real-World Scenarios Think of real-life situations:

  • What if a user tries to create a todo without a title?

  • What if a user tries to view another user's private todos?

Here's an example testing invalid input:

public function test_todo_title_is_required()
{
    $user = User::factory()->create();
    $todoData = [
        'description' => 'Milk, bread, and eggs'
    ];

    $response = $this->actingAs($user)
                    ->post('/todos', $todoData);

    $response->assertStatus(422)
             ->assertJsonValidationErrors(['title']);
}

Would you like me to explain this code as well?

Common Testing Methods

  • get('/url') - Like visiting a webpage

  • post('/url', $data) - Like submitting a form

  • put('/url', $data) - Like updating your profile

  • delete('/url') - Like deleting a post

  • assertStatus($code) - Checking if the operation was successful

  • assertSee($text) - Checking if text appears on the page

Real-Life Example: Testing a Shopping Cart

Imagine testing a shopping cart feature - it's like checking if a physical shopping cart works:

public function test_user_can_add_item_to_cart()
{
    $user = User::factory()->create();
    $product = Product::factory()->create([
        'name' => 'Coffee Mug',
        'price' => 9.99
    ]);

    $response = $this->actingAs($user)
                    ->post('/cart/add', [
                        'product_id' => $product->id,
                        'quantity' => 2
                    ]);

    $response->assertStatus(200);
    $this->assertDatabaseHas('cart_items', [
        'user_id' => $user->id,
        'product_id' => $product->id,
        'quantity' => 2
    ]);
}

Would you like me to explain this code?

Running Your Tests

# Run all tests
php artisan test

# Run a specific test class
php artisan test --filter TodoTest

# Run a specific test method
php artisan test --filter test_user_can_create_todo

Topics to Explore Further

  1. Testing Fundamentals

    • PHPUnit basics

    • Test-Driven Development (TDD)

    • Behavior-Driven Development (BDD)

  2. Advanced Testing

    • Mocking

    • Database seeding

    • Testing APIs

    • Browser testing with Laravel Dusk

  3. Testing Best Practices

    • Test coverage

    • Continuous Integration

    • Testing patterns

  4. Related Tools

    • PHPUnit

    • Pest

    • Laravel Dusk

    • Faker

    • Database factories

Conclusion

Feature testing might seem overwhelming at first, but think of it as writing a checklist for your application. Just like you'd check if you've packed everything before a trip, tests verify if your application works as expected.

Remember: A well-tested application is like a well-inspected car - you can trust it to work reliably when you need it.

0
Subscribe to my newsletter

Read articles from Sohag Hasan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sohag Hasan
Sohag Hasan

WhoAmI => notes.sohag.pro/author