Skip to content

Instantly share code, notes, and snippets.

@hotsaucejake
Created June 17, 2023 12:05
Show Gist options
  • Save hotsaucejake/a84b3439597f726870efd4c9e67f5870 to your computer and use it in GitHub Desktop.
Save hotsaucejake/a84b3439597f726870efd4c9e67f5870 to your computer and use it in GitHub Desktop.
Checksum Faster Refresh Database Trait for Laravel Tests
<?php
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\RefreshDatabaseState;
use Symfony\Component\Finder\Finder;
/**
* Only migrate fresh if necessary -> much faster after the first time!
*/
trait FasterRefreshDatabase
{
use RefreshDatabase;
/**
* Only migrates fresh if necessary
*/
protected function refreshTestDatabase(): void
{
if (!RefreshDatabaseState::$migrated) {
$this->runMigrationsIfNecessary();
$this->app[Kernel::class]->setArtisan(null);
RefreshDatabaseState::$migrated = true;
}
$this->beginDatabaseTransaction();
}
/**
* Check if migration fresh is necessary by checking
* if the migrations files checksum has changed.
*/
protected function runMigrationsIfNecessary(): void
{
if (!$this->identicalChecksum()) {
// $this->seed();
$this->artisan('migrate:fresh', $this->migrateFreshUsing());
//create checksum after migration finishes
$this->createChecksum();
}
}
/**
* Calaculates the checksum of the migration files.
*/
private function calculateChecksum(): string
{
$files = Finder::create()
->files()
->exclude([
'factories',
'seeders',
])
->in(database_path())
->ignoreDotFiles(true)
->ignoreVCS(true)
->getIterator();
$files = array_keys(iterator_to_array($files));
$checksum = collect($files)->map(function ($file) {
return md5_file($file);
})->implode('');
return md5($checksum);
}
/**
* Filepath to store the checksum.
*/
private function checksumFilePath(): string
{
return base_path('.phpunit.database.checksum');
}
/**
* Creates the checksum file.
*/
private function createChecksum(): void
{
file_put_contents($this->checksumFilePath(), $this->calculateChecksum());
}
/**
* Get the checksum file content.
*
* @return false|string
*/
private function checksumFileContents()
{
return file_get_contents($this->checksumFilePath());
}
/**
* Check if checksum exists.
*/
private function isChecksumExists(): bool
{
return file_exists($this->checksumFilePath());
}
/**
* Check if checksum of current database migration files
* are identical to the one we stored already.
*/
private function identicalChecksum(): bool
{
if (!$this->isChecksumExists()) {
return false;
}
if ($this->checksumFileContents() === $this->calculateChecksum()) {
return true;
}
return false;
}
}
@hotsaucejake
Copy link
Author

Screenshot_20230608_160311 (1)

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