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

Phpunit Select Config Laravel Package

automattic/phpunit-select-config

Small utility for PHPUnit projects that helps select or switch the PHPUnit configuration file to use when running tests. Handy for repos with multiple phpunit.xml variants (e.g., local vs CI) and scripts that need consistent config selection.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package:

    composer require --dev automattic/phpunit-select-config
    

    This adds the phpunit-select-config binary to vendor/bin/.

  2. Create Versioned Config Files: Name your PHPUnit configs with a versioned pattern (e.g., phpunit.8.xml.dist, phpunit.9.xml.dist, phpunit.10.xml.dist). The # in the filename pattern (e.g., phpunit.#.xml.dist) will be replaced by the detected PHPUnit major version.

  3. First Usage: Replace direct phpunit calls with:

    vendor/bin/phpunit-select-config phpunit.#.xml.dist
    

    Or via Composer:

    composer exec -- phpunit-select-config phpunit.#.xml.dist
    
  4. Laravel Integration: Add a custom Artisan command (e.g., app/Console/Commands/RunVersionedTests.php) to wrap the package:

    use Automattic\PHPUnitSelectConfig\Runner;
    
    class RunVersionedTests extends Command {
        protected $signature = 'test:versioned {config_pattern? : e.g., phpunit.#.xml.dist}';
        public function handle() {
            $pattern = $this->argument('config_pattern') ?? 'phpunit.#.xml.dist';
            $runner = new Runner($pattern);
            $runner->run();
        }
    }
    

    Register the command in app/Console/Kernel.php:

    protected $commands = [
        Commands\RunVersionedTests::class,
    ];
    

Implementation Patterns

Usage Patterns

  1. Version-Based Testing: Use the package to automatically select configs based on the PHPUnit version installed in your environment (e.g., CI vs. local dev). Example:

    # Runs phpunit.9.xml.dist if PHPUnit 9.x is detected
    php artisan test:versioned phpunit.#.xml.dist
    
  2. Environment-Specific Configs: Extend the pattern to include environment-specific configs (e.g., phpunit.ci.#.xml.dist, phpunit.local.#.xml.dist). Override the pattern dynamically:

    $env = app()->environment();
    $pattern = "phpunit.{$env}.#.xml.dist";
    $runner = new Runner($pattern);
    
  3. Feature-Flagged Tests: Use the package to toggle test suites via config files (e.g., phpunit.feature-x.#.xml.dist). Trigger via CLI:

    php artisan test:versioned phpunit.feature-x.#.xml.dist
    
  4. CI/CD Pipeline Integration: Replace php artisan test with the versioned command in CI scripts. Example (GitHub Actions):

    - name: Run Tests
      run: php artisan test:versioned phpunit.ci.#.xml.dist
    

Workflows

  1. Local Development:

    • Use phpunit.local.#.xml.dist for local overrides (e.g., slower tests, debug configurations).
    • Example:
      composer exec -- phpunit-select-config phpunit.local.#.xml.dist
      
  2. Parallel Test Execution: Combine with Laravel’s --parallel flag:

    php artisan test:versioned phpunit.#.xml.dist --parallel
    
  3. Custom Test Groups: Create configs like phpunit.unit.#.xml.dist and phpunit.integration.#.xml.dist, then run selectively:

    php artisan test:versioned phpunit.unit.#.xml.dist
    

Integration Tips

  1. Laravel TestCase Bootstrapping: Ensure your TestCase extends Illuminate\Foundation\Testing\TestCase and that the package’s config selection doesn’t interfere with Laravel’s service providers. If issues arise, override the createApplication method to enforce config selection:

    public function createApplication() {
        $config = $this->getTestConfig(); // Custom logic to fetch config
        $runner = new Runner($config);
        return $runner->createLaravelApplication();
    }
    
  2. Composer Scripts: Add a custom Composer script to simplify usage:

    {
        "scripts": {
            "test": "php artisan test:versioned phpunit.#.xml.dist",
            "test:unit": "php artisan test:versioned phpunit.unit.#.xml.dist"
        }
    }
    

    Now run tests with:

    composer test
    
  3. Environment Variables: Allow dynamic config selection via .env:

    TEST_CONFIG_PATTERN=phpunit.ci.#.xml.dist
    

    Update the Artisan command to read this:

    $pattern = env('TEST_CONFIG_PATTERN', 'phpunit.#.xml.dist');
    
  4. Fallback Configs: Provide a default config in the pattern (e.g., phpunit.default.xml.dist) to handle cases where the versioned config doesn’t exist:

    php artisan test:versioned phpunit.#.xml.dist --fallback=phpunit.default.xml.dist
    

Gotchas and Tips

Pitfalls

  1. Filename Pattern Mismatch:

    • The # in the pattern must match the PHPUnit major version (e.g., phpunit.9.xml.dist for PHPUnit 9.x). If the file doesn’t exist, the package will fail silently or throw an error.
    • Fix: Validate the pattern and files exist before execution. Add a check in your Artisan command:
      if (!file_exists($selectedConfig)) {
          $this->error("Config file not found: {$selectedConfig}");
          return 1;
      }
      
  2. PHPUnit Version Detection:

    • The package detects the PHPUnit version via phpunit --version. If PHPUnit isn’t in PATH or the version is unrecognized, it may default to an incorrect config.
    • Fix: Explicitly set the PHPUnit version in your config or use a wrapper script to ensure the correct version is used.
  3. Laravel Service Provider Conflicts:

    • If your TestCase relies on service providers or bindings that aren’t loaded in the selected config, tests may fail unexpectedly.
    • Fix: Ensure all required providers are included in every versioned config or override createApplication to load them dynamically.
  4. CI/CD Environment Issues:

    • In CI, the PHPUnit version might differ from local dev, causing unexpected config selection. For example, GitHub Actions might use PHPUnit 10 while your local machine uses PHPUnit 9.
    • Fix: Pin the PHPUnit version in composer.json or use a matrix strategy in CI to test multiple versions.
  5. Performance Overhead:

    • The package adds a small overhead to test execution due to config selection logic. In CI, this might increase build times marginally.
    • Fix: Benchmark the impact and consider caching the selected config in a temporary file for repeated runs.

Debugging

  1. Verbose Output: Enable debug mode to see which config is being selected:

    composer exec -- phpunit-select-config --verbose phpunit.#.xml.dist
    

    Or extend your Artisan command:

    $runner->setVerbose(true);
    
  2. Logging: Add logging to track config selection:

    Log::info("Selected config: {$selectedConfig}");
    
  3. Dry Runs: Test config selection without running tests:

    composer exec -- phpunit-select-config --dry-run phpunit.#.xml.dist
    

Config Quirks

  1. Case Sensitivity: Filename patterns are case-sensitive. Ensure your configs match the pattern exactly (e.g., phpunit.8.xml.dist vs. phpunit.8.XML.dist).

  2. Default Configs: The package doesn’t provide a built-in default config. Always specify a fallback or ensure the pattern matches an existing file.

  3. Custom PHPUnit Arguments: Arguments passed to phpunit-select-config are forwarded to PHPUnit, but some (e.g., --configuration) may conflict with the package’s logic.

    • Fix: Avoid passing --configuration manually; let the package handle it.

Extension Points

  1. Custom Config Selectors: Extend the package’s logic to support non-version-based selection (e.g., by environment, feature flag, or custom logic). Fork the package or create a wrapper:

    class CustomConfigSelector {
        public function selectConfig(string $pattern): string {
            $version = $this->detectPhpUnitVersion();
            $env = app()->environment();
            return str_replace('#', $version, str_replace('.', ".{$env}.", $pattern));
        }
    }
    
  2. Pre/Post-Execution Hooks: Add hooks to validate configs or modify the test environment before execution:

    $runner->addPreHook(function ($config) {
        if (!str_contains($config, 'coverage')) {
            putenv('X
    
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.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime