PHPackages                             cornermonkey/pest-plugin-rerun - 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. cornermonkey/pest-plugin-rerun

ActiveLibrary

cornermonkey/pest-plugin-rerun
==============================

Adds --only-failed and --rerun-failed flags to Pest.

0.1.1(1mo ago)03MITPHPPHP ^8.3CI passing

Since Jul 8Pushed 1mo agoCompare

[ Source](https://github.com/CornerMonkey/pest-plugin-rerun)[ Packagist](https://packagist.org/packages/cornermonkey/pest-plugin-rerun)[ Docs](https://github.com/CornerMonkey/pest-plugin-rerun)[ RSS](/packages/cornermonkey-pest-plugin-rerun/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (4)Versions (3)Used By (0)

Pest Plugin: Only Failed / Rerun Failed
=======================================

[](#pest-plugin-only-failed--rerun-failed)

[![CI](https://github.com/tim-zitcha/pest-plugin-rerun/actions/workflows/ci.yml/badge.svg)](https://github.com/tim-zitcha/pest-plugin-rerun/actions/workflows/ci.yml)

Adds two independent CLI flags to [Pest](https://pestphp.com) v4:

- `--only-failed` — skip straight to running only the tests that failed on the previous run, instead of the full suite.
- `--rerun-failed` — run the full suite as normal, and if anything failed, automatically rerun just those failed tests afterward, in the same invocation, under a distinct "Rerun of failed tests" section — so you can see at a glance whether a failure was consistent or flaky.

No `phpunit.xml` changes are required in consuming projects.

Install
-------

[](#install)

```
composer require --dev tim-zitcha/pest-plugin-rerun
```

Composer's plugin allow-list may prompt you to trust `pestphp/pest-plugin`(the mechanism Pest itself uses to discover plugins from `composer.json`'s `extra.pest.plugins`); this package is registered the same way.

Usage
-----

[](#usage)

```
# Run everything, as normal, then automatically rerun anything that failed.
vendor/bin/pest --rerun-failed

# Skip straight to re-running only what failed last time.
vendor/bin/pest --only-failed

# Combine them: re-run only last run's failures, and if any of those still
# fail, rerun just those again in the same invocation.
vendor/bin/pest --only-failed --rerun-failed
```

Every run (with or without either flag) overwrites `.pest-only-failed.json`in the project root with the current run's failures — a plain overwrite, not a merge, so a test that's since been fixed drops off the list automatically. Add this file to your `.gitignore`.

The flake-exit-code decision
----------------------------

[](#the-flake-exit-code-decision)

If `--rerun-failed` reruns a test and it **passes**, the overall run still **exits non-zero**. The initial failure counts. The rerun section is purely informational — it tells you whether a failure was consistent (fails again) or possibly flaky (passes on rerun), but it does not launder the exit code. This is a deliberate strict default: CI should not go green just because a test happened to pass on a second attempt.

`--parallel` support
--------------------

[](#--parallel-support)

Both flags work under `--parallel`. Each paratest worker is a separate process with its own partial view of the results — only the fraction of tests it happened to run — so this plugin does nothing in worker processes and defers entirely to the **coordinator** process. The coordinator never runs any tests itself (it just dispatches work to workers and waits), so instead of PHPUnit's normal per-process result facade, it reads `Pest\Plugins\Parallel\Paratest\WrapperRunner::$result` — the object Pest's own parallel runner populates by merging every worker's serialized result once they've all finished. That merged result is what gets written to `.pest-only-failed.json` and what `--rerun-failed` reruns.

The rerun itself always runs **serially**, even after a `--parallel` main pass — a rerun set is normally a handful of tests, not enough to be worth re-parallelizing, and it avoids recursing through the whole worker/coordinator split a second time.

`--only-failed`'s read side needs no special handling at all: it pushes a `--filter` argument before Pest hands off to paratest, so paratest just distributes the already-narrowed test list across workers as normal.

Known upgrade risks
-------------------

[](#known-upgrade-risks)

This plugin relies on internal PHPUnit/Pest details that are **not** covered by either project's backward-compatibility promise:

- `PHPUnit\TestRunner\TestResult\Facade::result()` — PHPUnit's own internal accessor for the current run's results, marked `@internal`. A future PHPUnit release could change or remove it.
- Pest overrides PHPUnit's `--filter` matching (see `vendor/pestphp/pest/overrides/Runner/Filter/NameFilterIterator.php`) to match functional `test()`/`it()` cases against their **printable** name (the original description string, via `Pest\Contracts\HasPrintableTestCaseName`) rather than the internal, mangled method name PHPUnit's event system reports. This plugin builds its failure ids the same way Pest's override does, so `--filter` round-trips correctly — but that override is itself `@internal` to Pest and could change in a future release. Classic class-based (`extends TestCase`) tests aren't affected by this distinction.
- `Pest\Plugins\Parallel::isWorker()`/`isEnabled()` and `Pest\Plugins\Parallel\Paratest\WrapperRunner::$result` — all `@internal`to Pest, and specific to Pest's current paratest integration. If Pest changes how it merges parallel results, `--parallel` support here could silently start reading a stale or empty result again.

If either of these break, both flags will most likely fail to select the right tests (or select none) rather than fail silently — bug reports welcome.

How it works
------------

[](#how-it-works)

- `--only-failed` reads `.pest-only-failed.json` and, if it has entries, pushes a `--filter` argument onto the CLI arguments before PHPUnit boots (via `Pest\Contracts\Plugins\HandlesArguments`).
- After the run finishes (via `Pest\Contracts\Plugins\Terminable`), the plugin reads the final result, writes the current failure list, and — if `--rerun-failed` was passed and something failed — spawns a **fresh subprocess** (`php vendor/bin/pest --filter=... --colors=...`) scoped to just those tests. A second in-process PHPUnit run isn't attempted: `PHPUnit\TextUI\Application::run()` seals the event subscriber system with no corresponding unseal, so a second in-process run risks colliding with already-sealed state from the first pass.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance90

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor2

2 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 ~4 days

Total

2

Last Release

49d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/fb66a58abe215b3029c04d80c13d3fce8adaa693a0e66c9d57c59da53ea69b69?d=identicon)[CornerMonkey](/maintainers/CornerMonkey)

---

Top Contributors

[![CornerMonkey](https://avatars.githubusercontent.com/u/42125571?v=4)](https://github.com/CornerMonkey "CornerMonkey (5 commits)")[![tim-zitcha](https://avatars.githubusercontent.com/u/152822531?v=4)](https://github.com/tim-zitcha "tim-zitcha (5 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/cornermonkey-pest-plugin-rerun/health.svg)

```
[![Health](https://phpackages.com/badges/cornermonkey-pest-plugin-rerun/health.svg)](https://phpackages.com/packages/cornermonkey-pest-plugin-rerun)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

35.4k569.8M21.9k](/packages/laravel-framework)[matomo/matomo

Matomo is the leading Free/Libre open analytics platform

21.8k40.0k](/packages/matomo-matomo)[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k104.7M369](/packages/laravel-horizon)[tempest/framework

The PHP framework that gets out of your way.

2.3k42.4k21](/packages/tempest-framework)[drupal/core

Drupal is an open source content management platform powering millions of websites and applications.

21668.5M2.0k](/packages/drupal-core)[illuminate/console

The Illuminate Console package.

13747.3M7.7k](/packages/illuminate-console)

PHPackages © 2026

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