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.
## Getting Started
### Minimal Setup
1. **Install the package** via Composer:
```bash
composer require --dev alies-dev/psalm-tester
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.
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)).
Parallel batch execution (optimized for CI):
./vendor/bin/psalm-tester run --batch-size=50 --parallel --workers=4
Processes files concurrently while maintaining batch boundaries.
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
}
}
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'));
}
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).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
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,
Batch Execution Quirks:
--parallel cautiously with stateful operations.--verbose:
./vendor/bin/psalm-tester run --batch-size=50 --verbose
--continue-on-error is used.--SKIPIF-- Section Rules:
--SKIPIF-- (case-sensitive) with no extra whitespace.skipIf: fn() => Cache::remember('skip_check', now()->addMinutes(5), fn() => ...)
Progress Output Overhead:
--no-progress in CI:
./vendor/bin/psalm-tester run --no-progress
config/psalm-tester.php:
'progress_template' => '[{group}/{total}] {file} ({percent}%)',
Batch-Specific Issues:
--debug-batches:
./vendor/bin/psalm-tester run --batch-size=2 --debug-batches
Batch 1: [src/File1.php, src/File2.php]).Conditional Skip Debugging:
skipIf logic in isolation:
./vendor/bin/psalm-tester debug:skip --condition="!env('FEATURE_ENABLED')"
--SKIPIF-- sections with:
./vendor/bin/psalm-tester validate:skip src/Feature.php
Parallel Execution Gotchas:
./vendor/bin/psalm-tester run --workers=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,
]);
});
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,
],
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,
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],
],
],
Progress Output Levels:
@skipProgress annotation:
/**
* @skipProgress
*/
public function testNoProgress()
{
// ...
}
'progress' => [
'enabled' => env('CI') ? false : true,
],
Batch Size Limits:
20 (adjustable via CLI or config).100 may cause memory issues. Monitor with --verbose.--SKIPIF-- Section Validation:
// --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
How can I help you explore Laravel packages today?