mirror of
https://github.com/pestphp/pest.git
synced 2026-09-05 14:23:34 +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 NunoMaduro\Collision\Adapters\Phpunit\Printers\DefaultPrinter;
|
||||||
use Pest\Contracts\Plugins\AddsOutput;
|
use Pest\Contracts\Plugins\AddsOutput;
|
||||||
use Pest\Contracts\Plugins\HandlesArguments;
|
use Pest\Contracts\Plugins\HandlesArguments;
|
||||||
|
use Pest\Contracts\Plugins\HandlesOriginalArguments;
|
||||||
use Pest\Contracts\Plugins\Terminable;
|
use Pest\Contracts\Plugins\Terminable;
|
||||||
use Pest\Exceptions\NoAffectedTestsFound;
|
use Pest\Exceptions\NoAffectedTestsFound;
|
||||||
use Pest\Exceptions\TiaRequiresRepositoryRoot;
|
use Pest\Exceptions\TiaRequiresRepositoryRoot;
|
||||||
@@ -36,7 +37,7 @@ use Symfony\Component\Process\Process;
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
final class Tia implements AddsOutput, HandlesArguments, Terminable
|
final class Tia implements AddsOutput, HandlesArguments, HandlesOriginalArguments, Terminable
|
||||||
{
|
{
|
||||||
use HandleArguments;
|
use HandleArguments;
|
||||||
|
|
||||||
@@ -107,6 +108,29 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
|||||||
'--compact', '--ci-build-id', '--min',
|
'--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 $graphWritten = false;
|
||||||
|
|
||||||
private bool $replayRan = false;
|
private bool $replayRan = false;
|
||||||
@@ -142,6 +166,11 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
|||||||
|
|
||||||
private bool $filteredMode = false;
|
private bool $filteredMode = false;
|
||||||
|
|
||||||
|
private bool $writesSuppressed = false;
|
||||||
|
|
||||||
|
/** @var array<int, string> */
|
||||||
|
private array $originalArguments = [];
|
||||||
|
|
||||||
private ?string $driftLabel = null;
|
private ?string $driftLabel = null;
|
||||||
|
|
||||||
private ?string $driftDetails = null;
|
private ?string $driftDetails = null;
|
||||||
@@ -317,6 +346,14 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
|||||||
return $this->cachedAssertionsByTestId[$testId] ?? 0;
|
return $this->cachedAssertionsByTestId[$testId] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function handleOriginalArguments(array $arguments): void
|
||||||
|
{
|
||||||
|
$this->originalArguments = $arguments;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@@ -339,9 +376,12 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
|||||||
$cliEnabled = $this->hasArgument(self::OPTION, $arguments) || self::envFlagEnabled(self::ENV_TIA);
|
$cliEnabled = $this->hasArgument(self::OPTION, $arguments) || self::envFlagEnabled(self::ENV_TIA);
|
||||||
$alwaysEnabled = $watchPatterns->isEnabled()
|
$alwaysEnabled = $watchPatterns->isEnabled()
|
||||||
&& (! $watchPatterns->isLocally() || Environment::name() === Environment::LOCAL);
|
&& (! $watchPatterns->isLocally() || Environment::name() === Environment::LOCAL);
|
||||||
|
$hasExplicitPath = $this->hasExplicitPathArgument($arguments);
|
||||||
|
$partial = ! $isWorker && ($hasExplicitPath || $this->hasPartialSelection($arguments));
|
||||||
|
$disabled = $disabled || $partial;
|
||||||
$enabled = ! $disabled && ($cliEnabled || $alwaysEnabled);
|
$enabled = ! $disabled && ($cliEnabled || $alwaysEnabled);
|
||||||
$this->filteredMode = ($this->hasArgument(self::FILTERED_OPTION, $arguments) || self::envFlagEnabled(self::ENV_FILTERED) || $watchPatterns->isFiltered())
|
$this->filteredMode = ($this->hasArgument(self::FILTERED_OPTION, $arguments) || self::envFlagEnabled(self::ENV_FILTERED) || $watchPatterns->isFiltered())
|
||||||
&& ! $this->hasExplicitPathArgument($arguments)
|
&& ! $hasExplicitPath
|
||||||
&& ! $this->coverageReportActive();
|
&& ! $this->coverageReportActive();
|
||||||
$freshRequested = $this->hasArgument(self::FRESH_OPTION, $arguments);
|
$freshRequested = $this->hasArgument(self::FRESH_OPTION, $arguments);
|
||||||
$this->forceRefetch = $this->hasArgument(self::REFETCH_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);
|
$arguments = $this->popArgument(self::BASELINED_OPTION, $arguments);
|
||||||
|
|
||||||
if ($disabled) {
|
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->forceRefetch = false;
|
||||||
$this->filteredMode = false;
|
$this->filteredMode = false;
|
||||||
$this->freshRebuild = false;
|
$this->freshRebuild = false;
|
||||||
@@ -392,6 +448,16 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
|||||||
$this->flushWorkerReplay();
|
$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;
|
$recorder = $this->recorder;
|
||||||
|
|
||||||
if (! $this->recordingActive && ! $recorder->isActive()) {
|
if (! $this->recordingActive && ! $recorder->isActive()) {
|
||||||
@@ -481,12 +547,25 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
|||||||
return $exitCode;
|
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();
|
$this->reportMissingWorkerDrivers();
|
||||||
|
|
||||||
if (Parallel::isEnabled()) {
|
if (Parallel::isEnabled()) {
|
||||||
$this->mergeWorkerReplayPartials();
|
$this->mergeWorkerReplayPartials();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->writesSuppressed) {
|
||||||
|
return $exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->replayRan) {
|
if ($this->replayRan) {
|
||||||
$this->bumpRecordedSha();
|
$this->bumpRecordedSha();
|
||||||
}
|
}
|
||||||
@@ -1528,6 +1607,29 @@ final class Tia implements AddsOutput, HandlesArguments, Terminable
|
|||||||
return $coverage->coverage;
|
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
|
* @param array<int, string> $arguments
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user