Skip to content

fix(shard): make time-based sharding namespace-agnostic and forward --test-directory#1677

Open
norbybaru wants to merge 11 commits intopestphp:4.xfrom
norbybaru:time-base-shard-namespace-agnostic
Open

fix(shard): make time-based sharding namespace-agnostic and forward --test-directory#1677
norbybaru wants to merge 11 commits intopestphp:4.xfrom
norbybaru:time-base-shard-namespace-agnostic

Conversation

@norbybaru
Copy link
Copy Markdown

@norbybaru norbybaru commented Apr 16, 2026

What:

  • Bug Fix
  • New Feature

Description:

Time-based sharding (#1671) silently fails for projects whose tests do not live under the Tests\ namespace.

Root cause 1 — hardcoded namespace in regex (Shard.php:196):

The allTests() method parses --list-tests output using a regex that only captures FQCNs starting with Tests\:

preg_match_all('/ - (?:P\\\\)?(Tests\\\\[^:]+)::/', $output, $matches);

For any other namespace (App\Tests\, Acme\Suite\, etc.), allTests() returns [], causing:

  • --update-shards writes an empty shards.json
  • Time-balanced partitioning silently falls back to naive array_chunk
  • Feature appears to work but provides no benefit

Root cause 2 — --test-directory not forwarded to subprocess:

bin/pest strips --test-directory from argv before the plugin pipeline runs (lines 42-50). Shard::allTests() spawns a subprocess with those stripped arguments, so the subprocess always
defaults to the tests/ directory — even when users configure a custom test path.

Solution

1. Namespace-agnostic regex

Replaced Tests\\-hardcoded regex with a pattern matching any valid PHP FQCN:

preg_match_all('/ - (?:P\\\\)?([A-Za-z_]\w*(?:\\\\[A-Za-z_]\w*)*)::/', $output, $matches);

Matches sequences of valid PHP identifiers joined by \. Stricter than a catch-all [^:]+ — rejects whitespace, punctuation, and malformed lines.

2. Forward --test-directory to the subprocess

Read the already-resolved test path from the TestSuite singleton and inject it into the subprocess command:

$command = $this->buildListTestsCommand($arguments, TestSuite::getInstance()->testPath);

@norbybaru norbybaru marked this pull request as ready for review April 16, 2026 10:10
The removeParallelArguments method was not filtering --processes flags, causing the list-tests subprocess to fail when parallel execution was enabled. This prevented time-based sharding from working correctly with the --parallel option.

Now both --parallel/-p and --processes arguments are removed from the command used to enumerate tests, ensuring the subprocess runs successfully.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant