Laravel Reset Database after Test

laravel test database connection
laravel refreshdatabase
laravel testing
laravel create test database
laravel factory relationship
laravel test setup
laravel database assertions
laravel testing models

I have just started using Laravel Dusk to test my project and need some guidance. After I run all the tests available, I want to be able to reset my database back to before I run the tests. (If there were any entries in my database before I run the tests, I would still like to see them after I run the tests. However, any entires created during the test, I would not like to see them after the tests finish running.) Any pointers on how I would achieve this? Thank you!

Update:

<?php

namespace Tests\Browser;

use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class UserRegisterTest extends DuskTestCase
{
    use DatabaseTransactions;
    /**
     * A test for user registration.
     * @group register
     * @return void
     */

    public function testRegisterUser()
    {
        //Register with all info filled out correctly
        $this->browse(function ($browser){
            $browser->visit('/register')
                    ->type('firstName', 'JenLogin')
                    ->type('lastName', 'Zhou')
                    ->type('email', 'testLogin@gmail.com')
                    ->type('bio', 'Hello, this user is for testing login purposes!')
                    ->type('location_zip', '11111')
                    ->type('password', '123456')
                    ->type('password_confirmation', '123456')
                    ->click('.btn-primary')
                    ->assertPathIs('/home')
                    ->click('.dropdown-toggle')
                    ->click('.dropdown-menu li:last-child');

        });

        $this->assertDatabaseHas('users', ['firstName' => 'JenLogin', 'lastName' => 'Zhou', 'email' => 'testLogin@gmail.com']);


    }

    /**
     * Register with duplicate user
     * @group register
     * @return void
     */
    public function testRegisterDuplicateUser(){

        $this->browse(function ($browser){
            $browser->visit('/register')
                ->type('firstName', 'JenLoginDup')
                ->type('lastName', 'Zhou')
                ->type('email', 'testLogin@gmail.com')
                ->type('bio', 'Hello, this user is for testing login purposes!')
                ->type('location_zip', '11111')
                ->type('password', '123456')
                ->type('password_confirmation', '123456')
                ->click('.btn-primary')
                ->assertPathIs('/register')
                ->assertSee('The email has already been taken.');
        });

        $this->assertDatabaseMissing('users', ['firstName' => 'JenLoginDup', 'lastName' => 'Zhou', 'email' => 'testLogin@gmail.com']);
    }

    /**
     * Register with incorrect password confirmation
     * @group register
     * @return void
     */
    public function testRegisterUserNoPassConfirm(){

        $this->browse(function ($browser){
            $browser->visit('/register')
                ->type('firstName', 'JenLoginPass')
                ->type('lastName', 'Zhou')
                ->type('email', 'testLoginPass@gmail.com')
                ->type('bio', 'Hello, this user is for testing login purposes!')
                ->type('location_zip', '11111')
                ->type('password', '123456')
                ->type('password_confirmation', '888888')
                ->click('.btn-primary')
                ->assertPathIs('/register')
                ->assertSee('The password confirmation does not match.');
        });

        $this->assertDatabaseMissing('users', ['firstName' => 'JenLoginPass', 'lastName' => 'Zhou', 'email' => 'testLoginPass@gmail.com']);
    }
}

You are looking for the DatabaseTransactions trait. Use it in your test class like this and it will automatically rollback all database transactions made during your tests.

use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

    // test methods here
}

This will keep track of all transactions made during your test and undo them upon completion.

note: this trait only works on default database connections

Testing Laravel: resetting the database after each test, but better, Learn how to refresh and seed your database for each test in a quick way, by storing the clean database into a file and copying it for each test. Resetting The Database After Each Test. It is often useful to reset your database after each test so that data from a previous test does not interfere with subsequent tests. The RefreshDatabase trait takes the most optimal approach to migrating your test database depending on if you are using an in-memory database or a traditional database. Use the trait on your test class and everything will be handled for you:

There is no sane workflow for running tests on live/dev db with data and reverting changes back, done by tests.

Therefore your approach fails here, instead you should:

  1. Create separate test schema/db for tests
  2. Switch to test db, before running tests - this can be somehow automated depending on your configuration in phpunit and .env.dusk, but it depends on your local setup.
  3. Then in your tests you will create all from scratch on clean db (run migrations, seeds, factories)
  4. Run tests against this test db
  5. For development switch back to your base db with current data, which will not be affected by tests.

Next time you will run your tests all starts again from point zero - clean database, this will be done by in tests: use CreatesApplication; use DatabaseMigrations; parent::setUp();etc.

Read more about these methods...

Side Notes:

  1. With this approach, it will be easy, to test your app in CI environments also.

  2. Never write your tests which depend on data on your dev/live db. For tests all required data should be provided by seeds or ewentually factories!

Database Testing - Laravel, Resetting The Database After Each Test. It is often useful to reset your database after  Testing Laravel: resetting the database after each test, but better 22 January 2018 on Laravel , Testing , PHPUnit , Database , Migrating , Seeding In this blog post I'll be explaining my solution for refreshing and seeding a test database for each test, in a quick way.

First of all, when you are running tests you should use completely different database than your live (or dev) database. For this you should create .env.dusk and set in there:

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=testing_database
DB_USERNAME=root
DB_PASSWORD=pass

to database used for tests only.

Second thing is that for Laravel Dusk you cannot use just DatabaseTransactions. You should in fact use DatabaseMigrations for Dusk tests otherwise you will get unexpected results.

Testing - Laravel, So let's create a trait which runs php artisan migrate:fresh --seed once before testing starts. Following should be already in place: Laravel Framework (article based  Laravel provides two approaches to resetting your database after every test. They are DatabaseMigrations and DatabaseTransactions. Let’s try the DatabaseMigrations.

I think this is a great question. I found an Artisan tool that may be what you are looking for. You can use it to take a snapshot of the database before you run the test and then use it again to load that snapshot restoring your database to the previous state. I gave it a run(using MYSQL) and it worked great. Hope this is what you are looking for. Here is a link...

https://github.com/spatie/laravel-db-snapshots

Fresh Database Once Before Testing Starts - HelpSpace, From the doc.: ###Resetting The Database After Each Test It is often useful to reset your database after each test so that data from a previous test d Please note: https://laravel.com/docs/5.5/dusk#migrations. Posted 1 year  It is often useful to reset your database after each test so that data from a previous test does not interfere with subsequent tests. The RefreshDatabase trait takes the most optimal approach to migrating your test database depending on if you are using an in-memory database or a traditional database. Simply use the trait on your test class and everything will be handled for you.

phpunit.xml file is your solution there, you can set a .env variables in this file like so

    <env name="DB_CONNECTION" value="testing_mysql"/>
    <env name="DB_DATABASE_TEST" value="test"/>

now you can run your tests on a separate database.

Plus you can run a .php file every time before tests in automation, you just need to tell it to unittests

<phpunit 
     ...
     bootstrap="tests/autoload.php"
>

You can put any cleaners or seeders there or something like

echo 'Migration -begin-' . "\n";
echo shell_exec('php artisan migrate:fresh --seed');
echo 'Migration -end-' . "\n";

RefreshDatabase trait doesn't refresh database, This is my test case <?php namespace Tests\Feature\Discussions; use and brew; then did a fresh install of Laravel and wrote my first test. @tykus - Yes, after clearing the cache, database didn't delete; but the test case  After Resetting Passwords. Once you have defined the routes and views to reset your user's passwords, you may access the route in your browser at /password/reset. The ForgotPasswordController included with the framework already includes the logic to send the password reset link e-mails, while the ResetPasswordController includes the logic to reset user passwords. After a password is reset, the user will automatically be logged into the application and redirected to /home.

Database tables deleted after running phpunit test, the default one).. and obviously in Laravel's documentation: https://laravel.com/​docs/5.1/testing#resetting-the-database-after-each-test it says  After installing a new Laravel application, run phpunit on the command line to run your tests. Environment When running tests via phpunit , Laravel will automatically set the configuration environment to testing because of the environment variables defined in the phpunit.xml file.

phpUnit is deleting my database!, In this example, I'm using Laravel's migrations and SQLite as the test DB. parent::setUpBeforeClass(); exec('php artisan migrate --database  The Laravel Schema facade provides database agnostic support for creating and manipulating tables across all of Laravel's supported database systems. Generating Migrations. To create a migration, use the make:migration Artisan command: php artisan make:migration create_users_table. The new migration will be placed in your database/migrations directory. Each migration file name contains a timestamp, which allows Laravel to determine the order of the migrations.

Reset database in tests for specific connection, It is often useful to reset your database after each test so that the data from a previous test doesn't interfere with subsequent tests. The RefreshDatabase trait will take the most optimal approach to migrating your test database depending on if you are using an in-memory database or a traditional database.

Comments
  • I added the line "use DatabaseTransactions" , but got this error "Fatal error: Trait 'Tests\Browser\DatabaseTransactions' not found in /Users/jenniferzhou/Documents/Cypress/MarketPlace/tests/Browser/UserRegisterTest.php on line 17".
  • Did you include the top use statement use Illuminate\Foundation\Testing\DatabaseTransactions; as well? This should go up above the class declaration. Then the use DatabaseTransactions; statement should go just inside the opening class line as demonstrated above.
  • I added the line and now I do not get anymore errors. However, when I created a test to register a user in my database and added the lines to use DatabaseTransactions, the database still stores the user at the end of the test.
  • Can you post your test class ? Is there an exception being thrown, some other early exit or is it running to completion?
  • I added a test that I tried to use with Database Transaction!
  • Yes, this is a great package, but I don't think it is the main purpose for this kind of usage, How about cancelled tests in the midlle of the job? Is it covering of all requested scenarios? Certainly not. And still there are some artisan commands which you nieed to invoke. So isn't just easier to modify your .env to match proper test db and than switch back?