Adding support to "dump", "populate" and "cleanup" parameters
henrydekap opened this issue · 3 comments
This is meant for branch 1.0, I didn't have the time to test it in 2.0
Adding the standard Db module functionalities to load a specified dump for each connection, and setup the cleanup and populate config:
example config from codeception.yml:
Codeception\Extension\MultiDb:
timezone: '+00:00'
connectors:
Dev:
dsn: "mysql:host=127.0.0.1;port=3306;dbname=test_dev"
user: 'testuser'
password: 'whatever'
dump: tests/_data/test_dev.sql
populate: true
cleanup: true
Prod:
dsn: "mysql:host=127.0.0.1;port=3306;dbname=test_prod"
user: 'testuser'
password: 'whatever'
dump: tests/_data/test_prod.sql
populate: true
cleanup: true
What is needed is to add some code to the _initialize() function (taken directly from the Db module), and two protected functions to do the load and cleanup for the specified driver:
https://github.com/redmatter/Codeception-MultiDb/blob/1.0/src/Codeception/Extension/MultiDb.php
<?php
/**
* @copyright 2009-2014 Red Matter Ltd (UK)
*/
namespace Codeception\Extension;
use Codeception\Exception\TestRuntime as TestRuntimeException;
use Codeception\Extension\MultiDb\Utils\AsIs;
use Codeception\Extension\MultiDb\Utils\CleanupAction;
use Codeception\Lib\Driver\Db as Driver;
use Codeception\Exception\Module as ModuleException;
use Codeception\Exception\ModuleConfig as ModuleConfigException;
use Codeception\Module;
use Codeception\TestCase;
use Codeception\Configuration as Configuration;
/**
* MultiDb - Module that allows tests to perform setup queries and assertions across multiple databases.
*/
class MultiDb extends Module
{
const ASIS_PREFIX = '@asis ';
const CLEANUP_NEVER = 0;
const CLEANUP_AFTER_TEST = 1;
const CLEANUP_AFTER_SUITE = 2;
protected $dbh;
protected $config = ['connectors' => false, 'timezone' => 'UTC'];
protected $requiredFields = ['connectors'];
/** @var Driver[] */
protected $drivers = [];
/** @var Driver */
protected $chosenDriver = null;
protected $chosenConnector;
/** @var CleanupAction[] */
protected $test_cleanup_actions = [];
/** @var CleanupAction[] */
protected $suite_cleanup_actions = [];
protected $connectorRequiredFields = ['dsn', 'user', 'password'];
/** @var string */
private $timezone;
/** @var int */
private $transaction_level = 0;
/** @var string */
private $transaction_connector = null;
// HOOK: used after configuration is loaded
// @codingStandardsIgnoreLine overridden function from \Codeception\Module
public function _initialize()
{
$configOk = false;
if (is_array($this->config['connectors'])) {
foreach ($this->config['connectors'] as $connector => $connectorConfig) {
if (is_array($connectorConfig)) {
$fields = array_keys($connectorConfig);
$configOk = (
array_intersect($this->connectorRequiredFields, $fields) == $this->connectorRequiredFields
);
if (!$configOk) {
break;
}
}
}
}
if (!$configOk) {
throw new ModuleConfigException(
__CLASS__,
"\nOptions: " . implode(', ', $this->connectorRequiredFields) . " are required\n
Please, update the configuration and set all the required fields\n\n"
);
}
$this->timezone = $this->config['timezone'];
parent::_initialize();
foreach ($this->config['connectors'] as $connector => $connectorConfig) {
if ($connectorConfig['populate']) {
if ($connectorConfig['cleanup']) {
$this->cleanup($connector);
}
$this->loadDump($connector);
}
}
}
protected function loadDump($connector)
{
$config = $this->config['connectors'][$connector];
if ($config['dump'] && ($config['cleanup'] or ($config['populate']))) {
if (!file_exists(Configuration::projectDir() . $config['dump'])) {
throw new ModuleConfigException(
__CLASS__,
"\nFile with dump doesn't exist.
Please, check path for sql file: " . $config['dump']
);
}
$sql = file_get_contents(Configuration::projectDir() . $config['dump']);
$sql = preg_replace('%/\*(?!!\d+)(?:(?!\*/).)*\*/%s', "", $sql);
if (!empty($sql)) {
$sql = explode("\n", $sql);
}
}
if (!$sql) {
return;
}
try {
$this->getDriver($connector)->load($sql);
} catch (\PDOException $e) {
throw new ModuleException(
__CLASS__,
$e->getMessage() . "\nSQL query being executed: " . $sql
);
}
}
protected function cleanup($connector)
{
try {
$this->getDriver($connector)->cleanup();
} catch (\Exception $e) {
throw new ModuleException(__CLASS__, $e->getMessage());
}
}
[...]
}
Very good idea @henrydekap; feel free to make a pull request.
I would like to see this feature completed in the near future. Just swapped out the DB module for this MultiDb and this is the part that is missing.