PHPackages                             brianium/paratest - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. brianium/paratest

ActiveLibrary[Testing &amp; Quality](/categories/testing)

brianium/paratest
=================

Parallel testing for PHP

v7.19.2(2mo ago)2.5k118.8M—4.7%253[3 issues](https://github.com/paratestphp/paratest/issues)[3 PRs](https://github.com/paratestphp/paratest/pulls)20MITPHPPHP ~8.3.0 || ~8.4.0 || ~8.5.0CI passing

Since Nov 2Pushed today35 watchersCompare

[ Source](https://github.com/paratestphp/paratest)[ Packagist](https://packagist.org/packages/brianium/paratest)[ Docs](https://github.com/paratestphp/paratest)[ GitHub Sponsors](https://github.com/sponsors/Slamdunk)[ Fund](https://paypal.me/filippotessarotto)[ RSS](/packages/brianium-paratest/feed)WikiDiscussions 7.x Synced 1mo ago

READMEChangelog (10)Dependencies (30)Versions (183)Used By (20)

ParaTest
========

[](#paratest)

[![Latest Stable Version](https://camo.githubusercontent.com/4f5bc3752c9b5053f88d5d15a360c21e3d0cac381e94e7b9b0bba10ff3077fbc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f627269616e69756d2f70617261746573742e737667)](https://packagist.org/packages/brianium/paratest)[![Downloads](https://camo.githubusercontent.com/ecd15e3ef6c3a610da79d47d285250d23d9a085d2af330bf49ffbc9c89e66a00/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f627269616e69756d2f70617261746573742e737667)](https://packagist.org/packages/brianium/paratest)[![Integrate](https://github.com/paratestphp/paratest/actions/workflows/ci.yml/badge.svg?branch=7.x)](https://github.com/paratestphp/paratest/actions)[![Infection MSI](https://camo.githubusercontent.com/e65954b992ea8f55748f155225cb4f10ad3694c82ace00d99a09518dccf938a1/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742675726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d25324670617261746573747068702532467061726174657374253246372e78)](https://dashboard.stryker-mutator.io/reports/github.com/paratestphp/paratest/7.x)

The objective of ParaTest is to support parallel testing in PHPUnit. Provided you have well-written PHPUnit tests, you can drop `paratest` in your project and start using it with no additional bootstrap or configurations!

Benefits:

- Zero configuration. After the installation, run with `vendor/bin/paratest` to parallelize by TestCase or `vendor/bin/paratest --functional` to parallelize by Test. That's it!
- Code Coverage report combining. Run your tests in N parallel processes and all the code coverage output will be combined into one report.

Installation
============

[](#installation)

To install with composer run the following command:

```
composer require --dev brianium/paratest

```

Versions
========

[](#versions)

Only the latest version of PHPUnit is supported, and thus only the latest version of ParaTest is actively maintained.

This is because of the following reasons:

1. To reduce bugs, code duplication and incompatibilities with PHPUnit, from version 5 ParaTest heavily relies on PHPUnit `@internal` classes
2. The fast pace both PHP and PHPUnit have taken recently adds too much maintenance burden, which we can only afford for the latest versions to stay up-to-date

Usage
=====

[](#usage)

After installation, the binary can be found at `vendor/bin/paratest`. Run it with `--help` option to see a complete list of the available options.

Test token
----------

[](#test-token)

The `TEST_TOKEN` environment variable is guaranteed to have a value that is different from every other currently running test. This is useful to e.g. use a different database for each test:

```
if (getenv('TEST_TOKEN') !== false) {  // Using ParaTest
    $dbname = 'testdb_' . getenv('TEST_TOKEN');
} else {
    $dbname = 'testdb';
}
```

A `UNIQUE_TEST_TOKEN` environment variable is also available and guaranteed to have a value that is unique both per run and per process.

Code coverage
-------------

[](#code-coverage)

The cache is always warmed up by ParaTest before executing the test suite.

### PCOV

[](#pcov)

If you have installed `pcov` but need to enable it only while running tests, you have to pass thru the needed PHP binary option:

```
php -d pcov.enabled=1 vendor/bin/paratest --passthru-php="'-d' 'pcov.enabled=1'"

```

### xDebug

[](#xdebug)

If you have `xDebug` installed, activating it by the environment variable is enough to have it running even in the subprocesses:

```
XDEBUG_MODE=coverage vendor/bin/paratest

```

Initial setup for all tests
---------------------------

[](#initial-setup-for-all-tests)

Because ParaTest runs multiple processes in parallel, each with their own instance of the PHP interpreter, techniques used to perform an initialization step exactly once for each test work different from PHPUnit. The following pattern will not work as expected - run the initialization exactly once - and instead run the initialization once per process:

```
private static bool $initialized = false;

public function setUp(): void
{
    if (! self::$initialized) {
         self::initialize();
         self::$initialized = true;
    }
}
```

This is because static variables persist during the execution of a single process. In parallel testing each process has a separate instance of `$initialized`. You can use the following pattern to ensure your initialization runs exactly once for the entire test invocation:

```
static bool $initialized = false;

public function setUp(): void
{
    if (! self::$initialized) {
        // We utilize the filesystem as shared mutable state to coordinate between processes
        touch('/tmp/test-initialization-lock-file');
        $lockFile = fopen('/tmp/test-initialization-lock-file', 'r');

        // Attempt to get an exclusive lock - first process wins
        if (flock($lockFile, LOCK_EX | LOCK_NB)) {
            // Since we are the single process that has an exclusive lock, we run the initialization
            self::initialize();
        } else {
            // If no exclusive lock is available, block until the first process is done with initialization
            flock($lockFile, LOCK_SH);
        }

        self::$initialized = true;
    }
}
```

Troubleshooting
---------------

[](#troubleshooting)

If you run into problems with `paratest`, try to get more information about the issue by enabling debug output via `--verbose`.

When a sub-process fails, the originating command is given in the output and can then be copy-pasted in the terminal to be run and debugged. All internal commands run with `--printer [...]\NullPhpunitPrinter` which silence the original PHPUnit output: during a debugging run remove that option to restore the output and see what PHPUnit is doing.

Caveats
-------

[](#caveats)

1. Constants, static methods, static variables and everything exposed by test classes consumed by other test classes (including Reflection) are not supported. This is due to a limitation of the current implementation of `WrapperRunner`and how PHPUnit searches for classes. The fix is to put shared code into classes which are not tests *themselves*.

Integration with PHPStorm
-------------------------

[](#integration-with-phpstorm)

ParaTest provides a dedicated binary to work with PHPStorm; follow these steps to have ParaTest working within it:

1. Be sure you have PHPUnit already configured in PHPStorm: [https://www.jetbrains.com/help/phpstorm/using-phpunit-framework.html#php\_test\_frameworks\_phpunit\_integrate](https://www.jetbrains.com/help/phpstorm/using-phpunit-framework.html#php_test_frameworks_phpunit_integrate)
2. Go to `Run` -&gt; `Edit configurations...`
3. Select `Add new Configuration`, select the `PHPUnit` type and name it `ParaTest`
4. In the `Command Line` -&gt; `Interpreter options` add `./vendor/bin/paratest_for_phpstorm`
5. Any additional ParaTest options you want to pass to ParaTest should go within the `Test runner` -&gt; `Test runner options` section

You should now have a `ParaTest` run within your configurations list. It should natively work with the `Rerun failed tests` and `Toggle auto-test` buttons of the `Run` overlay.

### Run with Coverage

[](#run-with-coverage)

Coverage with one of the [available coverage engines](#code-coverage) must already be [configured in PHPStorm](https://www.jetbrains.com/help/phpstorm/code-coverage.html)and working when running tests sequentially in order for the helper binary to correctly handle code coverage

For Contributors: testing ParaTest itself
=========================================

[](#for-contributors-testing-paratest-itself)

Before creating a Pull Request be sure to run all the necessary checks with `make` command.

###  Health Score

87

—

ExcellentBetter than 100% of packages

Maintenance94

Actively maintained with recent releases

Popularity81

Widely adopted with strong download metrics

Community60

Healthy contributor diversity

Maturity100

Battle-tested with a long release history

 Bus Factor3

3 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~27 days

Recently: every ~11 days

Total

178

Last Release

54d ago

Major Versions

v6.9.1 → v7.1.12023-03-13

v6.10.0 → v7.1.52023-06-13

v6.10.1 → v7.2.82023-10-04

v6.11.0 → v7.3.12023-10-31

v6.11.1 → v7.4.42024-05-03

PHP version history (16 changes)v0.1.0PHP &gt;=5.3.0

0.13.0PHP &gt;=5.4.0

0.14.0PHP &gt;=5.5.11

1.0.0PHP &gt;=7.0

2.0PHP &gt;=7.1

3.0.0PHP ^7.2

3.1.0PHP ^7.1

4.1.0PHP ^7.3

v6.0.0PHP ^7.3 || ^8.0

v7.0.0PHP ~8.1.0 || ~8.2.0

v7.2.0PHP ~8.1.0 || ~8.2.0 || ~8.3.0

v7.4.0PHP ~8.2.0 || ~8.3.0

v7.6.0PHP ~8.2.0 || ~8.3.0 || ~8.4.0

v7.9.0PHP ~8.3.0 || ~8.4.0

v7.12.0PHP ~8.3.0 || ~8.4.0 || ~8.5.0

v7.8.5PHP ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/5cd2707d7bc5233dac66a38db2af69d347c4c815ffb6ddbd9be27cd1eda37d14?d=identicon)[Jean85](/maintainers/Jean85)

![](https://avatars.githubusercontent.com/u/50348?v=4)[Sahn Lam](/maintainers/Slam)[@slam](https://github.com/slam)

![](https://www.gravatar.com/avatar/55f8651ac4bc64c823cbd59c45c9b7cbacf417e7e543da2159a48d3a99b0448c?d=identicon)[andreasschroth](/maintainers/andreasschroth)

---

Top Contributors

[![renovate[bot]](https://avatars.githubusercontent.com/in/2740?v=4)](https://github.com/renovate[bot] "renovate[bot] (261 commits)")[![Slamdunk](https://avatars.githubusercontent.com/u/152236?v=4)](https://github.com/Slamdunk "Slamdunk (260 commits)")[![brianium](https://avatars.githubusercontent.com/u/636651?v=4)](https://github.com/brianium "brianium (233 commits)")[![julianseeger](https://avatars.githubusercontent.com/u/3258762?v=4)](https://github.com/julianseeger "julianseeger (166 commits)")[![andreasschroth](https://avatars.githubusercontent.com/u/13320551?v=4)](https://github.com/andreasschroth "andreasschroth (107 commits)")[![giorgiosironi](https://avatars.githubusercontent.com/u/160299?v=4)](https://github.com/giorgiosironi "giorgiosironi (65 commits)")[![chbiel](https://avatars.githubusercontent.com/u/1297702?v=4)](https://github.com/chbiel "chbiel (21 commits)")[![Jean85](https://avatars.githubusercontent.com/u/6729988?v=4)](https://github.com/Jean85 "Jean85 (15 commits)")[![michaelbutler](https://avatars.githubusercontent.com/u/521702?v=4)](https://github.com/michaelbutler "michaelbutler (15 commits)")[![ebi](https://avatars.githubusercontent.com/u/11541?v=4)](https://github.com/ebi "ebi (15 commits)")[![TysonAndre-tmg](https://avatars.githubusercontent.com/u/110992834?v=4)](https://github.com/TysonAndre-tmg "TysonAndre-tmg (14 commits)")[![dbaltas](https://avatars.githubusercontent.com/u/442804?v=4)](https://github.com/dbaltas "dbaltas (14 commits)")[![TysonAndre](https://avatars.githubusercontent.com/u/1904430?v=4)](https://github.com/TysonAndre "TysonAndre (14 commits)")[![luispabon](https://avatars.githubusercontent.com/u/6388823?v=4)](https://github.com/luispabon "luispabon (10 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (9 commits)")[![jdufresne](https://avatars.githubusercontent.com/u/347634?v=4)](https://github.com/jdufresne "jdufresne (9 commits)")[![lox](https://avatars.githubusercontent.com/u/15758?v=4)](https://github.com/lox "lox (9 commits)")[![michaelgv](https://avatars.githubusercontent.com/u/32310492?v=4)](https://github.com/michaelgv "michaelgv (9 commits)")[![sormy](https://avatars.githubusercontent.com/u/7675583?v=4)](https://github.com/sormy "sormy (7 commits)")[![maxnk](https://avatars.githubusercontent.com/u/2979256?v=4)](https://github.com/maxnk "maxnk (7 commits)")

---

Tags

testingphpunitconcurrentparallel

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/brianium-paratest/health.svg)

```
[![Health](https://phpackages.com/badges/brianium-paratest/health.svg)](https://phpackages.com/packages/brianium-paratest)
```

###  Alternatives

[phpunit/phpunit

The PHP Unit Testing framework.

20.0k910.7M134.8k](/packages/phpunit-phpunit)[infection/infection

Infection is a Mutation Testing framework for PHP. The mutation adequacy score can be used to measure the effectiveness of a test set in terms of its ability to detect faults.

2.2k26.2M1.8k](/packages/infection-infection)[facile-it/paraunit

paraunit

146721.6k11](/packages/facile-it-paraunit)[lmc/steward

Steward - makes Selenium WebDriver + PHPUnit testing easy and robust

222163.1k1](/packages/lmc-steward)[robiningelbrecht/phpunit-coverage-tools

PHPUnit coverage tools

1783.0k34](/packages/robiningelbrecht-phpunit-coverage-tools)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
