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

Test Utilities Laravel Package

wyrihaximus/test-utilities

Shared test utilities for PHP projects: a PHPUnit TestCase with helpers like random namespaces and temp directories, plus ready-to-use PHPStan defaults and a preconfigured RectorConfig for common project layouts and doc-tag to attribute conversions.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require wyrihaximus/test-utilities
    

    Add the package to your project’s composer.json under require-dev if not using globally.

  2. PHPUnit Integration: Extend your test case with the provided base class:

    use WyriHaximus\TestUtilities\TestCase;
    
    class MyTest extends TestCase
    {
        // Your tests here
    }
    
  3. Rector Configuration: Create a rector.php file in your project root:

    <?php
    declare(strict_types=1);
    
    use WyriHaximus\TestUtilities\RectorConfig;
    
    return RectorConfig::configure(__DIR__);
    
  4. PHPStan Integration: Add the package’s PHPStan extension to your phpstan.neon:

    includes:
        - vendor/wyrihaximus/test-utilities/extension.neon
    

First Use Case

Random File Storage Testing: Use the built-in random directory and file utilities for isolated file-based tests:

public function testFileUpload()
{
    $tempDir = $this->getRandomDirectory();
    $tempFile = $this->getRandomFile($tempDir);

    // Test file operations here
    $this->assertFileExists($tempFile);
}

Implementation Patterns

PHPUnit Workflows

  1. Test Isolation: Leverage getRandomDirectory() and getRandomFile() to avoid test pollution:

    public function testUserUploadsFile()
    {
        $tempDir = $this->getRandomDirectory();
        $filePath = $this->createRandomFile($tempDir, 'test.txt', 'content');
    
        // Assertions and cleanup
        $this->assertFileExists($filePath);
        $this->assertEquals('content', file_get_contents($filePath));
    }
    
  2. Namespace Generation: Use getRandomNamespace() for testing classes in isolated namespaces:

    $namespace = $this->getRandomNamespace();
    eval("namespace $namespace; class TestClass {}");
    
  3. Database Testing: Combine with Laravel’s DatabaseTransactions trait for clean DB states:

    use Illuminate\Foundation\Testing\DatabaseTransactions;
    
    class UserTest extends TestCase
    {
        use DatabaseTransactions;
    
        public function testUserCreation()
        {
            // Test logic
        }
    }
    

Rector Integration

  1. Automated Refactoring: Use the RectorConfig to standardize your codebase:

    vendor/bin/rector process src --dry-run
    
    • Converts docblocks to attributes (e.g., @var#[var]).
    • Standardizes paths (etc/, src/, tests/).
  2. Custom Rules: Extend the config for project-specific rules:

    return RectorConfig::configure(__DIR__)
        ->withPaths(['src'])
        ->withRules([
            // Custom rules here
        ]);
    

PHPStan Patterns

  1. Type Safety: Use the package’s PHPStan extension to enforce stricter typing in tests:

    // phpstan.neon
    includes:
        - vendor/wyrihaximus/test-utilities/extension.neon
    levels:
        - max
    
  2. Test-Specific Rules: Override rules for test files:

    paths:
        tests:
            - testCaseClassName: 'WyriHaximus\TestUtilities\TestCase'
              excludeRules: ['*']
    

Laravel-Specific Patterns

  1. Artisan Command Testing: Use getRandomNamespace() for isolated command classes:

    public function testCustomCommand()
    {
        $namespace = $this->getRandomNamespace();
        $command = new ($namespace . '\CustomCommand');
    
        $this->artisan('custom:command')
             ->expectsOutput('Expected output')
             ->assertExitCode(0);
    }
    
  2. Service Container Mocking: Combine with Laravel’s MockApplication for clean container tests:

    public function testServiceBinding()
    {
        $this->mock(Application::class, function ($mock) {
            $mock->shouldReceive('bind')
                 ->once();
        });
    }
    
  3. Event Testing: Use random namespaces for isolated event listeners:

    public function testEventListener()
    {
        $namespace = $this->getRandomNamespace();
        $listener = new ($namespace . '\EventListener');
    
        $this->bus->assertListening($listener);
    }
    

Gotchas and Tips

Pitfalls

  1. Randomness in CI:

    • Random directories/files may cause flaky tests in CI if not cleaned up. Use afterApplicationCreated or tearDown:
      protected function tearDown(): void
      {
          parent::tearDown();
          $this->cleanupRandomDirectory();
      }
      
  2. Rector Path Conflicts:

    • Ensure etc/, src/, and tests/ paths in RectorConfig match your project structure. Override with:
      RectorConfig::configure(__DIR__)
          ->withPaths(['custom/src', 'custom/tests'])
      
  3. PHPStan Overrides:

    • The package’s PHPStan extension may conflict with custom rules. Explicitly exclude rules in phpstan.neon:
      excludeRules:
          - WyriHaximus\TestUtilities\Rules\*
      
  4. Namespace Collisions:

    • Random namespaces may collide with existing classes. Use a prefix:
      $namespace = $this->getRandomNamespace('Test');
      

Debugging Tips

  1. Slow Tests:

    • Use phpunit-slow-test-detector (included) to identify slow tests:
      vendor/bin/phpunit --testdox-html slow-tests.html
      
  2. Rector Dry Runs:

    • Always run Rector in dry mode first:
      vendor/bin/rector process src --dry-run
      
  3. PHPStan Debugging:

    • Enable verbose output for PHPStan:
      vendor/bin/phpstan analyse --verbose src
      

Extension Points

  1. Custom Test Case: Extend TestCase to add project-specific helpers:

    class ProjectTestCase extends TestCase
    {
        protected function createTestUser(): User
        {
            return User::factory()->create();
        }
    }
    
  2. Rector Rules: Add custom Rector rules to the config:

    RectorConfig::configure(__DIR__)
        ->withRules([
            new SetTypehintToString(),
            new AddExplicitReturnType(),
        ]);
    
  3. PHPStan Rules: Extend the package’s rules in phpstan.neon:

    includes:
        - vendor/wyrihaximus/test-utilities/extension.neon
        - rules.neon
    

Laravel-Specific Quirks

  1. Service Provider Testing: Use refreshApplication() to reset the container:

    public function testServiceProvider()
    {
        $this->refreshApplication();
        $this->assertTrue(app()->has('custom.service'));
    }
    
  2. Queue Testing: Combine with Laravel’s QueueTestingTrait:

    use Illuminate\Foundation\Testing\Concerns\InteractsWithQueues;
    
    class QueueTest extends TestCase
    {
        use InteractsWithQueues;
    
        public function testJobDispatch()
        {
            $this->assertCount(0, $this->queuedJobs());
            // Dispatch job
            $this->assertCount(1, $this->queuedJobs());
        }
    }
    
  3. Migration Testing: Use Schema::dropIfExists() for clean migrations:

    public function testMigration()
    {
        Schema::dropIfExists('test_table');
        // Run migration
        $this->assertTableExists('test_table');
    }
    

Performance Tips

  1. Parallel Tests: Use PHPUnit’s --parallel flag with isolated random directories:

    vendor/bin/phpunit --parallel
    
  2. Caching: Cache Rector results for faster runs:

    RectorConfig::configure(__DIR__)
        ->withCacheDirectory(__DIR__ . '/var/rector-cache');
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4