DylanBaine.com / Browse / Ensuring you dont run your Laravel test suite in production (and wipe out all of your production data).

Ensuring you dont run your Laravel test suite in production (and wipe out all of your production data).

What if you accidentally run your test suite in a production environment? Well, if you’ve been around Laravel long enough, you know what happens. You run php artisan test, you notice it’s taking a really long time, and you finally realize that is because the test is clearing out your whole database.

Lucky for you, there is a solution to this issue so that this problem never happens again! Laravel allows us to create artisan commands within the routes/console.php file. This allows us to override any existing commands that Laravel provides out of the box. See the code below for an example.

// in routes/console.php
if (config('app.env') === 'production') {
    Artisan::command('test', function () {
        throw new Exception("Can't test in production env.");
    })->purpose("Should not run test in production environment, as it may clear the database.");

This code is pretty straight forward I think. If you are in a production environment, let’s create a command that will override the default test command. You can imagine that this technique could be used to override a number of default Laravel commands for specific environments if you’d like.

But why did running php artisan test wipe out my database?

The PHP framework Laravel has a great host of tools that you can use to test your code that interacts with a database. Generally, you want each test to have its own state of the database so you can test your code in many types of situations. To do that is as easy as leveraging the Illuminate\Foundation\Testing\RefreshDatabase; trait, which clears out your database, and then runs your migrations. See below for an example of a test using this trait:

namespace Tests\Feature;

use Tests\TestCase;
use App\Actions\UpdateEmailAction;
use Illuminate\Foundation\Testing\RefreshDatabase;

class UpdateEmailActionTest extends TestCase
    use RefreshDatabase;

Now all you have to do is run php artisan test and each individual test function will clear out the database, and then re-run your migrations.

Another Solution

Another solution to this issue is to create a dedicated testing database connection for your tests to run in by ensuring that the only database environment variable in your phpunit.xml file is for your database connection name (DB_CONNECTION), then creating that testing connection in your config/database.php file under the connections array with all new environment variables (I suggest prefixing them all with TESTING_).

        <env name="APP_ENV" value="testing"/>
        <env name="BCRYPT_ROUNDS" value="4"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="DB_CONNECTION" value="testing"/>
        <env name="MAIL_MAILER" value="array"/>
        <env name="QUEUE_CONNECTION" value="sync"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="TELESCOPE_ENABLED" value="false"/>

I hope this article is helpful and that if you accidentally wiped out a production database that you can still be friends with you co-works.

Happy coding! 🙂