mirror of
https://github.com/pestphp/pest.git
synced 2026-09-05 06:13:35 +02:00
fix: tia filtered
This commit is contained in:
+104
-2
@@ -7,6 +7,7 @@ namespace Pest\Plugins;
|
||||
use NunoMaduro\Collision\Adapters\Phpunit\Printers\DefaultPrinter;
|
||||
use Pest\Contracts\Plugins\AddsOutput;
|
||||
use Pest\Contracts\Plugins\HandlesArguments;
|
||||
use Pest\Contracts\Plugins\HandlesOriginalArguments;
|
||||
use Pest\Contracts\Plugins\Terminable;
|
||||
use Pest\Exceptions\NoAffectedTestsFound;
|
||||
use Pest\Exceptions\TiaRequiresRepositoryRoot;
|
||||
@@ -36,7 +37,7 @@ use Symfony\Component\Process\Process;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
final class Tia implements AddsOutput, HandlesArguments, HandlesOriginalArguments, Terminable
|
||||
{
|
||||
use HandleArguments;
|
||||
|
||||
@@ -107,6 +108,29 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
'--compact', '--ci-build-id', '--min',
|
||||
];
|
||||
|
||||
/**
|
||||
* Flags that narrow this run to a subset of the suite.
|
||||
*
|
||||
* Only user-supplied, per-run narrowing belongs here. A filter that is
|
||||
* always in force — `<groups>` in phpunit.xml, or a plugin registering a
|
||||
* test case filter from `boot()` — applies equally to the runs that build
|
||||
* the baseline, so it does not make this run narrower than the baseline
|
||||
* and must not disable baseline writes.
|
||||
*
|
||||
* `--shard` is rewritten to `--filter` before this plugin sees the
|
||||
* arguments, so it is covered here too. The `bin/pest`-only flags are
|
||||
* stripped from the handled arguments, so they are matched against the
|
||||
* original argv instead.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
private const array PARTIAL_SELECTION_FLAGS = [
|
||||
'--filter', '--exclude-filter', '--group', '--exclude-group',
|
||||
'--covers', '--uses', '--testsuite', '--exclude-testsuite', '--test-suffix',
|
||||
'--dirty', '--todo', '--todos', '--flaky', '--notes',
|
||||
'--assignee', '--issue', '--ticket', '--pr', '--pull-request',
|
||||
];
|
||||
|
||||
private bool $graphWritten = false;
|
||||
|
||||
private bool $replayRan = false;
|
||||
@@ -142,6 +166,11 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
|
||||
private bool $filteredMode = false;
|
||||
|
||||
private bool $writesSuppressed = false;
|
||||
|
||||
/** @var array<int, string> */
|
||||
private array $originalArguments = [];
|
||||
|
||||
private ?string $driftLabel = null;
|
||||
|
||||
private ?string $driftDetails = null;
|
||||
@@ -317,6 +346,14 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
return $this->cachedAssertionsByTestId[$testId] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleOriginalArguments(array $arguments): void
|
||||
{
|
||||
$this->originalArguments = $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -339,9 +376,12 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
$cliEnabled = $this->hasArgument(self::OPTION, $arguments) || self::envFlagEnabled(self::ENV_TIA);
|
||||
$alwaysEnabled = $watchPatterns->isEnabled()
|
||||
&& (! $watchPatterns->isLocally() || Environment::name() === Environment::LOCAL);
|
||||
$hasExplicitPath = $this->hasExplicitPathArgument($arguments);
|
||||
$partial = ! $isWorker && ($hasExplicitPath || $this->hasPartialSelection($arguments));
|
||||
$disabled = $disabled || $partial;
|
||||
$enabled = ! $disabled && ($cliEnabled || $alwaysEnabled);
|
||||
$this->filteredMode = ($this->hasArgument(self::FILTERED_OPTION, $arguments) || self::envFlagEnabled(self::ENV_FILTERED) || $watchPatterns->isFiltered())
|
||||
&& ! $this->hasExplicitPathArgument($arguments)
|
||||
&& ! $hasExplicitPath
|
||||
&& ! $this->coverageReportActive();
|
||||
$freshRequested = $this->hasArgument(self::FRESH_OPTION, $arguments);
|
||||
$this->forceRefetch = $this->hasArgument(self::REFETCH_OPTION, $arguments);
|
||||
@@ -355,6 +395,22 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
$arguments = $this->popArgument(self::BASELINED_OPTION, $arguments);
|
||||
|
||||
if ($disabled) {
|
||||
if ($partial) {
|
||||
// Test results are collected unconditionally, and addOutput()
|
||||
// folds them into an existing graph even when TIA took no part
|
||||
// in the run. Left alone that would prune the cached results of
|
||||
// every sibling test the selection excluded, so the writes have
|
||||
// to be suppressed explicitly rather than merely skipped.
|
||||
// `--no-tia` deliberately keeps writing: it still runs the whole
|
||||
// suite, so its results remain valid for the baseline.
|
||||
$this->writesSuppressed = true;
|
||||
|
||||
if ($cliEnabled || $freshRequested || $this->forceRefetch) {
|
||||
$this->output->writeln('');
|
||||
$this->renderChild('TIA does not apply to partial runs — running the selected tests directly.');
|
||||
}
|
||||
}
|
||||
|
||||
$this->forceRefetch = false;
|
||||
$this->filteredMode = false;
|
||||
$this->freshRebuild = false;
|
||||
@@ -392,6 +448,16 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
$this->flushWorkerReplay();
|
||||
}
|
||||
|
||||
// Only ever set for the parent — addOutput() returns early in workers,
|
||||
// whose partials are ephemeral and only reach the baseline if the
|
||||
// parent consumes them, which it no longer does.
|
||||
if ($this->writesSuppressed) {
|
||||
$this->recorder->reset();
|
||||
$this->coverageCollector->reset();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$recorder = $this->recorder;
|
||||
|
||||
if (! $this->recordingActive && ! $recorder->isActive()) {
|
||||
@@ -481,12 +547,25 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
return $exitCode;
|
||||
}
|
||||
|
||||
// `->only()` narrows the executed set exactly like `--filter` does, but
|
||||
// is only knowable once the suite has been collected — too late to turn
|
||||
// TIA off up front, so instead every write is suppressed here. Sampled
|
||||
// in addOutput() because Only's lock file is already gone by the time
|
||||
// terminate() runs (its plugin terminates first).
|
||||
if (Only::isEnabled()) {
|
||||
$this->writesSuppressed = true;
|
||||
}
|
||||
|
||||
$this->reportMissingWorkerDrivers();
|
||||
|
||||
if (Parallel::isEnabled()) {
|
||||
$this->mergeWorkerReplayPartials();
|
||||
}
|
||||
|
||||
if ($this->writesSuppressed) {
|
||||
return $exitCode;
|
||||
}
|
||||
|
||||
if ($this->replayRan) {
|
||||
$this->bumpRecordedSha();
|
||||
}
|
||||
@@ -1528,6 +1607,29 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
||||
return $coverage->coverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a selection-narrowing flag was given, either among the arguments
|
||||
* PHPUnit receives or — for the flags `bin/pest` consumes itself — among
|
||||
* the original argv. Explicit path arguments and `->only()` are detected
|
||||
* separately.
|
||||
*
|
||||
* @param array<int, string> $arguments
|
||||
*/
|
||||
private function hasPartialSelection(array $arguments): bool
|
||||
{
|
||||
foreach (self::PARTIAL_SELECTION_FLAGS as $flag) {
|
||||
if ($this->hasArgument($flag, $arguments)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->hasArgument($flag, $this->originalArguments)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $arguments
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user