Skip to content

Instantly share code, notes, and snippets.

@haringsrob
Created September 18, 2019 07: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 haringsrob/82c6e3263fb4fb6305c5e7a98646cb78 to your computer and use it in GitHub Desktop.
Save haringsrob/82c6e3263fb4fb6305c5e7a98646cb78 to your computer and use it in GitHub Desktop.
Simple trait you can add to Behat feature context which creates a snapshot before running tests and restores it for every scenario ensuring a clean database.
<?php
namespace OpenEuropa\Site\Tests\Behat\FeatureTraits;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use Behat\Testwork\Hook\Scope\AfterSuiteScope;
use Behat\Testwork\Hook\Scope\BeforeSuiteScope;
/**
* Trait DatabaseRefreshingTrait.
*
* This trait adds some extra load to the tests, however it provides more
* consistent results and less need for managing cleanups.
*/
trait DatabaseRefreshingTrait {
/**
* A local cache property which tracks the first run status.
*
* @var bool
*/
public static $isFirstRun = TRUE;
/**
* Creates the initial backup when starting to run tests.
*
* @param \Behat\Testwork\Hook\Scope\BeforeSuiteScope $beforeSuiteScope
* The before suite scope.
*
* @BeforeSuite
*/
public static function saveDbBeforeSuite(BeforeSuiteScope $beforeSuiteScope): void {
echo 'DatabaseRefreshingTrait: Saving db to temporary file.' . PHP_EOL;
$file = $beforeSuiteScope->getEnvironment()
->getSuite()
->getSetting('paths');
$file = $file[0] . '/dump-behat-sql.sql';
exec("mysqldump --user={$_ENV["DRUPAL_DATABASE_USERNAME"]} --password={$_ENV["DRUPAL_DATABASE_PASSWORD"]} --host={$_ENV["DRUPAL_DATABASE_HOST"]} {$_ENV["DRUPAL_DATABASE_NAME"]} --result-file={$file} 2>&1");
}
/**
* Restores the db before a new scenario is running.
*
* @param \Behat\Behat\Hook\Scope\BeforeScenarioScope $beforeScenarioScope
* The before scenario scope.
*
* @BeforeScenario
*/
public static function restoreStateBeforeScenario(BeforeScenarioScope $beforeScenarioScope): void {
// Avoid this from running on the first scenario.
if (self::$isFirstRun) {
self::$isFirstRun = FALSE;
return;
}
echo 'DatabaseRefreshingTrait: Restoring db for next scenario.' . PHP_EOL;
$file = $beforeScenarioScope->getEnvironment()
->getSuite()
->getSetting('paths');
$file = $file[0] . '/dump-behat-sql.sql';
exec("mysql --user={$_ENV["DRUPAL_DATABASE_USERNAME"]} --password={$_ENV["DRUPAL_DATABASE_PASSWORD"]} --host={$_ENV["DRUPAL_DATABASE_HOST"]} {$_ENV["DRUPAL_DATABASE_NAME"]} < {$file} 2>&1");
}
/**
* Restores once more after all tests are done.
*
* @param \Behat\Testwork\Hook\Scope\AfterSuiteScope $afterSuiteScope
* The after suite scope.
*
* @AfterSuite
*/
public static function restoreStateAfterSuite(AfterSuiteScope $afterSuiteScope): void {
echo 'DatabaseRefreshingTrait: Restoring db after test suite.' . PHP_EOL;
$file = $afterSuiteScope->getEnvironment()
->getSuite()
->getSetting('paths');
$file = $file[0] . '/dump-behat-sql.sql';
exec("mysql --user={$_ENV["DRUPAL_DATABASE_USERNAME"]} --password={$_ENV["DRUPAL_DATABASE_PASSWORD"]} --host={$_ENV["DRUPAL_DATABASE_HOST"]} {$_ENV["DRUPAL_DATABASE_NAME"]} < {$file} 2>&1");
exec("rm $file");
}
}
@haringsrob
Copy link
Author

Note: You can replace $_ENV["DRUPAL_DATABASE_USERNAME"] by whatever build strategy you are using (read from file, read from settings.php, ...).

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