Automated browsing tests with Laravel Dusk

Thiago Alves • 05/31/2020

No matter how beginner you may be, it is very likely that, at some point, you have heard about automated testing, its importance in systems development and everything else.

In fact, as we increase the level of complexity of our projects, it is possible to notice how much this resource helps us in building and maintaining functionalities.

Unfortunately, many professionals, including myself, only notice that when they start to face problems that could have been avoided if the tests had been written. An example of this, is that change made that causes a bug in another area of the system.

Different types of tests

This is a pretty broad field these days. There are ways to test virtually every area of a system. From that small function that formats a date, for example, to a complex integration full of steps with another third-party system.

Unit, functional, integration, performance, security tests. The list is really extensive, to the point where some companies have professionals specialized in developing these tests, known as QA (Quality Analyst).

Laravel Dusk

It is a Laravel package created to develop tests simulating browser behavior, filling out forms, clicking on buttons and links, validating whether certain information appears on the screen and much more.

Like most solutions the framework offers, the package is very simple to install and use. The setup process practically does not exist, just execute the commands in the documentation. It also does not have dependencies like JDK e Selenium.

Setup

Use composer in order to install the package in your project:

$ composer require --dev laravel/dusk

Subsequently, run the command that will create the entire test structure within a Browser folder, in the project's tests directory.

$ php artisan dusk:install

Project's testing folder

You're all set!

P.S.: Confirm the installation commands in the official documentation, as they may change.

P.S. 2: Before we start practicing, check if the APP_URL variable in your .env file has the full URL of your application, if not, fix it.

Let's do it

The context

I implemented a very basic registration screen, where you only need to fill out your name and email. When clicking on the "Save" button, you will be redirected to a second screen where a list of all registers is showed. Screenchots below.

Form to add items

List of items registered

Test 1

I need to create an automated test to ensure this behavior happens correctly. So I created the following test for this:

// tests/Browser/RegistersTest

public function testAddRegisterSuccess()
{
    // Fake data generator
    $faker = Factory::create('pt_BR');

    $this->browse(function (Browser $browser) use ($faker) {
        $name = $faker->name;
        $email = $faker->email;

        $browser->visit('/registers/create') // Access the route of the form
            ->type('name', $name) // Fill out the name
            ->type('email', $email) // Fill out the email
            ->press('Salvar') // Click on "Salve"
            ->assertPathIs('/registers') // Test if it was redirected to the list page
            ->assertSee($name) // Test if the name registed is in the list
            ->assertSee($email); // Test if the email registed is in the list
    });
}

Executing Dusk

To execute all tests implemented with Dusk, simply run the command below:

$ php artisan dusk

To execute a specific test, run the command as follows:

$ php artisan dusk tests/Browser/RegistersTest.php

Result:

Result of the tests

Test 2

Now, I want to ensure that the form validation works correctly.

Form to add items with the validation messages

For that I wrote the following test:

// tests/Browser/RegistersTest

public function testAddRegisterValidation()
{
    $this->browse(function (Browser $browser) {
        $browser->visit('/registers/create') // Access the route of the form
            ->press('Salvar') // Click on "Save" without filling out anything
            ->assertPathIs('/registers/create') // Test if it keeps on the same page
            ->assertSee('The name field is required.') // Test if it shows the error on the name
            ->assertSee('The email field is required.'); // Test if it shows the error on the email
    });
}

Result:

Result of the test

Then

The possibilities are endless. In the future, I will make a second post exploring more resources.

At first impressions, this process seems laborious, but, like everything in programming, practice will make it easier and faster.

As time passes, you no longer worry about having to write tests, but rather, which ones to write in order to ensure that the most variable behaviors are covered.

All the code above is available in my repository, if you want to download and test it.

See you later!

Thiago Alves

Thiago Alves

Software Engineer, in the software development market since 2011. Specialist in PHP, Laravel and Vue.js.

Share your thoughts about this post in the comments below, in case you have any questions or would like to suggest a topic.