Laravel, Dusk – Build a web application with Laravel and test it with Dusk

As I have talked with a friend creating a web application with Laravel. I have share with him few insights about how to perform testing on such environment and at the same time I discovered that in the last version of Laravel is shipped with a very practical tool for testing named Dusk.

So here is the the POC made with Laravel (5.6.26) on Mac, with a MySQL database and Dusk. It is a simple application that I have made up with the help of an article of Mukesh Chapagain.

The files are available on Github @ https://github.com/bflaven/laravel-dusk-testing-people-app. The best thing to do is follow the step by step in the post and just use the files in the repository as models.

$ git clone https://github.com/bflaven/laravel-dusk-testing-people-app.git laravel-dusk-testing-people-app

Source: http://blog.chapagain.com.np/laravel-simple-crud-add-edit-delete-view-beginner-tutorial/

If you need to determine the Laravel version

php artisan --version

I advise you also a resource that I have found in order to understand the usage of Dusk. It gives a full listing of the testing assertions that can be made with Dusk

Source: http://laravel.at.jeffsbox.eu/laravel-5-cheatsheet-laravel-dusk-testing-assertions

The main page http://127.0.0.1:8000/people
 Laravel, Dusk -  Build a web application with Laravel and test it with Dusk

The page to add a person http://127.0.0.1:8000/people/add
 Laravel, Dusk -  Build a web application with Laravel and test it with Dusk

The records generated by Faker inside the database
 Laravel, Dusk -  Build a web application with Laravel and test it with Dusk

Launching the test in Duck with debug $ php artisan dusk --debug
 Laravel, Dusk -  Build a web application with Laravel and test it with Dusk

Launching the test in Duck with debug and a error in the login$ php artisan dusk --debug
 Laravel, Dusk -  Build a web application with Laravel and test it with Dusk

The error screen capture available at /tests/Browser/screenshots/
 Laravel, Dusk -  Build a web application with Laravel and test it with Dusk

Requirements

1. Database
In order to manage this application, you will need a MySQL database. To install and manage MySQL, there a quick and simple explanation at https://sequelpro.com/docs/ref/mysql/install-on-osx and at the same time, you can install also Sequel Pro: https://sequelpro.com/. Sequel Pro is a FREE and excellent tool to manage on a MAC, a MySQl databases.

2. Composer
If you need to install Composer globally, you can run this command in the console.

$ curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

3. Laravel
If you need to install laravel globally if needed.

composer global require "laravel/installer=~1.1"

Create the application

We are ready now to launch the building of the application through Laravel.

If you want to create from scratch your project, you can do so. Here is the first command to create the project, but you will need to grab the files from the repository git. The better is to clone directly from Github.

$ cd /path-to-your-directory/
$ laravel new laravel-dusk-testing-people-app
$ cd laravel-dusk-testing-people-app

2 things you need to know before diving into the application.

  1. The APP_URL : The first thing to do is to change your APP_URL. In order to Dusk access your application and test it, you have to change your local development URL editing the .env file. By default, the APP_URL is http://localhost. If you are running your server in another port, for example 8000, change it to http://localhost:8000. If you keep http://localhost, Dusk will not be able to test your app.
    In my example, the APP_URL=http://127.0.0.1:8000 in .env
  2. The DB: The second thing is to create a database named for instance db_laravel_people and change the .env by adding the correct databasename (db_laravel_people), username (root) and password (root)

Creating the Migration files

Migrations in Laravel are easy, here is the 2 commands to create a migration for your new application.

$ php artisan migrate:install
$ php artisan make:migration create_people_table --create=people

In the file created, add the code to create table ‘people’ in /database/migrations/2018_07_01_101838_create_people_table.php

   public function up()
    {
            // create table 'people'        
            Schema::create('people', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name',255);
            $table->string('email',255);
            $table->string('username',100);
            $table->text('bio');
            $table->date('dob');
            $table->text('address');
            $table->string('city',100)->nullable();
            $table->string('country',100)->nullable();
            $table->timestamps(); // timestamps() creates created_at & updated_at fields  
            }); 
    }

Launch the migration, it will create the table people in your MySQL database.

$ php artisan migrate

Create the Seeds files

Create seeds means basically add content into your database. So let add fake content inside the table people with the help of Faker.

$ php artisan make:seeder

You need to add this content to the model seeds ‘people’ in /database/seeds/PeopleTableSeeder.php

        public function run()
    {
        //the seeds for the database
 
        $faker = Faker\Factory::create();
 
        // add 50 rows of random data        
        for ($i=0; $i < 100; $i++) {            
          DB::table('people')->insert([
            'fullname' => $faker->name,
            'email' => $faker->safeEmail,
            'username' => $faker->userName,
            'bio' => $faker->paragraphs(3, true), // 3 paragraphs
            'dob' => $faker->date($format = 'Y-m-d', $max = 'now'),
            'address' => $faker->address,
            'city' => $faker->city,
            'country' => $faker->country,
            'created_at' => $faker->dateTime(),
            'updated_at' => $faker->dateTime(),
             ]);
        }
    }

To launch the seeds inside the database

$ php artisan db:seed --class=PeopleTableSeeder

Create the Model

$ php artisan make:model People

Just check the file created at app/People.php and add the following content. Be careful with protected $fillable, this is where you handle the fields of your table people.

namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
 
 
class People extends Model
{
    /**
     * The table associated with the model
     *
     * @var string
     */
    protected $table = 'people';
 
    /**
     * Indicates primary key of the table
     *
     * @var bool
     */
    public $primaryKey = 'id';
 
    /**
     * Indicates if the model should be timestamped
     * 
     * default value is 'true'
     * 
     * If set 'true' then created_at and updated_at columns 
     * will be automatically managed by Eloquent
     * 
     * If created_at and updated_at columns are not in your table
     * then set the value to 'false'
     *
     * @var bool
     */
    public $timestamps = true;
 
    /**
     * The attributes that are mass assignable
     *
     * @var array
     */
    protected $fillable = array('fullname', 'email', 'username', 'bio', 'dob', 'address', 'city', 'country', 'created_at', 'updated_at');
 
    /**
     * The attributes that aren't mass assignable
     *
     * @var array
     */
    protected $guarded = array();
}

Create the Routes

Add the following content in routes/web.php to define the routes for our application.

/* manage routes for People */
Route::get('people', array('as' => 'people.index', 'uses' => 'PeopleController@index'));
Route::get('people/add', array('as' => 'people.create', 'uses' => 'PeopleController@create'));
Route::post('people/store', array('as' => 'people.store', 'uses' => 'PeopleController@store'));
Route::get('people/edit/{id}', array('as' => 'people.edit', 'uses' => 'PeopleController@edit'));
Route::patch('people/update/{id}', array('as' => 'people.update', 'uses' => 'PeopleController@update'));
Route::delete('people/delete/{id}', array('as' => 'people.destroy', 'uses' => 'PeopleController@destroy'));
Route::get('people/{username}', array('as' => 'people.show', 'uses' => 'PeopleController@show'));

To test if the routes are OK in Laravel, you use the following command.

php artisan route:list

Create the Controller for people

Launch the following command in your console

$ php artisan make:controller PeopleController --resource

It will create a controller file in app/Http/Controllers/PeopleController.php, that make a basic CRUD actions for your web application. The code is available at https://github.com/bflaven/laravel-dusk-testing-people-app/blob/master/app/Http/Controllers/PeopleController.php

Creating the Views

You will add in the composer.json the following line:

"require": {
    "laravelcollective/html": "~5.0"
}

Next, you update with Composer from the Terminal:

$ composer update

You have to create the different vies of your application.

$ cd /path-to-your-app/laravel-dusk-testing-people-app/resources/views
$ mkdir layouts
$ cd layouts 
$ touch master.blade.php

For each file, check https://github.com/bflaven/laravel-dusk-testing-people-app/tree/master/resources/views/layouts and add the content in the file master.blade.php

mkdir people
cd people
touch index.blade.php
touch create.blade.php
touch edit.blade.php
touch show.blade.php

For each file, check https://github.com/bflaven/laravel-dusk-testing-people-app/tree/master/resources/views/people and add the content in the file master.blade.php

In order test also the login system that come with Laravel. I will pass this command.

Add the login sytem in the application by the following command

$ php artisan make:auth

So far I have created a simple web application based on Laravel. You can add record to the database. Sure that making a CRUD application with the help of Laravel is damn easy but that is the purpose of this post. My concern is to test Dusk inside Laravel. You can check the result with the command.

$ php artisan serve

Tests for the login and the app

We have now a very basic application with some records and 2 screens. So why don’t we test it with Dusk? In order to ensure that for each new feature, there will be no regression in our previous screens.

In order to install Dusk, you can add the following line in your the file: composer.json

$ composer require laravel/dusk

Then, type this command and it will install Dusk for good.

$ php artisan dusk:install

You have to add the following code inside the file app/Providers/AppServiceProvider.php. It will declare Dusk as a provider in all environment exception made of the production one.

    public function register()
    {
        //
        if ($this->app->environment('local', 'testing', 'staging')) {
           $this->app->register(DuskServiceProvider::class);
        }
    }

You can add the content from this file https://github.com/bflaven/laravel-dusk-testing-people-app/blob/master/app/Providers/AppServiceProvider.php

You will then create your first Dusk test for the login.

$ php artisan dusk:make LoginTest

You can add the content from this file https://github.com/bflaven/laravel-dusk-testing-people-app/blob/master/tests/Browser/CreatePeopleTest.php

You will also create our second Dusk test.

$ php artisan dusk:make CreatePeopleTest

You can add the content from this file https://github.com/bflaven/laravel-dusk-testing-people-app/blob/master/tests/Browser/CreatePeopleTest.php

To execute our Dusk tests, just type in the console.

$ php artisan dusk

To execute our Dusk tests in a more verbose way, just type in the console.

$ php artisan dusk --debug

Conclusion: Dusk is using a headless browser of Chrome to perform the tests on your application. Every time the test fails, you will get a nice capture of the screen where it has failed in /tests/Browser/screenshots/.

Read more