feat: adds phpunit 12.2.1 support

This commit is contained in:
Nuno Maduro
2025-06-08 15:29:23 +01:00
parent 02b1ffb334
commit 0fc9d4dfe0
12 changed files with 99 additions and 69 deletions

View File

@ -20,16 +20,15 @@
"php": "^8.3.0", "php": "^8.3.0",
"brianium/paratest": "^7.10.1", "brianium/paratest": "^7.10.1",
"nunomaduro/collision": "^8.8.0", "nunomaduro/collision": "^8.8.0",
"nunomaduro/pokio": "dev-main",
"nunomaduro/termwind": "^2.3.1", "nunomaduro/termwind": "^2.3.1",
"pestphp/pest-plugin": "^4.0.0", "pestphp/pest-plugin": "^4.0.0",
"pestphp/pest-plugin-arch": "^4.0.0", "pestphp/pest-plugin-arch": "^4.0.0",
"pestphp/pest-plugin-mutate": "^4.0.0", "pestphp/pest-plugin-mutate": "^4.0.0",
"phpunit/phpunit": "^12.1.6" "phpunit/phpunit": "^12.2.1"
}, },
"conflict": { "conflict": {
"filp/whoops": "<2.16.0", "filp/whoops": "<2.16.0",
"phpunit/phpunit": ">12.1.6", "phpunit/phpunit": ">12.2.1",
"sebastian/exporter": "<7.0.0", "sebastian/exporter": "<7.0.0",
"webmozart/assert": "<1.11.0" "webmozart/assert": "<1.11.0"
}, },

View File

@ -59,10 +59,10 @@ final class ResultPrinter
private readonly OutputInterface $output, private readonly OutputInterface $output,
private readonly Options $options private readonly Options $options
) { ) {
$this->printer = new class($this->output) implements Printer $this->printer = new readonly class($this->output) implements Printer
{ {
public function __construct( public function __construct(
private readonly OutputInterface $output, private OutputInterface $output,
) {} ) {}
public function print(string $buffer): void public function print(string $buffer): void

View File

@ -17,6 +17,7 @@ use ParaTest\WrapperRunner\WrapperWorker;
use Pest\Result; use Pest\Result;
use Pest\TestSuite; use Pest\TestSuite;
use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\Facade as EventFacade;
use PHPUnit\Event\Test\AfterLastTestMethodFailed;
use PHPUnit\Event\TestRunner\WarningTriggered; use PHPUnit\Event\TestRunner\WarningTriggered;
use PHPUnit\Runner\CodeCoverage; use PHPUnit\Runner\CodeCoverage;
use PHPUnit\Runner\ResultCache\DefaultResultCache; use PHPUnit\Runner\ResultCache\DefaultResultCache;
@ -313,12 +314,15 @@ final class WrapperRunner implements RunnerInterface
$testResult = unserialize($contents); $testResult = unserialize($contents);
assert($testResult instanceof TestResult); assert($testResult instanceof TestResult);
/** @var list<AfterLastTestMethodFailed> $failedEvents */
$failedEvents = array_merge_recursive($testResultSum->testFailedEvents(), $testResult->testFailedEvents());
$testResultSum = new TestResult( $testResultSum = new TestResult(
(int) $testResultSum->hasTests() + (int) $testResult->hasTests(), (int) $testResultSum->hasTests() + (int) $testResult->hasTests(),
$testResultSum->numberOfTestsRun() + $testResult->numberOfTestsRun(), $testResultSum->numberOfTestsRun() + $testResult->numberOfTestsRun(),
$testResultSum->numberOfAssertions() + $testResult->numberOfAssertions(), $testResultSum->numberOfAssertions() + $testResult->numberOfAssertions(),
array_merge_recursive($testResultSum->testErroredEvents(), $testResult->testErroredEvents()), array_merge_recursive($testResultSum->testErroredEvents(), $testResult->testErroredEvents()),
array_merge_recursive($testResultSum->testFailedEvents(), $testResult->testFailedEvents()), $failedEvents,
array_merge_recursive($testResultSum->testConsideredRiskyEvents(), $testResult->testConsideredRiskyEvents()), array_merge_recursive($testResultSum->testConsideredRiskyEvents(), $testResult->testConsideredRiskyEvents()),
array_merge_recursive($testResultSum->testSuiteSkippedEvents(), $testResult->testSuiteSkippedEvents()), array_merge_recursive($testResultSum->testSuiteSkippedEvents(), $testResult->testSuiteSkippedEvents()),
array_merge_recursive($testResultSum->testSkippedEvents(), $testResult->testSkippedEvents()), array_merge_recursive($testResultSum->testSkippedEvents(), $testResult->testSkippedEvents()),

View File

@ -100,10 +100,12 @@
--testdox ................ Replace default result output with TestDox format --testdox ................ Replace default result output with TestDox format
--testdox-summary Repeat TestDox output for tests with errors, failures, or issues --testdox-summary Repeat TestDox output for tests with errors, failures, or issues
--debug Replace default progress and result output with debugging information --debug Replace default progress and result output with debugging information
--with-telemetry Include telemetry information in debugging information output
--compact ................ Replace default result output with Compact format --compact ................ Replace default result output with Compact format
LOGGING OPTIONS: LOGGING OPTIONS:
--log-junit [file] .......... Write test results in JUnit XML format to file --log-junit [file] .......... Write test results in JUnit XML format to file
--log-otr [file] Write test results in Open Test Reporting XML format to file
--log-teamcity [file] ........ Write test results in TeamCity format to file --log-teamcity [file] ........ Write test results in TeamCity format to file
--testdox-html [file] .. Write test results in TestDox format (HTML) to file --testdox-html [file] .. Write test results in TestDox format (HTML) to file
--testdox-text [file] Write test results in TestDox format (plain text) to file --testdox-text [file] Write test results in TestDox format (plain text) to file
@ -115,6 +117,7 @@
--coverage ..... Generate code coverage report and output to standard output --coverage ..... Generate code coverage report and output to standard output
--coverage --min Set the minimum required coverage percentage, and fail if not met --coverage --min Set the minimum required coverage percentage, and fail if not met
--coverage-clover [file] Write code coverage report in Clover XML format to file --coverage-clover [file] Write code coverage report in Clover XML format to file
--coverage-openclover [file] Write code coverage report in OpenClover XML format to file
--coverage-cobertura [file] Write code coverage report in Cobertura XML format to file --coverage-cobertura [file] Write code coverage report in Cobertura XML format to file
--coverage-crap4j [file] Write code coverage report in Crap4J XML format to file --coverage-crap4j [file] Write code coverage report in Crap4J XML format to file
--coverage-html [dir] Write code coverage report in HTML format to directory --coverage-html [dir] Write code coverage report in HTML format to directory

View File

@ -68,14 +68,24 @@
✓ it adds coverage if --min exist ✓ it adds coverage if --min exist
✓ it generates coverage based on file input ✓ it generates coverage based on file input
PASS Tests\Features\Covers PASS Tests\Features\Covers\ClassCoverage
✓ it uses the correct PHPUnit attribute for class ✓ it uses the correct PHPUnit attribute for class
✓ it uses the correct PHPUnit attribute for function
✓ it guesses if the given argument is a class or function PASS Tests\Features\Covers\CoversNothing
✓ it uses the correct PHPUnit attribute for trait
✓ it uses the correct PHPUnit attribute for covers nothing ✓ it uses the correct PHPUnit attribute for covers nothing
PASS Tests\Features\Covers\ExceptionHandling
✓ it throws exception if no class nor method has been found ✓ it throws exception if no class nor method has been found
PASS Tests\Features\Covers\FunctionCoverage
✓ it uses the correct PHPUnit attribute for function
PASS Tests\Features\Covers\GuessCoverage
✓ it guesses if the given argument is a class or function
PASS Tests\Features\Covers\TraitCoverage
✓ it uses the correct PHPUnit attribute for trait
PASS Tests\Features\DatasetsTests - 1 todo PASS Tests\Features\DatasetsTests - 1 todo
✓ it throws exception if dataset does not exist ✓ it throws exception if dataset does not exist
✓ it throws exception if dataset already exist ✓ it throws exception if dataset already exist

View File

@ -1,59 +0,0 @@
<?php
use Pest\PendingCalls\TestCall;
use Pest\TestSuite;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversFunction;
use Tests\Fixtures\Covers\CoversClass1;
use Tests\Fixtures\Covers\CoversClass3;
use Tests\Fixtures\Covers\CoversTrait;
$runCounter = 0;
function testCoversFunction() {}
covers([CoversClass1::class]);
it('uses the correct PHPUnit attribute for class', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[1]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass');
expect($attributes[1]->getArguments()[0])->toBe('Tests\Fixtures\Covers\CoversClass1');
});
it('uses the correct PHPUnit attribute for function', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[3]->getName())->toBe('PHPUnit\Framework\Attributes\CoversFunction');
expect($attributes[3]->getArguments()[0])->toBe('testCoversFunction');
})->coversFunction('testCoversFunction');
it('guesses if the given argument is a class or function', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[5]->getName())->toBe(CoversClass::class);
expect($attributes[5]->getArguments()[0])->toBe(CoversClass3::class);
expect($attributes[6]->getName())->toBe(CoversFunction::class);
expect($attributes[6]->getArguments()[0])->toBe('testCoversFunction');
})->covers(CoversClass3::class, 'testCoversFunction');
it('uses the correct PHPUnit attribute for trait', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[8]->getName())->toBe('PHPUnit\Framework\Attributes\CoversTrait');
expect($attributes[8]->getArguments()[0])->toBe('Tests\Fixtures\Covers\CoversTrait');
})->coversTrait(CoversTrait::class);
it('uses the correct PHPUnit attribute for covers nothing', function () {
$attributes = (new ReflectionMethod($this, $this->name()))->getAttributes();
expect($attributes[3]->getName())->toBe('PHPUnit\Framework\Attributes\CoversNothing');
expect($attributes[3]->getArguments())->toHaveCount(0);
})->coversNothing();
it('throws exception if no class nor method has been found', function () {
$testCall = new TestCall(TestSuite::getInstance(), 'filename', 'description', fn () => 'closure');
$testCall->covers('fakeName');
})->throws(InvalidArgumentException::class, 'No class, trait or method named "fakeName" has been found.');

View File

@ -0,0 +1,13 @@
<?php
use PHPUnit\Framework\Attributes\CoversClass;
use Tests\Fixtures\Covers\CoversClass1;
covers([CoversClass1::class]);
it('uses the correct PHPUnit attribute for class', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[1]->getName())->toBe(CoversClass::class);
expect($attributes[1]->getArguments()[0])->toBe('Tests\Fixtures\Covers\CoversClass1');
});

View File

@ -0,0 +1,10 @@
<?php
use PHPUnit\Framework\Attributes\CoversNothing;
it('uses the correct PHPUnit attribute for covers nothing', function () {
$attributes = (new ReflectionMethod($this, $this->name()))->getAttributes();
expect($attributes[2]->getName())->toBe(CoversNothing::class);
expect($attributes[2]->getArguments())->toHaveCount(0);
})->coversNothing();

View File

@ -0,0 +1,10 @@
<?php
use Pest\PendingCalls\TestCall;
use Pest\TestSuite;
it('throws exception if no class nor method has been found', function () {
$testCall = new TestCall(TestSuite::getInstance(), 'filename', 'description', fn () => 'closure');
$testCall->covers('fakeName');
})->throws(InvalidArgumentException::class, 'No class, trait or method named "fakeName" has been found.');

View File

@ -0,0 +1,12 @@
<?php
use PHPUnit\Framework\Attributes\CoversFunction;
function testCoversFunction() {}
it('uses the correct PHPUnit attribute for function', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[1]->getName())->toBe(CoversFunction::class);
expect($attributes[1]->getArguments()[0])->toBe('testCoversFunction');
})->coversFunction('testCoversFunction');

View File

@ -0,0 +1,17 @@
<?php
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversFunction;
use Tests\Fixtures\Covers\CoversClass3;
function testCoversFunction2() {}
it('guesses if the given argument is a class or function', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[1]->getName())->toBe(CoversClass::class);
expect($attributes[1]->getArguments()[0])->toBe(CoversClass3::class);
expect($attributes[2]->getName())->toBe(CoversFunction::class);
expect($attributes[2]->getArguments()[0])->toBe('testCoversFunction2');
})->covers(CoversClass3::class, 'testCoversFunction2');

View File

@ -0,0 +1,11 @@
<?php
use PHPUnit\Framework\Attributes\CoversTrait as PHPUnitCoversTrait;
use Tests\Fixtures\Covers\CoversTrait;
it('uses the correct PHPUnit attribute for trait', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[1]->getName())->toBe(PHPUnitCoversTrait::class);
expect($attributes[1]->getArguments()[0])->toBe('Tests\Fixtures\Covers\CoversTrait');
})->coversTrait(CoversTrait::class);