Allows failed PHPUnit tests to automatically rerun.

0.2 2017-06-23 21:56 UTC


Average time to resolve an issue Percentage of issues still open Build Status codecov Dependency Status Reference Status HHVM Status

Latest Stable Version Total Downloads License

Allows failed PHPUnit tests to automatically rerun.

Use cases

Anywhere where there is an external dependency which you don't have full control of, e.g. when developing an SDK for some API, which might apply rate limiting or experience brief downtime.


  • Tested on HHVM
  • PHP 5.6 or 7.0+
  • Tested on PHPUnit 5.4 (require-dev ^5.0), but might run on older versions (update your installation!)


composer require --dev alorel/phpunit-auto-rerun


You can integrate retry functionality in your tests in one of two ways: using class inheritance or using traits.

In many situations, you can simply extend your test cases from PHPUnit_Retriable_TestCase, which itself extends the original PHPUnit_Framework_TestCase. Here, all you need to do is replace the class in your test cases:


    namespace Some\Thing\Or\Another;

    class PHPUnitReflectionTest extends \PHPUnit_Framework_TestCase {

would become


    namespace Some\Thing\Or\Another;

    class PHPUnitReflectionTest extends \PHPUnit_Retriable_TestCase {

In situations where your test cases have complex inheritance already, you can just use a trait in the test cases that need retry functionality:


    namespace Some\Thing\Or\Another;

    class MyTestCase extends MyTestBase {

        use \PHPUnit_Retriable_TestCase_Trait;


Modifying existing test cases/reverting back

The PHPUnit_Retriable_TestCase class was intentionally left in the global namespace to resemble the original PHPUnit_Framework_TestCase as much as possible. Most IDEs will generate/suggest a test case template to contain

class PHPUnitReflectionTest extends \PHPUnit_Retriable_TestCase

so you can safely do a tests-wide search-and-replace operation in either direction.


Configuration is performed via annotations, same way you'd configure expected exceptions, @befores and so on:

  • @retryCount specifies the maximum number of times a test case will run. Setting this to 0 will simply invoke the original test runner, setting it to 1 will run a test without retries (equivalent functionality), setting it to 5 will run it once and retry up to 4 times upon failure.
  • @sleepTime specifies how many seconds the script will sleep between retries.

Both these values default to 0.

Configuration can be performed by annotating both the class and the test method - class annotations are applied to all methods and are overriden by method annotations, for example, consider the following snippet:


     * @retryCount 5
    class SomeTest extends PHPUnit_Retriable_TestCase {

        function testOne() {
            //Will inherit the default sleep time of 0
            //and SomeTest's retry count of 5

         * @retryCount 0
        function testTwo() {
            //sleep time 0 (default)
            //retry count 0 (overrides SomeTest)

         * @sleepTime 10
        function testThree() {
            //sleep time 10 (overrides default)
            //retry count 5 (inherit from SomeTest)

         * @sleepTime 3
         * @retryCount 3
        function testFour() {
            //sleep time 3 (overrides default)
            //retry count 3 (overrides SomeTest)


Q: Will this work with @dataProvider annotations? A: Yes - the test will continue retrying with the same data provider value and continue to the next one when the test succeeds. This applies to both array data providers and generators/iterators.

Q: Why do I end up with a higher number of assertions than before? A: Even when a test fails it still increments the number of assertions made - it was not immediately obvious how to change this and I don't see it as an important feature, therefore I didn't bother implementing it.

Q: Can I set the configuration parameters via CLI/phpunit.xml? A: No and it does not appear to be possible without editing the original PHPUnit code.

* I wrote put these together before release, no one's asked them. Apologies for the ruse. 😞