Automated Testing in Laravel for Beginners

Many beginner developers see automated testing as extra work that wastes time. The reality is the opposite: a test written once keeps your feature correct forever. Every time you c...

Automated Testing in Laravel for Beginners

Many beginner developers see automated testing as extra work that wastes time. The reality is the opposite: a test written once keeps your feature correct forever. Every time you change your code, the test proves that older features still work — without you having to open the browser and click through everything by hand. Laravel ships with the entire testing toolkit from the first install, so there is nothing extra to set up. This tutorial walks you through writing your very first test from scratch.

1. Why Write Tests at All?

Imagine your point-of-sale app has a feature that calculates the shopping total. Without tests, every time you add a discount or tax you must manually check whether the math is still right. With tests, you run a single command and instantly know if something broke. The main benefits:

  • Prevent regressions: a feature that used to work does not silently break when you add new code.
  • Living documentation: tests describe how a feature is supposed to behave.
  • Confidence to refactor: you can safely clean up code because tests guard it.

2. Feature Tests vs Unit Tests

Laravel splits tests into two folders inside the tests/ directory:

  • Unit tests (tests/Unit) test one small piece of code in isolation, such as a single method in a class, without touching the database or HTTP.
  • Feature tests (tests/Feature) test the application as a whole: they send a request to a URL, inspect the response, and even check the database. For beginners, feature tests are usually the most useful because they test what the user actually sees.

3. Creating a Test with make:test

Create a new test file using Artisan. By default it creates a feature test:

php artisan make:test ProductTest

To create a unit test, add the --unit flag:

php artisan make:test PriceCalculatorTest --unit

Laravel 11 uses Pest by default, a testing framework with concise syntax. But classic PHPUnit is still fully supported. We will look at both.

4. Writing Your First Test (Pest)

Pest uses a readable functional style. Open the newly created file and write:

<?php

test('the products page loads', function () {
    $response = $this->get('/products');

    $response->assertStatus(200);
});

The sentence inside test('...') describes what is being tested. The $this->get('/products') call simulates a visitor opening the URL, and assertStatus(200) confirms the page responds successfully.

5. The PHPUnit Version

If you prefer the traditional class-based style, PHPUnit writes it as a method inside a class extending TestCase. Each test method starts with the word test:

<?php

namespace Tests\Feature;

use Tests\TestCase;

class ProductTest extends TestCase
{
    public function test_the_products_page_loads(): void
    {
        $response = $this->get('/products');

        $response->assertStatus(200);
    }
}

6. Commonly Used Assertions

An assertion is a statement that must be true for the test to pass. Some of the most common for testing HTTP responses:

$response->assertStatus(200);          // HTTP status code
$response->assertOk();                 // same as status 200
$response->assertRedirect('/login');  // redirected to a URL
$response->assertSee('Product List'); // text appears on the page
$response->assertSessionHasErrors('name'); // a validation error exists

7. Testing the Database with RefreshDatabase

When a test touches the database, you do not want test data polluting your real database. The RefreshDatabase trait runs migrations at the start and resets the database to a clean state for each test. Use a dedicated testing database (usually in-memory SQLite in phpunit.xml).

<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('a new product is saved to the database', function () {
    $response = $this->post('/products', [
        'name'  => 'Iced Latte',
        'price' => 15000,
        'stock' => 10,
    ]);

    $response->assertRedirect('/products');

    $this->assertDatabaseHas('products', [
        'name'  => 'Iced Latte',
        'price' => 15000,
    ]);
});

The assertDatabaseHas() assertion checks that a row with that data actually exists in the table — proof that the save feature works.

8. Generating Test Data with Factories

Writing dummy data by hand in every test is tiring. Factories produce realistic fake data in a single line. Create the factory:

php artisan make:factory ProductFactory

Define the shape of the data:

public function definition(): array
{
    return [
        'name'  => fake()->words(2, true),
        'price' => fake()->numberBetween(10000, 100000),
        'stock' => fake()->numberBetween(0, 50),
    ];
}

Now inside a test you can create 3 products at once and confirm they all show up:

test('the list shows all products', function () {
    Product::factory()->count(3)->create();

    $response = $this->get('/products');

    $response->assertStatus(200);
    $this->assertDatabaseCount('products', 3);
});

9. Running All Tests

Run the entire test suite with a single command:

php artisan test

You will see a green dot for every passing test and a detailed explanation when one fails. To run just a single file:

php artisan test --filter=ProductTest

Tips to Make Testing a Habit

  • Start with feature tests for your most important features (login, checkout, saving data).
  • Write tests before or right after building a feature, do not put it off.
  • Run php artisan test before every commit so nothing broken reaches the repository.

By mastering make:test, assertions, RefreshDatabase, and factories, you have a solid enough testing foundation to keep any Laravel application healthy as its features grow.

Yudhi
Written by
Yudhi
Founder & Lead Developer, GudangCode

Yudhi is the founder of GudangCode and a Laravel developer who has built dozens of ready-to-use business information systems — from POS and HRIS to management apps. He writes guides and articles on GudangCode to help Indonesian developers run, understand, and deploy Laravel source code correctly.

LaravelPHPMySQLSistem Informasi Bisnis See all articles by Yudhi
Want the full source code & apps?

Sign up free to download ready-to-use business applications, information systems, and Laravel source code.

Sign Up Free & Download
Testing Laravel Programming & Laravel
Share this article
Back to Blog
📚 Free Learning Hub

Learn Coding for Free at DhieCoderWeb

Explore Laravel, PHP, JavaScript tutorials, source code, web development guides, and practical programming tips.

DhieCoderWeb
100+
Tutorials
Free
Learning
SEO
Tips
Visit Dhiecoderweb.com →

Get Full Access Now!

Join our membership and unlock exclusive access to all premium features. Fast, easy, and ready to use instantly.

Join Membership Now
Tim Support
Online
Isi data dulu untuk mulai chat:
Beri rating & testimoni sebelum menutup:
Live chat by gudangcode.com