Skip to content

Commit

Permalink
fix: PHPunit extensions must run before data providers (#917)
Browse files Browse the repository at this point in the history
* test: add a failing test case

* Run extension before loading the suite

---------

Co-authored-by: Filippo Tessarotto <[email protected]>
  • Loading branch information
nikophil and Slamdunk authored Dec 10, 2024
1 parent 64b784e commit 1ad660c
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 11 deletions.
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@
"phpunit/php-timer": "^7.0.1",
"phpunit/phpunit": "^11.5.0",
"sebastian/environment": "^7.2.0",
"symfony/console": "^6.4.14 || ^7.1.7",
"symfony/process": "^6.4.14 || ^7.1.7"
"symfony/console": "^6.4.14 || ^7.2.0",
"symfony/process": "^6.4.14 || ^7.2.0"
},
"require-dev": {
"ext-pcov": "*",
"ext-posix": "*",
"doctrine/coding-standard": "^12.0.0",
"phpstan/phpstan": "^2",
"phpstan/phpstan-deprecation-rules": "^2",
"phpstan/phpstan-phpunit": "^2",
"phpstan/phpstan": "^2.0.3",
"phpstan/phpstan-deprecation-rules": "^2.0.1",
"phpstan/phpstan-phpunit": "^2.0.1",
"phpstan/phpstan-strict-rules": "^2",
"squizlabs/php_codesniffer": "^3.11.1",
"symfony/filesystem": "^6.4.13 || ^7.1.6"
"symfony/filesystem": "^6.4.13 || ^7.2.0"
},
"autoload": {
"psr-4": {
Expand Down
33 changes: 32 additions & 1 deletion src/WrapperRunner/SuiteLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@

use Generator;
use ParaTest\Options;
use PHPUnit\Event\Facade as EventFacade;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Runner\Extension\ExtensionBootstrapper;
use PHPUnit\Runner\Extension\Facade as ExtensionFacade;
use PHPUnit\Runner\Extension\PharLoader;
use PHPUnit\Runner\PhptTestCase;
use PHPUnit\Runner\ResultCache\NullResultCache;
use PHPUnit\Runner\TestSuiteSorter;
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
use PHPUnit\TextUI\Command\Result;
use PHPUnit\TextUI\Command\WarmCodeCoverageCacheCommand;
use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry;
Expand Down Expand Up @@ -50,9 +55,35 @@ public function __construct(
(new PhpHandler())->handle($this->options->configuration->php());

if ($this->options->configuration->hasBootstrap()) {
include_once $this->options->configuration->bootstrap();
$bootstrapFilename = $this->options->configuration->bootstrap();
include_once $bootstrapFilename;
EventFacade::emitter()->testRunnerBootstrapFinished($bootstrapFilename);
}

if (! $this->options->configuration->noExtensions()) {
if ($this->options->configuration->hasPharExtensionDirectory()) {
(new PharLoader())->loadPharExtensionsInDirectory(
$this->options->configuration->pharExtensionDirectory(),
);
}

$extensionFacade = new ExtensionFacade();
$extensionBootstrapper = new ExtensionBootstrapper(
$this->options->configuration,
$extensionFacade,
);

foreach ($this->options->configuration->extensionBootstrappers() as $bootstrapper) {
$extensionBootstrapper->bootstrap(
$bootstrapper['className'],
$bootstrapper['parameters'],
);
}
}

TestResultFacade::init();
EventFacade::instance()->seal();

$testSuite = (new TestSuiteBuilder())->build($this->options->configuration);

if ($this->options->configuration->executionOrder() === TestSuiteSorter::ORDER_RANDOMIZED) {
Expand Down
3 changes: 0 additions & 3 deletions src/WrapperRunner/WrapperRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use ParaTest\JUnit\Writer;
use ParaTest\Options;
use ParaTest\RunnerInterface;
use PHPUnit\Event\Facade as EventFacade;
use PHPUnit\Runner\CodeCoverage;
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
use PHPUnit\TestRunner\TestResult\TestResult;
Expand Down Expand Up @@ -100,8 +99,6 @@ public function run(): int
$directory = dirname(__DIR__);
assert($directory !== '');
ExcludeList::addDirectory($directory);
TestResultFacade::init();
EventFacade::instance()->seal();
$suiteLoader = new SuiteLoader(
$this->options,
$this->output,
Expand Down
12 changes: 11 additions & 1 deletion test/TestBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use ParaTest\Options;
use ParaTest\RunnerInterface;
use ParaTest\WrapperRunner\WrapperRunner;
use PHPUnit\Event\Facade;
use PHPUnit\Framework\TestCase;
use ReflectionProperty;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Output\BufferedOutput;
Expand Down Expand Up @@ -87,7 +89,15 @@ final protected function runRunner(): RunnerResult
unset($_SERVER[Options::ENV_KEY_UNIQUE_TOKEN]);
}

$exitCode = $runner->run();
$refProperty = new ReflectionProperty(Facade::class, 'instance');
$keep = $refProperty->getValue(new Facade());
$refProperty->setValue(new Facade(), null);
try {
$exitCode = $runner->run();
} finally {
$refProperty->setValue(new Facade(), $keep);
}

if ($shouldPutEnvForParatestTestingItSelf) {
putenv(Options::ENV_KEY_TOKEN . '=' . $prevToken);
putenv(Options::ENV_KEY_UNIQUE_TOKEN . '=' . $prevUniqueToken);
Expand Down
21 changes: 21 additions & 0 deletions test/Unit/WrapperRunner/WrapperRunnerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,27 @@ public function testBaselineIsRespected(): void
Time: %s, Memory: %s MB
OK%a
EOF;
self::assertStringMatchesFormat($expectedOutput, $runnerResult->output);
self::assertEquals(RunnerInterface::SUCCESS_EXIT, $runnerResult->exitCode);
}

public function testExtensionMustRunBeforeDataProvider(): void
{
$this->bareOptions['--configuration'] = $this->fixture('extension_run_before_data_provider' . DIRECTORY_SEPARATOR . 'phpunit.xml');

$runnerResult = $this->runRunner();

$expectedOutput = <<<EOF
Processes: %s
Runtime: PHP %s
Configuration: {$this->bareOptions['--configuration']}
. 1 / 1 (100%)
Time: %s, Memory: %s MB
OK%a
EOF;
self::assertStringMatchesFormat($expectedOutput, $runnerResult->output);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace ParaTest\Tests\fixtures\extension_run_before_data_provider;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use RuntimeException;

final class ExtensionMustRunBeforeDataProviderTest extends TestCase
{
public static string $var = 'foo';

#[DataProvider('provide')]
public function testExtensionMustRunBeforeDataProvider(string $var): void
{
self::assertSame('bar', $var);
}

/** @return iterable<array{string}> */
public static function provide(): iterable
{
if (self::$var !== 'bar') {
throw new RuntimeException('Extension did not run before data provider.');
}

yield [self::$var];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace ParaTest\Tests\fixtures\extension_run_before_data_provider;

use PHPUnit\Event;
use PHPUnit\Runner;
use PHPUnit\TextUI;

final class PHPUnitExtension implements Runner\Extension\Extension
{
public function bootstrap(
TextUI\Configuration\Configuration $configuration,
Runner\Extension\Facade $facade,
Runner\Extension\ParameterCollection $parameters,
): void {
$facade->registerSubscribers(
new class implements Event\Test\DataProviderMethodCalledSubscriber {
public function notify(Event\Test\DataProviderMethodCalled $event): void
{
ExtensionMustRunBeforeDataProviderTest::$var = 'bar';
}
},
);
}
}
10 changes: 10 additions & 0 deletions test/fixtures/extension_run_before_data_provider/phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<phpunit>
<testsuites>
<testsuite name="ExtensionMustRunBeforeDataProviderTest">
<file>ExtensionMustRunBeforeDataProviderTest.php</file>
</testsuite>
</testsuites>
<extensions>
<bootstrap class="ParaTest\Tests\fixtures\extension_run_before_data_provider\PHPUnitExtension" />
</extensions>
</phpunit>

0 comments on commit 1ad660c

Please sign in to comment.