8000 [9.x] Adds support for Parallel Testing by nunomaduro · Pull Request #35778 · laravel/framework · GitHub
[go: up one dir, main page]

Skip to content

[9.x] Adds support for Parallel Testing #35778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 52 commits into from
Jan 13, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6418fed
Adds parallel testing
nunomaduro Jan 4, 2021
dcc5112
Fixes "Class MysqlBuilder" not found
nunomaduro Jan 4, 2021
bb004e5
Updates wording when drivers do not support create/drop databases
nunomaduro Jan 4, 2021
8e30c93
Avoids "getenv" and "putenv" in favour of $_SERVER
nunomaduro Jan 5, 2021
36d5e7a
Moves "createDatabaseIfNotExists" to "createDatabase"
nunomaduro Jan 5, 2021
a546cf2
Adds support to "Postgres"
nunomaduro Jan 5, 2021
b0b6243
Fixes CS
nunomaduro Jan 5, 2021
5697ee4
Uses a database per process regardless of the used database testing t…
nunomaduro Jan 7, 2021
07d9cb3
Apply fixes from StyleCI
nunomaduro Jan 7, 2021
d9ba522
Merge pull request #3 from nunomaduro/analysis-wj2l5w
nunomaduro Jan 7, 2021
83f648d
Removes unused catch
nunomaduro Jan 7, 2021
d4afcf2
Merge branch 'feat/adds-parallel-testing' of https://github.com/nunom…
nunomaduro Jan 7, 2021
66d2dcc
Refactors into service providers
nunomaduro Jan 7, 2021
70a231e
Apply fixes from StyleCI
nunomaduro Jan 7, 2021
f08a714
Merge pull request #4 from nunomaduro/analysis-KZ6kV6
nunomaduro Jan 7, 2021
2f60c87
Removes token resolver from the public API
nunomaduro Jan 7, 2021
208bf65
Renames Parallel Testing register callbacks
nunomaduro Jan 7, 2021
447c27b
Fixes CS
nunomaduro Jan 7, 2021
27a2c49
Adds "setUp" process and "tearDown" test case
nunomaduro Jan 8, 2021
e18d25d
Updates Parallel Testing facade
nunomaduro Jan 8, 2021
f140288
Suffixes _test_ on storage too
nunomaduro Jan 8, 2021
2793882
Fixes missing envs for process callbacks
nunomaduro Jan 8, 2021
0cd2df7
Apply fixes from StyleCI
nunomaduro Jan 8, 2021
9749170
Merge pull request #5 from nunomaduro/analysis-OMYD5l
nunomaduro Jan 8, 2021
8c560a6
Ensures "drops" only happen when needed
nunomaduro Jan 8, 2021
0f1e621
Apply fixes from StyleCI
nunomaduro Jan 8, 2021
f690305
Merge pull request #6 from nunomaduro/analysis-e7kaPv
nunomaduro Jan 8, 2021
29d705c
Adds support for SQLite file databases
nunomaduro Jan 11, 2021
52de4b4
Adds tests for SQLite file databases
nunomaduro Jan 11, 2021
f255cee
Lower case create/drop statements
nunomaduro Jan 11, 2021
3d62d42
Adds support for SQL Server
nunomaduro Jan 11, 2021
2a5c678
Apply fixes from StyleCI
nunomaduro Jan 11, 2021
0bb1ca2
Merge pull request #7 from nunomaduro/analysis-d02NGv
nunomaduro Jan 11, 2021
d29bb9d
Adds tests against Parallel Testing callbacks
nunomaduro Jan 11, 2021
b2c3296
Adds tests for parallel console output
nunomaduro Jan 11, 2021
49c4b28
Apply fixes from StyleCI
nunomaduro Jan 11, 2021
df2107d
Merge pull request #8 from nunomaduro/analysis-Zl51bP
nunomaduro Jan 11, 2021
e85ed40
Removes unused lines in tests
nunomaduro Jan 11, 2021
3c6d8d1
Merge branch 'feat/adds-parallel-testing' of https://github.com/nunom…
nunomaduro Jan 11, 2021
cc4bffa
Calls Parallel Testing setUp callbacks after refresh app only
nunomaduro Jan 11, 2021
4f57aac
Cleans folders for parallel testing
nunomaduro Jan 11, 2021
69b9eb0
Makes test databases persist
nunomaduro Jan 12, 2021
b389c43
Apply fixes from StyleCI
nunomaduro Jan 12, 2021
f280ffa
Merge pull request #9 from nunomaduro/analysis-3w0NZr
nunomaduro Jan 12, 2021
528b6bd
Resolve parallel testing callbacks from container
nunomaduro Jan 12, 2021
c15917c
Merge branch 'feat/adds-parallel-testing' of https://github.com/nunom…
nunomaduro Jan 12, 2021
0f4c024
Apply fixes from StyleCI
nunomaduro Jan 12, 2021
85c5558
Merge pull request #10 from nunomaduro/analysis-gOgb36
nunomaduro Jan 12, 2021
f52fa9e
Update TestDatabases.php
taylorotwell Jan 12, 2021
985c3d3
Update ParallelTesting.php
taylorotwell Jan 12, 2021
a3109db
Renames "refresh-databases" to "recreate-databases"
nunomaduro Jan 13, 2021
8e0c299
Merge branch 'feat/adds-parallel-testing' of https://github.com/nunom…
nunomaduro Jan 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Uses a database per process regardless of the used database testing t…
…rait
  • Loading branch information
nunomaduro committed Jan 7, 2021
commit 5697ee4f50c290e33b6fafac7ec09ec61ba115f3
76 changes: 3 additions & 73 deletions src/Illuminate/Foundation/Testing/RefreshDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
namespace Illuminate\Foundation\Testing;

use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Testing;

trait RefreshDatabase
{
Expand All @@ -15,15 +13,9 @@ trait RefreshDatabase
*/
public function refreshDatabase()
{
if ($this->usingInMemoryDatabase()) {
return $this->refreshInMemoryDatabase();
}

Testing::whenRunningInParallel(function () {
$this->switchToTemporaryDatabase();
});

$this->refreshTestDatabase();
$this->usingInMemoryDatabase()
? $this->refreshInMemoryDatabase()
: $this->refreshTestDatabase();
}

/**
Expand All @@ -38,68 +30,6 @@ protected function usingInMemoryDatabase()
return config("database.connections.$default.database") === ':memory:';
}

/**
* Switch to the temporary test database.
*
* @return void
*/
protected function switchToTemporaryDatabase()
{
$default = config('database.default');

config()->set(
"database.connections.{$default}.database",
RefreshDatabaseState::$temporaryDatabase,
);
}

/**
* Creates a temporary database, if needed.
*
* @beforeClass
*
* @return void
*/
public static function setUpTemporaryDatabase()
{
tap(new static(), function ($testCase) {
$testCase->refreshApplication();

if ($testCase->usingInMemoryDatabase()) {
return;
}

Testing::whenRunningInParallel(function () use ($testCase) {
$name = $testCase->getConnection()->getConfig('database');

RefreshDatabaseState::$temporaryDatabase = Testing::addTokenIfNeeded($name);

Schema::dropDatabaseIfExists(RefreshDatabaseState::$temporaryDatabase);
Schema::createDatabase(RefreshDatabaseState::$temporaryDatabase);
});
})->app->flush();
}

/**
* Drop the temporary database, if any.
*
* @afterClass
*
* @return void
*/
public static function tearDownTemporaryDatabase()
{
if (RefreshDatabaseState::$temporaryDatabase) {
tap(new static(), function ($testCase) {
$testCase->refreshApplication();

Schema::dropDatabaseIfExists(
RefreshDatabaseState::$temporaryDatabase,
);
})->app->flush();
}
}

/**
* Refresh the in-memory database.
*
Expand Down
7 changes: 0 additions & 7 deletions src/Illuminate/Foundation/Testing/RefreshDatabaseState.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,4 @@ class RefreshDatabaseState
* @var bool
*/
public static $migrated = false;

/**
* The temporary database name, if any.
*
* @var string|null
*/
public static $temporaryDatabase;
}
3 changes: 3 additions & 0 deletions src/Illuminate/Foundation/Testing/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Console\Application as Artisan;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Facade;
use Illuminate\Testing\ParallelTesting;
use Illuminate\Support\Str;
use Mockery;
use Mockery\Exception\InvalidCountException;
Expand Down Expand Up @@ -83,6 +84,8 @@ protected function setUp(): void
$this->refreshApplication();
}

$this->app[ParallelTesting::class]->setUpIfNeeded($this);

$this->setUpTraits();

foreach ($this->afterApplicationCreatedCallbacks as $callback) {
Expand Down
3 changes: 2 additions & 1 deletion src/Illuminate/Support/Facades/Storage.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Illuminate\Support\Facades;

use Illuminate\Filesystem\Filesystem;
use Illuminate\Testing\ParallelTesting;

/**
* @method static \Illuminate\Contracts\Filesystem\Filesystem assertExists(string|array $path)
Expand Down Expand Up @@ -54,7 +55,7 @@ public static function fake($disk = null, array $config = [])
$root = storage_path('framework/testing/disks/'.$disk)
);

$root = Testing::addTokenIfNeeded($root);
$root = static::$app[ParallelTesting::class]->addTokenIfNeeded($root);

static::set($disk, $fake = static::createLocalDriver(array_merge($config, [
'root' => $root,
Expand Down
22 changes: 0 additions & 22 deletions src/Illuminate/Support/Facades/Testing.php

This file was deleted.

61 changes: 61 additions & 0 deletions src/Illuminate/Testing/ParallelConsoleOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Illuminate\Testing;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Symfony\Component\Console\Output\ConsoleOutput;

class ParallelConsoleOutput extends ConsoleOutput
{
/**
* The original output instance.
*
* @var \Symfony\Component\Console\Output\OutputInterface
*/
protected $output;

/**
* The output that should be ignored.
*
* @var array
*/
protected $ignore = [
'Running phpunit in',
'Configuration read from',
];

/**
* Create a new Parallel ConsoleOutput instance.
*
* @param \Symfony\Component\Console\Output\OutputInterface
* @return void
*/
public function __construct($output)
{
parent::__construct(
$output->getVerbosity(),
$output->isDecorated(),
$output->getFormatter(),
);

$this->output = $output;
}

/**
* Writes a message to the output.
*
* @param string|iterable $messages
* @param bool $newline
* @param int $options
* @return void
*/
public function write($messages, bool $newline = false, int $options = 0)
{
$messages = collect($messages)->filter(function ($message) {
return ! Str::contains($message, $this->ignore);
});

$this->output->write($messages->toArray(), $newline, $options);
}
}
136 changes: 136 additions & 0 deletions src/Illuminate/Testing/ParallelRunner.php
10854
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php

namespace Illuminate\Testing;

use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Facades\Schema;
use ParaTest\Runners\PHPUnit\Options;
use ParaTest\Runners\PHPUnit\RunnerInterface;
use ParaTest\Runners\PHPUnit\WrapperRunner;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\OutputInterface;

class ParallelRunner implements RunnerInterface
{
/**
* The application resolver callback.
*
* @var \Closure|null
*/
protected static $applicationResolver;

/**
* The original test runner options.
*
* @var \ParaTest\Runners\PHPUnit\Options
*/
protected $options;

/**
* The output instance.
*
* @var \Symfony\Component\Console\Output\OutputInterface
*/
protected $output;

/**
* The original test runner.
*
* @var \ParaTest\Runners\PHPUnit\RunnerInterface
*/
protected $runner;

/**
* Creates a new test runner instance.
*
* @param \ParaTest\Runners\PHPUnit\Options $options
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return void
*/
public function __construct(Options $options, OutputInterface $output)
{
$this->options = $options;

if ($output instanceof ConsoleOutput) {
$output = new ParallelConsoleOutput($output);
}

$this->runner = new WrapperRunner($options, $output);
}

/**
* Set the application resolver callback.
*
* @param \Closure|null $resolver
* @return void
*/
public static function resolveApplicationUsing($resolver)
{
static::$applicationResolver = $resolver;
}

/**
* Runs the test suite.
*
* @return void
*/
public function run(): void
{
try {
$this->runner->run();
} catch (Throwable $e) {
throw $e;
} finally {
$this->forEachProcess(function ($app) {
$app[ParallelTesting::class]->beforeProcessDestroyed();
});
}
}

/**
* Returns the highest exit code encountered throughout the course of test execution.
*
* @return int
*/
public function getExitCode(): int
{
return $this->runner->getExitCode();
}

/**
* Apply the given callback for each process.
*
* @param callable $callback
* @return void
*/
protected function forEachProcess($callback)
{
collect(range(1, $this->options->processes()))->each(function ($token) use ($callback) {
tap($this->createApplication(), function ($app) use ($callback, $token) {
ParallelTesting::resolveTokenUsing(function () use ($token) {
return $token;
});

$callback($app);
})->flush();
});
}

/**
* Creates the application.
*
* @return \Illuminate\Contracts\Foundation\Application
*/
protected function createApplication()
{
$applicationResolver = static::$applicationResolver ?: function () {
$applicationCreator = new class {
use \Tests\CreatesApplication;
};

return $applicationCreator->createApplication();
};

return call_user_func($applicationResolver);
}
}
Loading
0