Skip to content

Instantly share code, notes, and snippets.

@neoascetic
Last active September 9, 2020 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neoascetic/6504409 to your computer and use it in GitHub Desktop.
Save neoascetic/6504409 to your computer and use it in GitHub Desktop.
[Laravel] Bootstrap file for (re)creating database before running tests
<?php
/**
* Bootstrap file for (re)creating database before running tests
*
* You only need to put this file in "bootstrap" directory of the project
* and change "bootstrap" phpunit parameter within "phpunit.xml"
* from "bootstrap/autoload.php" to "bootstap/testing.php"
*/
$testEnvironment = 'testing';
$config = require("app/config/{$testEnvironment}/database.php");
extract($config['connections'][$config['default']]);
$connection = new PDO("{$driver}:host={$host}", $username, $password);
$connection->query("DROP DATABASE IF EXISTS ".$database);
$connection->query("CREATE DATABASE ".$database);
require_once('app/libraries/helpers.php');
// run migrations for packages
foreach(glob('vendor/*/*', GLOB_ONLYDIR) as $package) {
$packageName = substr($package, 7); // drop "vendor" prefix
passthru("./artisan migrate --package={$packageName} --env={$testEnvironment}");
}
passthru('./artisan migrate --env='.$testEnvironment);
require('autoload.php'); // run laravel's original bootstap file
@deepakxoptimo
Copy link

I am facing issue in this script. My database is not getting created. Can you please help me.

@neoascetic
Copy link
Author

@deepakxoptimo any error message?

@marcenuc
Copy link

@neoascetic for me the problem was the following line:

$connection = new PDO("{$driver}:user={$username} password={$password}");

I think it lacks ; between user and password. I've used:

$connection = new PDO("{$driver}:host={$host}", $username, $password);

@neoascetic
Copy link
Author

@marcenuc yeah, solution you've provided is more general. That DSN worked for me with PostgreSQL. I'll update the code.

@mpyw
Copy link

mpyw commented Dec 29, 2017

Best solution for PHP 7.1 + Laravel 5.5

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="tests/bootstrap.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing" />
        <env name="CACHE_DRIVER" value="array" />
        <env name="DB_DATABASE" value="my-testing-database" />
        <env name="SESSION_DRIVER" value="array" />
        <env name="QUEUE_DRIVER" value="sync" />
    </php>
</phpunit>

tests/bootstrap.php

<?php

require __DIR__ . '/../bootstrap/autoload.php';

(new class() {
    use \Tests\CreatesApplication;
})->createApplication()[\Illuminate\Contracts\Console\Kernel]->call('migrate:fresh');

@partyka1
Copy link

partyka1 commented Dec 1, 2019

@mpyw nice solution!

@zeetabit
Copy link

zeetabit commented Sep 9, 2020

not working @mpyw solution, simplier same solution in setUp function call same thing Artisan::call('migrate:fresh') and it shouldn't work also
because initial solution creates database instead of modifying existing db
I created command, thats can create database by passed db name (if not exists). And then call this command every time in setUp method .

@zeetabit
Copy link

zeetabit commented Sep 9, 2020

more simpler using this piece of code in setUp method

// Get the default connection name, and the database name for that connection from laravel config.
$connectionName = config('database.default');
$databaseName = config("database.connections.{$connectionName}.database");

// Set the database name to null so DB commands connect to raw mysql, not a database.
config(["database.connections.{$connectionName}.database" => null]);

// Create the db if it doesn't exist.
DB::statement("CREATE DATABASE IF NOT EXISTS " . $databaseName);

// Reset database name and purge database-less connection from cache.
config(["database.connections.{$connectionName}.database" => $databaseName ]);
DB::purge();

source laravel/framework#19412 (comment)

You can't use RefreshDatabase trait in first initial test. Because this trait (and some others) should use database that could be not exists

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment