I'm trying to set up the test environment in my Laravel project. I'm using http://packalyst.com/packages/package/mayconbordin/l5-fixtures with json for the seeding with a sqlite in memory database and calling:
Artisan::call('migrate');
Artisan::call('db:seed');
in my setUp function but this is executed before every single test which it can grow to thousands in this project.
I tried the setUpBeforeClass but it didn't work. I think there because the createApplication method is called in every test and that reset the whole application and also wasn't loading the fixtures from the json probably for the same reason.
php artisan migrate:fresh is used when we want a fresh or new installation of our database. It deletes all the existing tables of the database and runs the migrate command. php artisan migrate:refresh is a two in one command that executes the :rollback command and the migrate command.
Laravel Migration is an essential feature in Laravel that allows you to create a table in your database. It allows you to modify and share the application's database schema. You can modify the table by adding a new column or deleting an existing column.
Laravel includes the ability to seed your database with data using seed classes. All seed classes are stored in the database/seeders directory. By default, a DatabaseSeeder class is defined for you. From this class, you may use the call method to run other seed classes, allowing you to control the seeding order.
Migrations and seeders are powerful database utilities provided by the Laravel PHP framework to allow developers to quickly bootstrap, destroy and recreate an application’s database.
To create a migration, we use laravel’s artisan command make:migration Full command is php artisan make:migration schema_name . Using this command, laravel generates a table schema with the name that you have provided in the database/migration directory.
The artisan command line tool that ships with Laravel contains a series of helper commands that can be used to manage the application and bootstrap new classes. To generate a new migration class, we can use the make:migration command as follows:
Laravel makes it pretty easy to perform seeding. A seeder class contains a run method by default. You can insert data by using a query builder or Eloquent model factories. Let’s run an Artisan command to generate a seeder. Then, you use the model factory to generate ten users in the run method.
This is how I did it in case someone else is struggling with the same, I created a base testClase
class that inherits from Laravel's and did this:
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
return self::initialize();
}
private static $configurationApp = null;
public static function initialize(){
if(is_null(self::$configurationApp)){
$app = require __DIR__.'/../bootstrap/app.php';
$app->loadEnvironmentFrom('.env.testing');
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
if (config('database.default') == 'sqlite') {
$db = app()->make('db');
$db->connection()->getPdo()->exec("pragma foreign_keys=1");
}
Artisan::call('migrate');
Artisan::call('db:seed');
self::$configurationApp = $app;
return $app;
}
return self::$configurationApp;
}
public function tearDown()
{
if ($this->app) {
foreach ($this->beforeApplicationDestroyedCallbacks as $callback) {
call_user_func($callback);
}
}
$this->setUpHasRun = false;
if (property_exists($this, 'serverVariables')) {
$this->serverVariables = [];
}
if (class_exists('Mockery')) {
Mockery::close();
}
$this->afterApplicationCreatedCallbacks = [];
$this->beforeApplicationDestroyedCallbacks = [];
}
I overwrote the createApplication()
and tearDown()
methods. I changed the first one to use the same $app
configuration and remove the part of the teardown()
where it flush $this->app
.
Every other of my test has to inherit from this TestClass and that's it.
Everything else didn't work. This works even with in memory database, it's 100s times faster.
if you are dealing with user session, once you log the user in you will have to log him out in tear down, otherwise the user will be logged in because the app environment is never reconstructed or you can do something like this to refresh the application every time you want:
protected static $applicationRefreshed = false;
/**
* Refresh the application instance.
*
* @return void
*/
protected function forceRefreshApplication() {
if (!is_null($this->app)) {
$this->app->flush();
}
$this->app = null;
self::$configurationApp = null;
self::$applicationRefreshed = true;
parent::refreshApplication();
}
And add this to the tearDown()
before the $this->setUphasRun = false;
:
if (self::$applicationRefreshed) {
self::$applicationRefreshed = false;
$this->app->flush();
$this->app = null;
self::$configurationApp = null;
}
create file in your project testrunner
with this content (also prepare .env.testing
file with testing environment variables) :
php artisan migrate:rollback --env=testing
php artisan migrate --env=testing --seed
vendor/bin/phpunit
And give permission to execute by command chmod +x testrunner
and execute it by ./testrunner
. Thats all :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With