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

A set of PHP test utilities for package development: a PHPUnit TestCase with helpers like random namespaces and temp directories, plus ready-made configuration defaults for PHPStan and Rector (paths and docblock-to-attribute conversions).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require wyrihaximus/test-utilities --dev
    

    Add to your composer.json under require-dev if not using --dev.

  2. First Use Case: Extend WyriHaximus\TestUtilities\TestCase in your test class for built-in utilities:

    use WyriHaximus\TestUtilities\TestCase;
    
    class MyTest extends TestCase
    {
        public function testRandomNamespace()
        {
            $namespace = $this->randomNamespace();
            $this->assertStringContainsString('\\', $namespace);
        }
    }
    
  3. Key Features to Explore:

    • Random Directories: $this->randomDirectory() for temp file/dir tests.
    • Rector Integration: Pre-configured RectorConfig for docblock-to-attribute conversion.
    • PHPStan Extensions: Built-in defaults for stricter static analysis.

Implementation Patterns

Core Workflows

1. Test Case Base Class

  • Pattern: Extend TestCase for all tests needing utilities.
  • Example:
    class FileUploadTest extends TestCase
    {
        public function testFileUpload()
        {
            $tempDir = $this->randomDirectory();
            $tempFile = $tempDir . '/test.txt';
            file_put_contents($tempFile, 'test');
            $this->assertFileExists($tempFile);
        }
    }
    
  • Why: Avoids manual temp dir/file cleanup and provides random namespaces/dirs.

2. Rector Integration

  • Pattern: Use RectorConfig for project-wide refactoring.
  • Example (rector.php):
    <?php
    declare(strict_types=1);
    use WyriHaximus\TestUtilities\RectorConfig;
    
    return RectorConfig::configure(__DIR__ . '/../src');
    
  • Why: Standardizes docblock-to-attribute conversion and configures etc/src/tests paths by default.

3. PHPStan Configuration

  • Pattern: Leverage built-in extensions for stricter analysis.
  • Example (phpstan.neon):
    includes:
        - vendor/wyrihaximus/test-utilities/extension.neon
    
  • Why: Reduces false positives and enforces consistent static analysis.

4. Random Data Generation

  • Pattern: Use helper methods for test data.
  • Examples:
    $this->randomNamespace();       // e.g., `\Test\Random\12345`
    $this->randomDirectory();       // e.g., `/tmp/php-test-12345`
    $this->randomString(10);        // e.g., `aB3x9KpL2`
    $this->randomEmail();           // e.g., `test+123@example.com`
    

5. File System Testing

  • Pattern: Combine randomDirectory() with Storage facades (if using Laravel).
  • Example:
    public function testStorageUpload()
    {
        Storage::put($this->randomFile(), 'test');
        $this->assertTrue(Storage::exists($this->randomFile()));
    }
    

Laravel-Specific Patterns

1. Artisan Command Testing

  • Pattern: Use randomString() for unique command inputs.
  • Example:
    public function testCustomCommand()
    {
        $input = $this->randomString();
        $this->artisan('command:name', ['input' => $input])
            ->assertExitCode(0);
    }
    

2. Database Testing

  • Pattern: Generate random model factories.
  • Example:
    public function testModelCreation()
    {
        $user = User::factory()->create([
            'email' => $this->randomEmail(),
        ]);
        $this->assertDatabaseHas('users', ['email' => $user->email]);
    }
    

3. API Testing

  • Pattern: Combine with Http tests for unique routes/data.
  • Example:
    public function testApiEndpoint()
    {
        $route = 'api/v1/users/' . $this->randomString();
        $this->get($route)->assertStatus(200);
    }
    

Gotchas and Tips

Pitfalls

  1. Temp Directory Cleanup:

    • Gotcha: randomDirectory() creates dirs in /tmp by default. Ensure your CI/CD cleans them up.
    • Fix: Use $this->assertDirectoryIsEmpty() or manually delete after tests.
  2. Rector Conflicts:

    • Gotcha: Pinning Rector versions (e.g., ^2.2.1) may cause dependency conflicts with other packages.
    • Fix: Unpin or use ^2.3.0 (as seen in v12.0.0) and resolve conflicts via composer why-not.
  3. PHPStan False Positives:

    • Gotcha: Extensions may not cover all edge cases in your codebase.
    • Fix: Extend extension.neon or report issues to the package.
  4. Namespace Collisions:

    • Gotcha: Random namespaces might collide with existing code.
    • Fix: Prefix with a project-specific string (e.g., Test\\MyProject\\).
  5. Laravel Storage Paths:

    • Gotcha: randomDirectory() paths may not resolve correctly in Laravel’s storage context.
    • Fix: Use storage_path($this->randomDirectory()) for Laravel-specific tests.

Debugging Tips

  1. Slow Tests:

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

    • Tip: Test Rector changes without modifying files:
      ./vendor/bin/rector process src --dry-run
      
  3. PHPStan Debugging:

    • Tip: Run PHPStan with verbose output:
      ./vendor/bin/phpstan analyse --level=max --error-format=github src
      

Extension Points

  1. Custom Test Case Methods:

    • How: Extend TestCase and override methods:
      class CustomTestCase extends TestCase
      {
          protected function randomLaravelModel(): Model
          {
              return Model::factory()->create();
          }
      }
      
  2. Rector Rules:

    • How: Add custom rules to RectorConfig:
      return RectorConfig::configure(__DIR__)
          ->withRules([
              new YourCustomRule(),
          ]);
      
  3. PHPStan Extensions:

    • How: Merge custom extensions:
      extends: vendor/wyrihaximus/test-utilities/extension.neon
      includes:
          - your-custom-extension.neon
      
  4. Test Utilities:

    • How: Add to TestCase via traits or service providers:
      use function WyriHaximus\TestUtilities\randomString;
      
      $this->assertStringMatchesFormat('/^[a-z0-9]{10}$/', randomString(10));
      

Laravel Integration Tips

  1. Service Provider Booting:

    • Tip: Use refreshDatabase() or refreshTestingDatabase() in TestCase:
      protected function setUp(): void
      {
          parent::setUp();
          $this->refreshDatabase();
      }
      
  2. Artisan Commands:

    • Tip: Mock commands for faster tests:
      $this->mock(Artisan::class)->shouldReceive('call')->once();
      
  3. Event Testing:

    • Tip: Use randomString() for event payloads:
      Event::fake();
      $this->dispatch(new YourEvent($this->randomString()));
      Event::assertDispatched(YourEvent::class);
      
  4. Queue Testing:

    • Tip: Combine with randomString() for unique jobs:
      $job = new YourJob($this->randomString());
      $this->assertQueued($job);
      
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