Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Repeat Laravel Package

testo/repeat

Testo repeat policy plugin. Re-runs a test multiple times in a single run to surface flaky behavior, catch intermittent regressions, and verify consistent results. Opt-in per test or per test class and works alongside other Testo plugins.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package in your Laravel project (or Testo-based test suite):
    composer require --dev testo/repeat
    
  2. Enable the plugin in your Testo configuration (typically testo.php):
    return [
        'plugins' => [
            Testo\Repeat\RepeatPlugin::class,
        ],
    ];
    
  3. Annotate a test class or method to repeat execution:
    use Testo\Repeat\Repeat;
    
    class ExampleTest
    {
        #[Repeat(3)] // Runs this test 3 times
        public function test_something_flaky()
        {
            // Test logic here
        }
    }
    
    Or for a class-level repeat:
    #[Repeat(2)]
    class ExampleTest
    {
        // All tests in this class run 2 times
    }
    

First Use Case

Identify flaky tests in CI:

  • Add @Repeat(3) to tests known to fail intermittently (e.g., API calls, database operations).
  • Configure maxFailures to fail the test only if it fails all 3 times (default: maxFailures = 0 means any failure counts).
    #[Repeat(3, maxFailures: 1)] // Fails if ≥1 failure out of 3
    

Implementation Patterns

Core Workflows

  1. Opt-In Repeat Testing:

    • Use method-level repeats for granular control:
      #[Repeat(5)]
      public function test_payment_processing()
      {
          // Runs 5 times; fails if any iteration fails (default maxFailures=0)
      }
      
    • Use class-level repeats for consistency:
      #[Repeat(2)]
      class FlakyApiTest
      {
          // All tests here run twice
      }
      
  2. Failure Threshold Tuning:

    • Adjust maxFailures to balance sensitivity and noise:
      #[Repeat(3, maxFailures: 1)] // Fails if ≥1 failure (strict)
      #[Repeat(3, maxFailures: 2)] // Fails if ≥2 failures (lenient)
      
  3. Integration with Testo Plugins:

    • Combine with assertions, mocking, or database plugins:
      use Testo\Assert\Assert;
      use Testo\Repeat\Repeat;
      
      #[Repeat(3)]
      public function test_user_creation()
      {
          Assert::true(User::create(['name' => 'Test'])->exists());
      }
      
  4. CI-Specific Configuration:

    • Override repeats in CI via environment variables or config:
      // In testo.php
      'repeat' => [
          'default_repeats' => env('CI') ? 3 : 1,
      ],
      

Laravel-Specific Patterns

  1. Repeat Laravel Test Cases:

    • Extend TestCase and annotate:
      use Illuminate\Foundation\Testing\TestCase as LaravelTestCase;
      use Testo\Repeat\Repeat;
      
      #[Repeat(2)]
      class UserTest extends LaravelTestCase
      {
          // Laravel test logic
      }
      
  2. Repeat Database Transactions:

    • Useful for testing race conditions:
      #[Repeat(5)]
      public function test_concurrent_orders()
      {
          $this->seed();
          // Simulate concurrent requests
      }
      
  3. Repeat API Tests:

    • Catch intermittent HTTP failures:
      #[Repeat(3, maxFailures: 1)]
      public function test_api_payment()
      {
          $response = $this->post('/pay', ['amount' => 100]);
          $response->assertOk();
      }
      
  4. Compose with Laravel Factories:

    • Repeat tests using Laravel’s factories:
      #[Repeat(3)]
      public function test_factory_creation()
      {
          $user = User::factory()->create();
          Assert::true($user->exists());
      }
      

Gotchas and Tips

Common Pitfalls

  1. Test Hangs or Timeouts:

    • Repeating tests with slow operations (e.g., API calls, external services) can cause CI timeouts.
    • Fix: Add timeouts or reduce repeat counts for slow tests.
  2. False Positives from State Leakage:

    • Repeating tests that modify shared state (e.g., databases, caches) may cause failures in later iterations.
    • Fix: Use transactions or reset state between repeats:
      #[Repeat(3)]
      public function test_with_clean_state()
      {
          $this->withoutExceptionHandling();
          $this->artisan('migrate:fresh'); // Reset DB before each repeat
          // Test logic
      }
      
  3. maxFailures Misconfiguration:

    • Setting maxFailures too high may mask real issues.
    • Tip: Start with maxFailures: 0 (fail on any failure) and adjust as needed.
  4. Plugin Conflicts:

  5. Laravel-Specific Issues:

    • Application state (e.g., auth, sessions) may persist across repeats.
    • Fix: Reset state or use actingAs() per repeat:
      #[Repeat(2)]
      public function test_authenticated_routes()
      {
          $user = User::factory()->create();
          $this->actingAs($user); // Reset auth per repeat
          $this->get('/dashboard')->assertOk();
      }
      

Debugging Tips

  1. Log Repeat Iterations:

    • Add debug output to track repeat progress:
      #[Repeat(3)]
      public function test_debug_repeats()
      {
          \Log::info('Repeat iteration: ' . $this->getRepeatCount());
          // Test logic
      }
      
  2. Isolate Flaky Tests:

    • Temporarily increase repeats to 5–10 to expose hidden flakiness:
      #[Repeat(10)]
      public function test_high_risk_operation()
      {
          // ...
      }
      
  3. Check Testo’s Repeat Plugin Docs:

Extension Points

  1. Custom Repeat Logic:

    • Extend the Repeat trait or plugin to add dynamic repeat counts:
      use Testo\Repeat\Repeat;
      
      #[Repeat]
      public function test_dynamic_repeats()
      {
          $repeats = env('TEST_REPEATS', 3);
          $this->setRepeatCount($repeats);
          // Test logic
      }
      
  2. Post-Repeat Actions:

    • Hook into repeat completion (e.g., log stats):
      #[Repeat(3)]
      public function test_with_hooks()
      {
          $this->afterRepeat(function () {
              \Log::info('Test completed ' . $this->getRepeatCount() . ' times');
          });
          // Test logic
      }
      
  3. Global Repeat Configuration:

    • Override defaults in testo.php:
      'repeat' => [
          'default_repeats' => 2,
          'max_failures' => 0, // Fail on any failure
      ],
      

Performance Optimization

  1. Skip Repeats in Local Dev:

    • Disable repeats locally to speed up development:
      #[Repeat(app()->environment('production') ? 3 : 1)]
      public function test_production_only_repeats()
      {
          // ...
      }
      
  2. Parallelize Repeats (Advanced):

    • If Testo supports parallel testing, consider parallel repeat execution (requires custom setup).
  3. Exclude Stable Tests:

    • Avoid repeating deterministic tests to save time:
      #[Repeat(1)] // Disable repeats for stable tests
      public function test_stable_operation()
      {
          // ...
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
cadot.eu/make
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky