[Bug]: StateGenerator TypeError with AfterLastTestMethodErrored in parallel mode
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 11.7k
- Forks
- 538
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 8
Description
Pest Version
v4.3.2
PHP Version
8.4
Operation System
macOS / Linux
Description
When running tests in parallel mode (--parallel), if any test triggers an AfterLastTestMethodErrored event (e.g., errors during teardown/cleanup), Pest crashes with a TypeError:
TypeError: NunoMaduro\Collision\Adapters\Phpunit\TestResult::fromBeforeFirstTestMethodErrored():
Argument #1 ($event) must be of type PHPUnit\Event\Test\BeforeFirstTestMethodErrored,
PHPUnit\Event\Test\AfterLastTestMethodErrored given,
called in vendor/pestphp/pest/src/Support/StateGenerator.php on line 34
Root Cause
In src/Support/StateGenerator.php, the code assumes all non-Errored events from testErroredEvents() are BeforeFirstTestMethodErrored:
foreach ($testResult->testErroredEvents() as $testResultEvent) {
if ($testResultEvent instanceof Errored) {
// ... handle Errored
} else {
// @phpstan-ignore-next-line
$state->add(TestResult::fromBeforeFirstTestMethodErrored($testResultEvent));
}
}
However, testErroredEvents() can also return AfterLastTestMethodErrored events, which are then incorrectly passed to fromBeforeFirstTestMethodErrored().
Suggested Fix
Add an explicit instanceof check for BeforeFirstTestMethodErrored:
use PHPUnit\Event\Test\BeforeFirstTestMethodErrored;
foreach ($testResult->testErroredEvents() as $testResultEvent) {
if ($testResultEvent instanceof Errored) {
$state->add(TestResult::fromPestParallelTestCase(
$testResultEvent->test(),
TestResult::FAIL,
$testResultEvent->throwable()
));
} elseif ($testResultEvent instanceof BeforeFirstTestMethodErrored) {
$state->add(TestResult::fromBeforeFirstTestMethodErrored($testResultEvent));
}
// AfterLastTestMethodErrored events can be skipped or handled separately
}
Steps to Reproduce
- Create a test that causes an error during teardown (e.g., database constraint violation in
afterEach) - Run tests with
--parallelflag - Observe the TypeError crash
Workaround
We've created a composer patch that fixes this issue:
--- a/src/Support/StateGenerator.php
+++ b/src/Support/StateGenerator.php
@@ -10,6 +10,7 @@
use PHPUnit\Event\Code\TestDoxBuilder;
use PHPUnit\Event\Code\TestMethod;
use PHPUnit\Event\Code\ThrowableBuilder;
+use PHPUnit\Event\Test\BeforeFirstTestMethodErrored;
use PHPUnit\Event\Test\Errored;
use PHPUnit\Event\TestData\TestDataCollection;
use PHPUnit\Framework\SkippedWithMessageException;
@@ -29,10 +30,11 @@
TestResult::FAIL,
$testResultEvent->throwable()
));
- } else {
- // @phpstan-ignore-next-line
+ } elseif ($testResultEvent instanceof BeforeFirstTestMethodErrored) {
$state->add(TestResult::fromBeforeFirstTestMethodErrored($testResultEvent));
}
+ // AfterLastTestMethodErrored events are intentionally skipped
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/Support/StateGenerator.php and inspect the loop over testErroredEvents() and its event type handling. Reproduce the failure with --parallel and a teardown error, then verify that BeforeFirstTestMethodErrored events still produce results while AfterLastTestMethodErrored events no longer cause a TypeError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100