PHPUnit
testflake/phpunit is a Composer package. It needs no Node, npm, or JavaScript
toolchain — it talks to the TestFlake API directly over HTTP.
There is also nothing to register in phpunit.xml. PHPUnit already exposes
everything TestFlake needs as command-line flags, so unlike the Playwright
integration there is no reporter or extension to add.
Requirements
Section titled “Requirements”PHP 7.2 or later, with the curl, dom and json extensions.
PHPUnit itself is not a dependency. The client wraps whichever phpunit you
already run, so it stays out of your version constraints.
ext-zlib is optional but worth having: with it, result payloads are gzipped
before upload. The client detects it at runtime and sends them uncompressed
otherwise.
-
Install the package
Terminal window composer require --dev testflake/phpunit -
Wrap the command you already run
Terminal window TESTFLAKE_KEY=your-key TESTFLAKE_HOST=https://app.testflake.com \vendor/bin/testflake vendor/bin/phpunitYour own flags pass straight through, and the suite is enumerated with them applied —
--testsuite,--groupand--filterall behave as usual:Terminal window vendor/bin/testflake vendor/bin/phpunit --testsuite=integration
Sharding across CI machines
Section titled “Sharding across CI machines”--shard=N/M is read by the wrapper and never reaches PHPUnit, which has no
such flag of its own. It goes before the command being wrapped:
TESTFLAKE_KEY=your-key vendor/bin/testflake --shard=2/8 vendor/bin/phpunitOn GitLab CI you can leave it out entirely — the wrapper reads CI_NODE_INDEX
and CI_NODE_TOTAL:
phpunit: parallel: 8 script: - vendor/bin/testflake vendor/bin/phpunitThe first run has no timing data and falls back to an alphabetical split. From the second run on, shards are balanced by recorded duration.
Setting it up in CI
Section titled “Setting it up in CI”Every shard of one run has to agree on a run id, or each becomes its own pipeline holding the whole suite. On GitLab that is automatic; elsewhere you pass it.
Complete pipelines for GitLab CI, GitHub Actions, CircleCI, Jenkins and Travis are in Continuous integration.
Code coverage
Section titled “Code coverage”Ask PHPUnit for a Cobertura report and the client uploads it, so each run has a Coverage tab listing every file with the share of its executable lines that ran:
vendor/bin/testflake vendor/bin/phpunit --coverage-cobertura=coverage.xmlA <cobertura outputFile="..."/> entry in your phpunit.xml works just as
well — the client reads either. Coverage is optional throughout: a run without
it is an ordinary run, and a failed upload is a warning and nothing more.
Every shard uploads what its own tests loaded and the server adds them together, so the figures are the whole run’s rather than one machine’s.
Showing the source
Section titled “Showing the source”By default TestFlake stores the numbers and not the files. Add
--include-source-files and the client uploads the source of each covered file
too, which is what lets the dashboard show it annotated line by line:
vendor/bin/testflake --include-source-files vendor/bin/phpunit \ --coverage-cobertura=coverage.xmlFiles are stored per project and keyed by their contents, so a file is uploaded once and never again until it changes. The first run of a suite sends the checkout; every run after it sends only what the commit touched.
Three things are never sent: files over 1 MiB, files that are not valid UTF-8, and anything the client cannot read. Nothing else about the flag is configurable — leave it off and no source ever leaves your CI machine.
How it drives PHPUnit
Section titled “How it drives PHPUnit”The client uses three flags PHPUnit already has, which is why there is nothing to install into your test runner:
| Flag | Used for |
|---|---|
--list-tests-xml |
Enumerating the suite, with your own flags applied. |
--test-id-filter-file |
Selecting exactly this shard’s tests. |
--log-junit |
Reading back what each test did and how long it took. |
--test-id-filter-file is only in recent PHPUnit releases. The client checks
for it and falls back to a --filter regex on older versions — no configuration
needed either way.
The wrapper’s own, consumed before the PHPUnit command it forwards:
| Flag | Default | Purpose |
|---|---|---|
--shard=N/M |
detected on GitLab | Which shard this machine is. |
--include-source-files |
off | Uploads the source of each covered file. |
Environment variables
Section titled “Environment variables”| Variable | Default | Purpose |
|---|---|---|
TESTFLAKE_KEY |
— | Attributes runs to a project. Treat as a credential. |
TESTFLAKE_HOST |
— | API base URL. |
TESTFLAKE_RUN_ID |
detected on GitLab and GitHub | Ties the shards of one run together. |
TESTFLAKE_BRANCH |
detected on GitLab and GitHub | Branch the run belongs to. |