1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2024-11-24 03:42:32 +01:00

Merge pull request #3751 from BookStackApp/parallel_testing

Parallel Testing Support
This commit is contained in:
Dan Brown 2022-09-27 01:31:37 +01:00 committed by GitHub
commit 67d7534d4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 13 deletions

View File

@ -44,6 +44,7 @@
"ssddanbrown/htmldiff": "^1.0.2"
},
"require-dev": {
"brianium/paratest": "^6.6",
"fakerphp/faker": "^1.16",
"itsgoingd/clockwork": "^5.1",
"mockery/mockery": "^1.4",
@ -73,6 +74,8 @@
"format": "phpcbf",
"lint": "phpcs",
"test": "phpunit",
"t": "@php artisan test --parallel",
"t-reset": "@php artisan test --recreate-databases",
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"

View File

@ -108,14 +108,9 @@ npm run dev
BookStack has many integration tests that use Laravel's built-in testing capabilities which makes use of PHPUnit. There is a `mysql_testing` database defined within the app config which is what is used by PHPUnit. This database is set with the database name, user name and password all defined as `bookstack-test`. You will have to create that database and that set of credentials before testing.
The testing database will also need migrating and seeding beforehand. This can be done with the following commands:
The testing database will also need migrating and seeding beforehand. This can be done by running `composer refresh-test-database`.
``` bash
php artisan migrate --database=mysql_testing
php artisan db:seed --class=DummyContentSeeder --database=mysql_testing
```
Once done you can run `composer test` in the application root directory to run all tests.
Once done you can run `composer test` in the application root directory to run all tests. Tests can be ran in parallel by running them via `composer t`. This will use Laravel's built-in parallel testing functionality, and attempt to create and seed a database instance for each testing thread. If required these parallel testing instances can be reset, before testing again, by running `composer t-reset`.
### 📜 Code Standards

View File

@ -22,10 +22,12 @@ use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Env;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Testing\Assert as PHPUnit;
use Monolog\Handler\TestHandler;
@ -47,6 +49,21 @@ abstract class TestCase extends BaseTestCase
*/
protected string $baseUrl = 'http://localhost';
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
/** @var \Illuminate\Foundation\Application $app */
$app = require __DIR__ . '/../bootstrap/app.php';
$app->register(TestServiceProvider::class);
$app->make(Kernel::class)->bootstrap();
return $app;
}
/**
* Set the current user context to be an admin.
*/
@ -299,6 +316,8 @@ abstract class TestCase extends BaseTestCase
/**
* Run a set test with the given env variable.
* Remembers the original and resets the value after test.
* Database config is juggled so the value can be restored when
* parallel testing are used, where multiple databases exist.
*/
protected function runWithEnv(string $name, $value, callable $callback)
{
@ -311,7 +330,12 @@ abstract class TestCase extends BaseTestCase
$_SERVER[$name] = $value;
}
$database = config('database.connections.mysql_testing.database');
$this->refreshApplication();
DB::purge();
config()->set('database.connections.mysql_testing.database', $database);
$callback();
if (is_null($originalVal)) {

View File

@ -0,0 +1,26 @@
<?php
namespace Tests;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\ParallelTesting;
use Illuminate\Support\ServiceProvider;
class TestServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
// Tell Laravel's parallel testing functionality to seed the test
// databases with the DummyContentSeeder upon creation.
// This is only done for initial database creation. Seeding
// won't occur on every run.
ParallelTesting::setUpTestDatabase(function ($database, $token) {
Artisan::call('db:seed --class=DummyContentSeeder');
});
}
}

View File

@ -322,8 +322,8 @@ class ThemeTest extends TestCase
public function test_export_body_start_and_end_template_files_can_be_used()
{
$bodyStartStr = 'barry-fought-against-the-panther';
$bodyEndStr = 'barry-lost-his-fight-with-grace';
$bodyStartStr = 'garry-fought-against-the-panther';
$bodyEndStr = 'garry-lost-his-fight-with-grace';
/** @var Page $page */
$page = Page::query()->first();
@ -342,18 +342,18 @@ class ThemeTest extends TestCase
protected function usingThemeFolder(callable $callback)
{
// Create a folder and configure a theme
$themeFolderName = 'testing_theme_' . rtrim(base64_encode(time()), '=');
$themeFolderName = 'testing_theme_' . str_shuffle(rtrim(base64_encode(time()), '='));
config()->set('view.theme', $themeFolderName);
$themeFolderPath = theme_path('');
// Create theme folder and clean it up on application tear-down
File::makeDirectory($themeFolderPath);
$this->beforeApplicationDestroyed(fn() => File::deleteDirectory($themeFolderPath));
// Run provided callback with theme env option set
$this->runWithEnv('APP_THEME', $themeFolderName, function () use ($callback, $themeFolderName) {
call_user_func($callback, $themeFolderName);
});
// Cleanup the custom theme folder we created
File::deleteDirectory($themeFolderPath);
}
}