Stop manually refreshing your browser to verify features. Learn how to write your first Laravel feature test using PEST to automate assertions and save time.
Previously in this course, we refactored our Task Manager: Refactoring for Clean Code to keep our controllers lean and maintainable. Now, we’ll move from manual browser testing to automated verification.
Testing is the difference between a project that works "on my machine" and one that works in production. By writing tests, you create a safety net that warns you immediately if a new feature breaks an existing one. In Laravel, we primarily use two tools for this: PHPUnit (the industry-standard engine) and PEST (a delightful, expressive testing framework built on top of PHPUnit).
In Laravel, we distinguish between Unit Tests (testing a single method in isolation) and Feature Tests (testing a full request-to-response cycle). For a beginner, Feature Tests are your best friend. They simulate a real user hitting your routes, filling out forms, and seeing data in the database.
If you’ve explored other ecosystems, you might recognize these concepts from Introduction to Testing: Quality Assurance in React with Jest, but here we apply them to server-side logic and database persistence.
Laravel comes pre-installed with PEST. To create your first test, run this command in your terminal:
Bashphp artisan make:test TaskTest --pest
This generates a file in tests/Feature/TaskTest.php. Open it up, and you'll see a basic test structure. Let’s write a test to ensure our "Index" page loads correctly.
PHPtest('the tasks page returns a successful response', function () { $response = $this->get('/tasks'); $response->assertStatus(200); });
Here, we are:
$this->get('/tasks') simulates a visitor hitting that URL.assertStatus(200) checks that the server responded with an "OK" status.To run this test, execute php artisan test in your terminal. You should see a green output confirming your test passed.
Testing the response status is only the beginning. Often, you need to verify that your application is actually saving data to the database. We use the assertDatabaseHas assertion for this.
Let’s add a test to verify that we can create a task:
PHPuse App\Models\Task; test('a user can create a task', function () { $this->post('/tasks', [ 'title' => 'Buy milk', 'description' => 'Go to the store' ]); $this->assertDatabaseHas('tasks', [ 'title' => 'Buy milk', ]); });
In this example, we send a POST request to our store route. Immediately after, we check the tasks table to ensure the record exists. Laravel automatically wraps these tests in a database transaction, meaning it rolls back the changes after the test finishes—your database stays clean!
tests/Feature/TaskTest.php./tasks route and asserts that the page contains the text "My Tasks" (you can use $response->assertSee('My Tasks')).php artisan test to confirm it passes.Illuminate\Foundation\Testing\RefreshDatabase trait (though PEST usually handles this automatically).We've covered the basics of automated testing in Laravel. We used PEST to verify that our routes respond with a 200 status code and confirmed that our database operations successfully persist data. By mastering these basics, you're building a foundation for a robust, professional-grade application.
Up next: Testing Forms and Validation — where we'll simulate user input and ensure our validation rules actually catch bad data.
Learn to use DB::transaction to ensure data integrity in your Laravel apps. Prevent partial state updates by wrapping complex operations in atomic blocks.
Read moreLearn to prepare your Laravel app for production. Master configuration caching, route optimization, and essential security settings to go live with confidence.
Introduction to Testing
Managing Assets in Production
Task Manager: Deployment Preparation