Skip to content

feat: install ParaTest in the image - #13

Merged
Spomky merged 1 commit into
mainfrom
feat/paratest
Oct 9, 2026
Merged

Spomky merged 1 commit into
mainfrom
feat/paratest

Conversation

@Spomky

@Spomky Spomky commented Oct 9, 2026

Copy link
Copy Markdown
Member

Closes #12.

/tools/paratest, out of the Composer tree the image already keeps beside PHPUnit. A require line and a symlink, because the hard part was already here: vendor-bin/phpunit/vendor holds phpunit/phpunit already, pulled by the extensions that tree exists for, at the version of the PHAR.

$ docker run --rm ghcr.io/spomky-labs/phpqa:8.5 /tools/.composer/vendor-bin/phpunit/vendor/bin/phpunit --version
PHPUnit 13.3.5
$ docker run --rm ghcr.io/spomky-labs/phpqa:8.5 /tools/phpunit --version
PHPUnit 13.3.5

The two agree by construction, and the comment added beside the require block says to leave them to it: the PHAR URL serves the newest 13.x at build time and Composer resolves the newest 13.x for that tree, so pinning either one is what would make them disagree.

Why paratest and not sharding across jobs: it merges the coverage of its worker processes itself. PHPUnit does not merge XML coverage reports from several runs, so a sharded suite leaves each shard with a partial report and nothing to join them with, which matters for anything that reads that coverage afterwards, mutation testing first of all.

Resolved and run before the build, in the 8.5 image, on the tree's own require block with paratest added: paratest v7.26.0 with phpunit/phpunit 13.4.1 alongside every existing require, 56 installs and no conflict, and both binaries answering --version. /tools/phpunit is untouched and its selection loop unchanged.

Docs: the tool table of the README and the two lists that enumerate what the image carries.

@Spomky

Spomky commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

Built locally for PHP 8.5 (tests/test-local-build.sh 8.5), green, and the image checked for what this adds:

/tools/paratest -> /tools/.composer/vendor-bin/phpunit/vendor/bin/paratest
$ paratest --version                      ParaTest v7.26.0
$ composer exec -- paratest --version     ParaTest v7.26.0
$ /tools/.composer/vendor-bin/phpunit/vendor/bin/phpunit --version   PHPUnit 13.4.1
$ /tools/phpunit --version                                          PHPUnit 13.4.1

The last two lines are the thing worth reading: a build from today puts both PHPUnit at 13.4.1 on its own, the PHAR because its URL serves the newest 13.x and the Composer tree because it resolves the newest 13.x. They were at 13.3.5 together in the published 8.5 image. That is the agreement the comment asks not to break by pinning either one.

paratest runs the test files in parallel processes and merges the coverage of its workers itself,
which is what sharding a suite across CI jobs cannot do: PHPUnit does not merge XML coverage
reports from several runs, so each shard is left with a partial one and nothing to join them with.

It costs a require line and a symlink, because the hard part was already here. paratest is a
Composer package and needs phpunit/phpunit in its own vendor tree, which is usually what makes it
awkward beside a PHAR; the vendor-bin/phpunit tree already holds one, pulled by the extensions it
exists for.

"^7" rather than a precise version, because the PHP of the build decides: paratest 7.26 asks for PHP
8.4 and PHPUnit 13.4, 7.20 for PHP 8.3 and PHPUnit 12.5, 7.8 for PHP 8.2 and PHPUnit 11.5. Composer
resolves the newest that runs there, and the PHPUnit it brings is the newest that runs there too,
the same bound the PHAR loop uses for /tools/phpunit, so the two land on the same version without
either being pinned.

Resolved in the image of every version the build targets, on the tree's own require block: 8.2 gives
paratest 7.8.6 with PHPUnit 11.5.57, 8.3 gives 7.20.0 with 12.5.38, 8.5 gives 7.26.0 with 13.4.1,
none of them in conflict with what the tree already requires. A build for 8.5 then answers
"ParaTest v7.26.0" on the PATH and through "composer exec", with both PHPUnit at 13.4.1.
@Spomky

Spomky commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

The 8.2 and 8.3 builds were right to fail: ^7.26 pins a paratest whose own floor is PHP 8.4, and this image builds from 8.2. I had resolved it in the 8.5 image only, and built locally for 8.5 only, so the matrix is what caught it.

Fixed by letting the PHP of the build decide, ^7, and resolved in each image on the tree's own require block:

PHP paratest phpunit/phpunit
8.2 v7.8.6 11.5.57
8.3 v7.20.0 12.5.38
8.5 v7.26.0 13.4.1

None of them conflicts with what the tree already requires. That is also the agreement the comment now claims, in the right terms: the PHPUnit Composer can resolve for a given PHP and the newest PHAR that runs on it are bounded by the same thing, so they land together without either being pinned. PHPUnit 13.4.1 requires PHP >= 8.4.1, which is why 8.3 gets 12 and 8.2 gets 11, on both sides.

Noticed while checking, and not this pull request's business: the published 8.2 and 8.3 tags are older builds than 8.4 and 8.5. They still carry phpunit-8 and phpunit-9, which this Dockerfile no longer installs, and they have no /tools/phpunit at all, so nothing resolves phpunit on their PATH. A rebuild gives them the selection loop and the symlink.

@Spomky
Spomky merged commit e2948a0 into main Oct 9, 2026
17 checks passed
@Spomky
Spomky deleted the feat/paratest branch October 9, 2026 11:34
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.

paratest, for the suites long enough to want it

1 participant