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

Eris Laravel Package

giorgiosironi/eris

Eris brings QuickCheck-style property-based testing to PHP and PHPUnit. Define properties, generate many randomized inputs, and let Eris shrink failing cases to minimal counterexamples. Works with PHP 8.1+ and PHPUnit 10–13 via a simple TestTrait.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation: Add Eris via Composer in your Laravel project's test dependencies:
    composer require --dev giorgiosironi/eris
    
  2. Test Trait: Use the TestTrait in your PHPUnit test classes:
    use Eris\TestTrait;
    use Eris\Generators;
    
    class ExampleTest extends \Tests\TestCase
    {
        use TestTrait;
    }
    

First Use Case: Property-Based Testing

Test a simple property (e.g., "sum of two numbers is commutative"):

public function testSumCommutativity()
{
    $this->forAll(
        Generators::int(),
        Generators::int()
    )
    ->then(function ($a, $b) {
        $this->assertEquals($a + $b, $b + $a);
    });
}

Key Starting Points

  • Generators: Explore Generators::* static methods (e.g., int(), string(), date()).
  • Annotations: Use @eris-* annotations for test configuration (e.g., @eris-repeat 100).
  • Documentation: Refer to Eris ReadTheDocs for advanced usage.

Implementation Patterns

Core Workflow: Property-Based Testing

  1. Define Generators: Use Generators::* to create input generators.
    $generator = Generators::array(Generators::string(), 10);
    
  2. Chain with forAll: Bind generators to test logic.
    $this->forAll($generator)
         ->then(function ($array) {
             $this->assertCount(10, $array);
         });
    
  3. Combine Generators: Use Generators::tuple(), Generators::oneOf(), or Generators::suchThat().
    $this->forAll(
        Generators::tuple(Generators::int(), Generators::string())
    )->then(function ($tuple) {
        $this->assertIsInt($tuple[0]);
    });
    

Integration with Laravel

  1. TestCase Setup: Extend Laravel's TestCase and include TestTrait:
    use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
    use Eris\TestTrait;
    
    class FeatureTest extends BaseTestCase
    {
        use TestTrait;
    }
    
  2. Database Testing: Use Generators::date() or Generators::uuid() for realistic test data:
    $this->forAll(Generators::date('Y-m-d'))
         ->then(function ($date) {
             $this->assertDatabaseHas('events', ['date' => $date]);
         });
    

Advanced Patterns

  • Custom Generators: Extend Eris\Generator\AbstractGenerator for domain-specific inputs.
  • Shrinking: Enable shrinking to find minimal failing inputs:
    $this->forAll(Generators::int())
         ->shrink()
         ->then(...);
    
  • Listeners: Hook into test lifecycle with Listener::* (e.g., log generations or collect frequencies):
    $this->hook(Listener\collectFrequencies('generations.log'));
    

Gotchas and Tips

Common Pitfalls

  1. Generator Size: Large generators (e.g., Generators::string(1000)) may slow tests. Use limitTo() to cap iterations:
    $this->forAll(Generators::string(1000))
         ->limitTo(100)
         ->then(...);
    
  2. Shrinking Overhead: Disable shrinking for performance-critical tests:
    $this->forAll(Generators::int())
         ->disableShrinking()
         ->then(...);
    
  3. Annotation Conflicts: Ensure @eris-* annotations don’t clash with Laravel’s testing annotations (e.g., @test).

Debugging Tips

  • Environment Variables:
    • ERIS_SEED=123 for reproducible test runs.
    • ERIS_ORIGINAL_INPUT=1 to log generated inputs in failures.
  • Verbose Output: Use Listener\log() to debug generator behavior:
    $this->hook(Listener\log('debug.log'));
    
  • PSalm Compatibility: Avoid Generators::oneOf() with complex types (see #153).

Extension Points

  1. Custom Shrinkers: Implement Eris\Shrinker\ShrinkerInterface for domain-specific shrinking logic.
  2. Generator Combinators: Use Generators::bind() to create dependent generators:
    $generator = Generators::bind(
        Generators::int(),
        function ($size) { return Generators::array(Generators::string(), $size); }
    );
    
  3. Listener Extensions: Extend Eris\Listener\ListenerInterface to integrate with Laravel’s event system (e.g., log test results to Scout).

Laravel-Specific Quirks

  • Service Container: Bind custom generators as Laravel services:
    $this->app->bind('custom.generator', function () {
        return new CustomGenerator();
    });
    
  • Test Isolation: Use Generators::uuid() for unique test data in integration tests:
    $this->forAll(Generators::uuid())
         ->then(function ($uuid) {
             $this->assertDatabaseMissing('users', ['id' => $uuid]);
         });
    

Performance Optimization

  • Memoization: Cache expensive generator outputs in Laravel’s cache:
    $cachedGenerator = Generators::memoize(
        Generators::complexGenerator(),
        fn ($value) => Cache::remember("generator_{$value}", now()->addHour(), fn () => $value)
    );
    
  • Parallel Testing: Combine with Laravel’s parallel PHPUnit flag for faster property checks.
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai