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

Psalm Tester Laravel Package

alies-dev/psalm-tester

Run Psalm static analysis tests using .phpt fixtures. Define PHP code plus expected output (or EXPECTF), pass custom Psalm CLI args per tester or per test, and conditionally skip tests via SKIPIF. Integrates easily with PHPUnit test suites.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Install the package** via Composer:
   ```bash
   composer require --dev alies-dev/psalm-tester
  1. Publish the configuration (recommended for customization):

    php artisan vendor:publish --provider="AliesDev\PsalmTester\PsalmTesterServiceProvider" --tag="psalm-tester-config"
    

    This generates config/psalm-tester.php with updated defaults for batching, progress, and parallel execution.

  2. Run a basic Psalm check with batching and progress:

    ./vendor/bin/psalm-tester run --batch-size=20 --progress
    

    Outputs real-time progress (e.g., Batch 1/5: src/Module1/*.php (20% complete)).

  3. Parallel batch execution (optimized for CI):

    ./vendor/bin/psalm-tester run --batch-size=50 --parallel --workers=4
    

    Processes files concurrently while maintaining batch boundaries.


Implementation Patterns

Core Workflow: Batch-Aware Testing

  1. Define test expectations with batch overrides:

    use AliesDev\PsalmTester\Tests\PsalmTestCase;
    
    class TypeCheckTest extends PsalmTestCase
    {
        public function testModuleBatch()
        {
            $this->assertPsalmNoErrors([
                'src/Module1/*.php' => '...',
                'src/Module2/*.php' => '...',
            ], batchSize: 30); // Override default batch size
        }
    }
    
  2. Conditional Test Skipping with --SKIPIF--:

    public function testFeatureFlaggedCode()
    {
        $this->assertPsalmNoErrors([
            'src/Feature.php' => <<<'PHP'
            class Feature {
                // --SKIPIF-- !env('FEATURE_ENABLED')
                public function experimentalMethod() { ... }
                // --SKIPIF--
            }
            PHP,
        ], skipIf: fn() => !env('FEATURE_ENABLED'));
    }
    
  3. Parallel Execution with Resilience:

    ./vendor/bin/psalm-tester run \
      --batch-size=25 \
      --parallel \
      --workers=4 \
      --continue-on-error
    

    Key Flags:

    • --continue-on-error: Skip failed batches (useful for CI).
    • --workers=N: Limit parallel workers (default: CPU cores).

CI/CD Integration

GitHub Actions Example:

- name: Run Psalm with Batching
  run: |
    ./vendor/bin/psalm-tester run \
      --batch-size=50 \
      --parallel \
      --workers=2 \
      --progress \
      --format=junit \
      --output=psalm-report.xml
- name: Upload Artifacts
  uses: actions/upload-artifact@v3
  with:
    name: psalm-report
    path: psalm-report.xml

Custom Batch Strategies

Extend BatchStrategy for domain-specific grouping:

class DirectoryBasedBatchStrategy implements BatchStrategy
{
    public function groupFiles(array $files, int $batchSize): array
    {
        return array_chunk($files, $batchSize, true);
    }
}

Register in config/psalm-tester.php:

'batch_strategy' => \App\Strategies\DirectoryBasedBatchStrategy::class,

Gotchas and Tips

Pitfalls

  1. Batch Execution Quirks:

    • Ordering: Batches execute sequentially by default. Use --parallel cautiously with stateful operations.
    • Memory Spikes: Monitor batch size with --verbose:
      ./vendor/bin/psalm-tester run --batch-size=50 --verbose
      
    • Partial Failures: A single batch failure stops execution unless --continue-on-error is used.
  2. --SKIPIF-- Section Rules:

    • Syntax: Sections must be exactly --SKIPIF-- (case-sensitive) with no extra whitespace.
    • Scope: Conditions evaluate per-test, not per-batch. Cache results for expensive checks:
      skipIf: fn() => Cache::remember('skip_check', now()->addMinutes(5), fn() => ...)
      
    • Limitations: Only supports PHP expressions or function calls (no multi-line conditions).
  3. Progress Output Overhead:

    • Disable with --no-progress in CI:
      ./vendor/bin/psalm-tester run --no-progress
      
    • Customize template in config/psalm-tester.php:
      'progress_template' => '[{group}/{total}] {file} ({percent}%)',
      

Debugging

  1. Batch-Specific Issues:

    • Inspect batch boundaries with --debug-batches:
      ./vendor/bin/psalm-tester run --batch-size=2 --debug-batches
      
    • Output shows file grouping per batch (e.g., Batch 1: [src/File1.php, src/File2.php]).
  2. Conditional Skip Debugging:

    • Test skipIf logic in isolation:
      ./vendor/bin/psalm-tester debug:skip --condition="!env('FEATURE_ENABLED')"
      
    • Validate --SKIPIF-- sections with:
      ./vendor/bin/psalm-tester validate:skip src/Feature.php
      
  3. Parallel Execution Gotchas:

    • Race Conditions: Avoid shared state in parallel batches.
    • Worker Limits: Default workers = CPU cores. Reduce for memory-constrained environments:
      ./vendor/bin/psalm-tester run --workers=1
      

Extension Points

  1. Progress Event Listeners: Subscribe to batch/progress events for custom logging:

    use AliesDev\PsalmTester\Events\BatchProgress;
    
    BatchProgress::subscribe(function (BatchProgress $event) {
        logger()->debug("Batch {$event->batchNumber} progress", [
            'completed' => $event->completedFiles,
            'total' => $event->totalFiles,
        ]);
    });
    
  2. Dynamic Skip Providers: Implement SkipProvider for runtime conditions:

    class FeatureToggleSkipProvider implements SkipProvider
    {
        public function shouldSkip(string $file, string $section): bool
        {
            return FeatureFlags::isDisabled(basename($file));
        }
    }
    

    Register in config:

    'skip_providers' => [
        \App\Providers\FeatureToggleSkipProvider::class,
    ],
    
  3. Custom Progress Formats: Extend ProgressRenderer for team-specific output:

    class SlackProgressRenderer implements ProgressRenderer
    {
        public function render(int $group, int $total, int $percent): string
        {
            return "🚀 Psalm: {$percent}% complete ({$group}/{$total})";
        }
    }
    

    Register in config:

    'progress_renderer' => \App\Renderers\SlackProgressRenderer::class,
    

Configuration Quirks

  1. Environment-Specific Batching: Override batch settings per environment:

    // config/psalm-tester.php
    'environments' => [
        'ci' => [
            'batch' => ['size' => 100, 'parallel' => true, 'workers' => 4],
        ],
        'local' => [
            'batch' => ['size' => 10],
        ],
    ],
    
  2. Progress Output Levels:

    • Disable per-test with @skipProgress annotation:
      /**
       * @skipProgress
       */
      public function testNoProgress()
      {
          // ...
      }
      
    • Global toggle in config:
      'progress' => [
          'enabled' => env('CI') ? false : true,
      ],
      
  3. Batch Size Limits:

    • Default: 20 (adjustable via CLI or config).
    • Warning: Values > 100 may cause memory issues. Monitor with --verbose.
  4. --SKIPIF-- Section Validation:

    • Sections must be top-level (no nesting in classes/methods).
    • Avoid mixing with PHPDoc blocks (use // --SKIPIF-- instead of /** --SKIPIF-- */).

---
**Key Updates for 0.3.0**:
- **Batch Execution**: Memory-efficient processing for large codebases with configurable batch sizes and parallel workers.
- **Progress Tracking**: Real-time CLI feedback with customizable templates and per-test control.
- **Conditional Skipping**: `--SKIPIF--` sections for environment-aware test execution.
- **Extension Points**: New interfaces for progress rendering, skip providers, and batch strategies.
- **CI/CD Optimizations**: Built-in support for parallel execution and JUnit reporting
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.
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
spatie/mailcoach-vapor