Feature Testing in Laravel: A Beginner's Guide
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
Use Descriptive Test Names
Bad:
test_create()
Good:
test_user_can_create_todo()
Follow AAA Pattern
Arrange: Set up your test data
Act: Perform the action
Assert: Verify the results
Use Database Transactions
Always use
RefreshDatabase
trait for clean test environmentEach test should start with a fresh database
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 webpagepost('/url', $data)
- Like submitting a formput('/url', $data)
- Like updating your profiledelete('/url')
- Like deleting a postassertStatus($code)
- Checking if the operation was successfulassertSee($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
Testing Fundamentals
PHPUnit basics
Test-Driven Development (TDD)
Behavior-Driven Development (BDD)
Advanced Testing
Mocking
Database seeding
Testing APIs
Browser testing with Laravel Dusk
Testing Best Practices
Test coverage
Continuous Integration
Testing patterns
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.
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