Add ability to specify the connection used for running tests (#4159)

Credit to @czerwonyd
This commit is contained in:
Tomasz Strojny 2019-03-31 14:28:24 +02:00 committed by Luke Towers
parent 8280047d30
commit 956a234920
4 changed files with 90 additions and 15 deletions

View File

@ -125,4 +125,20 @@ return [
],
/*
|--------------------------------------------------------------------------
| Use DB configuration for testing
|--------------------------------------------------------------------------
|
| When running plugin tests OctoberCMS by default uses SQLite in memory.
| You can override this behavior by setting `useConfigForTesting` to true.
|
| After that OctoberCMS will take DB parameters from the config.
| If file `/config/testing/database.php` exists, config will be read from it,
| but remember that when not specified it will use parameters specified in
| `/config/database.php`.
|
*/
'useConfigForTesting' => false,
];

View File

@ -125,6 +125,7 @@ class OctoberEnv extends Command
{
foreach ($keys as $envKey => $configKey) {
$pattern = $this->buildPattern($configKey);
$callback = $this->buildCallback($envKey, $configKey);
if (preg_match($pattern, $line)) {
@ -142,7 +143,6 @@ class OctoberEnv extends Command
private function replaceDbConfigLine($line)
{
if ($this->config == 'database') {
foreach ($this->dbConfig() as $connection => $settings) {
$this->setCurrentConnection($line, $connection);
@ -183,7 +183,6 @@ class OctoberEnv extends Command
private function buildCallback($envKey, $configKey)
{
return function ($matches) use ($envKey, $configKey) {
$value = $this->envValue($configKey);
$this->saveEnvSettings($envKey, $value);
@ -249,6 +248,10 @@ class OctoberEnv extends Command
return config('database.default');
}
if ($configKey == 'useConfigForTesting') {
return config('database.useConfigForTesting');
}
if ($this->connection == 'redis') {
return config("database.redis.default.$configKey");
}
@ -345,6 +348,7 @@ class OctoberEnv extends Command
],
'database' => [
'DB_CONNECTION' => 'default',
'DB_USE_CONFIG_FOR_TESTING' => 'useConfigForTesting',
],
'cache' => [
'CACHE_DRIVER' => 'default',
@ -402,5 +406,4 @@ class OctoberEnv extends Command
],
];
}
}

View File

@ -25,14 +25,25 @@ abstract class PluginTestCase extends Illuminate\Foundation\Testing\TestCase
$app->setLocale('en');
/*
* Store database in memory
* Store database in memory by default, if not specified otherwise
*/
$app['config']->set('database.default', 'sqlite');
$app['config']->set('database.connections.sqlite', [
$dbConnection = 'sqlite';
$dbConnections = [];
$dbConnections['sqlite'] = [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => ''
]);
];
if (env('APP_ENV') === 'testing' && Config::get('database.useConfigForTesting', false)) {
$dbConnection = Config::get('database.default', 'sqlite');
$dbConnections[$dbConnection] = Config::get('database.connections' . $dbConnection, $dbConnections['sqlite']);
}
$app['config']->set('database.default', $dbConnection);
$app['config']->set('database.connections.' . $dbConnection, $dbConnections[$dbConnection]);
/*
* Modify the plugin path away from the test context
@ -53,7 +64,7 @@ abstract class PluginTestCase extends Illuminate\Foundation\Testing\TestCase
*/
PluginManager::forgetInstance();
UpdateManager::forgetInstance();
/*
* Create application instance
*/
@ -109,7 +120,9 @@ abstract class PluginTestCase extends Illuminate\Foundation\Testing\TestCase
protected function runPluginRefreshCommand($code, $throwException = true)
{
if (!preg_match('/^[\w+]*\.[\w+]*$/', $code)) {
if (!$throwException) return;
if (!$throwException) {
return;
}
throw new Exception(sprintf('Invalid plugin code: "%s"', $code));
}
@ -124,7 +137,9 @@ abstract class PluginTestCase extends Illuminate\Foundation\Testing\TestCase
$path = array_get($manager->getPluginNamespaces(), $namespace);
if (!$path) {
if (!$throwException) return;
if (!$throwException) {
return;
}
throw new Exception(sprintf('Unable to find plugin with code: "%s"', $code));
}
@ -138,8 +153,9 @@ abstract class PluginTestCase extends Illuminate\Foundation\Testing\TestCase
if (!empty($plugin->require)) {
foreach ((array) $plugin->require as $dependency) {
if (isset($this->pluginTestCaseLoadedPlugins[$dependency])) continue;
if (isset($this->pluginTestCaseLoadedPlugins[$dependency])) {
continue;
}
$this->runPluginRefreshCommand($dependency);
}

View File

@ -4,7 +4,7 @@ Plugin unit tests can be performed by running `phpunit` in the base plugin direc
### Creating plugin tests
Plugins can be tested by creating a creating a file called `phpunit.xml` in the base directory with the following content, for example, in a file **/plugins/acme/blog/phpunit.xml**:
Plugins can be tested by creating a file called `phpunit.xml` in the base directory with the following content, for example, in a file **/plugins/acme/blog/phpunit.xml**:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
@ -46,13 +46,53 @@ Then a **tests/** directory can be created to contain the test classes. The file
}
}
The test class should extend the base class `PluginTestCase` and this is a special class that will set up the October database stored in memory, as part of the `setUp()` method. It will also refresh the plugin being testing, along with any of the defined dependencies in the plugin registration file. This is the equivalent of running the following before each test:
The test class should extend the base class `PluginTestCase` and this is a special class that will set up the October database stored in memory, as part of the `setUp` method. It will also refresh the plugin being tested, along with any of the defined dependencies in the plugin registration file. This is the equivalent of running the following before each test:
php artisan october:up
php artisan plugin:refresh Acme.Blog
[php artisan plugin:refresh <dependency>, ...]
# System testing
> **Note:** If your plugin uses [configuration files](../plugin/settings#file-configuration), then you will need to run `System\Classes\PluginManager::instance()->registerAll(true);` in the `setUp` method of your tests. Below is an example of a base test case class that should be used if you need to test your plugin working with other plugins instead of in isolation.
use System\Classes\PluginManager;
class BaseTestCase extends PluginTestCase
{
public function setUp()
{
parent::setUp();
// Get the plugin manager
$pluginManager = PluginManager::instance();
// Register the plugins to make features like file configuration available
$pluginManager->registerAll(true);
// Boot all the plugins to test with dependencies of this plugin
$pluginManager->bootAll(true);
}
public function tearDown()
{
parent::tearDown();
// Get the plugin manager
$pluginManager = PluginManager::instance();
// Ensure that plugins are registered again for the next test
$pluginManager->unregisterAll();
}
}
#### Changing database engine for plugins tests
By default OctoberCMS uses SQLite stored in memory for the plugin testing environment. If you want to override the default behavior set the `useConfigForTesting` config to `true` in your `/config/database.php` file. When the `APP_ENV` is `testing` and the `useConfigForTesting` is `true` database parameters will be taken from `/config/database.php`.
You can override the `/config/database.php` file by creating `/config/testing/database.php`. In this case variables from the latter file will be taken.
## System testing
To perform unit testing on the core October files, you should download a development copy using composer or cloning the git repo. This will ensure you have the `tests/` directory.
### Unit tests