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.
Installation:
composer require wyrihaximus/test-utilities
Add the package to your project’s composer.json under require-dev if not using globally.
PHPUnit Integration: Extend your test case with the provided base class:
use WyriHaximus\TestUtilities\TestCase;
class MyTest extends TestCase
{
// Your tests here
}
Rector Configuration:
Create a rector.php file in your project root:
<?php
declare(strict_types=1);
use WyriHaximus\TestUtilities\RectorConfig;
return RectorConfig::configure(__DIR__);
PHPStan Integration:
Add the package’s PHPStan extension to your phpstan.neon:
includes:
- vendor/wyrihaximus/test-utilities/extension.neon
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);
}
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));
}
Namespace Generation:
Use getRandomNamespace() for testing classes in isolated namespaces:
$namespace = $this->getRandomNamespace();
eval("namespace $namespace; class TestClass {}");
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
}
}
Automated Refactoring:
Use the RectorConfig to standardize your codebase:
vendor/bin/rector process src --dry-run
@var → #[var]).etc/, src/, tests/).Custom Rules: Extend the config for project-specific rules:
return RectorConfig::configure(__DIR__)
->withPaths(['src'])
->withRules([
// Custom rules here
]);
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
Test-Specific Rules: Override rules for test files:
paths:
tests:
- testCaseClassName: 'WyriHaximus\TestUtilities\TestCase'
excludeRules: ['*']
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);
}
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();
});
}
Event Testing: Use random namespaces for isolated event listeners:
public function testEventListener()
{
$namespace = $this->getRandomNamespace();
$listener = new ($namespace . '\EventListener');
$this->bus->assertListening($listener);
}
Randomness in CI:
afterApplicationCreated or tearDown:
protected function tearDown(): void
{
parent::tearDown();
$this->cleanupRandomDirectory();
}
Rector Path Conflicts:
etc/, src/, and tests/ paths in RectorConfig match your project structure. Override with:
RectorConfig::configure(__DIR__)
->withPaths(['custom/src', 'custom/tests'])
PHPStan Overrides:
phpstan.neon:
excludeRules:
- WyriHaximus\TestUtilities\Rules\*
Namespace Collisions:
$namespace = $this->getRandomNamespace('Test');
Slow Tests:
phpunit-slow-test-detector (included) to identify slow tests:
vendor/bin/phpunit --testdox-html slow-tests.html
Rector Dry Runs:
vendor/bin/rector process src --dry-run
PHPStan Debugging:
vendor/bin/phpstan analyse --verbose src
Custom Test Case:
Extend TestCase to add project-specific helpers:
class ProjectTestCase extends TestCase
{
protected function createTestUser(): User
{
return User::factory()->create();
}
}
Rector Rules: Add custom Rector rules to the config:
RectorConfig::configure(__DIR__)
->withRules([
new SetTypehintToString(),
new AddExplicitReturnType(),
]);
PHPStan Rules:
Extend the package’s rules in phpstan.neon:
includes:
- vendor/wyrihaximus/test-utilities/extension.neon
- rules.neon
Service Provider Testing:
Use refreshApplication() to reset the container:
public function testServiceProvider()
{
$this->refreshApplication();
$this->assertTrue(app()->has('custom.service'));
}
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());
}
}
Migration Testing:
Use Schema::dropIfExists() for clean migrations:
public function testMigration()
{
Schema::dropIfExists('test_table');
// Run migration
$this->assertTableExists('test_table');
}
Parallel Tests:
Use PHPUnit’s --parallel flag with isolated random directories:
vendor/bin/phpunit --parallel
Caching: Cache Rector results for faster runs:
RectorConfig::configure(__DIR__)
->withCacheDirectory(__DIR__ . '/var/rector-cache');
How can I help you explore Laravel packages today?