contributte/phpunit
PHPUnit integration helpers by Contributte for PHP projects. Provides lightweight tooling and conventions to simplify writing, running, and organizing tests, with sensible defaults and compatibility aimed at smoother CI and developer experience.
Installation:
composer require contributte/phpunit --dev
Add to composer.json under require-dev:
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
Run composer dump-autoload.
Basic Configuration:
Create a phpunit.xml (or extend an existing one) with:
<phpunit bootstrap="vendor/autoload.php">
<extensions>
<extension class="Contributte\Phpunit\Extension\BootstrapExtension"/>
</extensions>
</phpunit>
First Use Case: Run a basic test:
./vendor/bin/phpunit
Verify the BootstrapExtension loads your Laravel environment (if configured).
Environment Bootstrapping:
Extend BootstrapExtension to load Laravel’s service container:
// In a custom extension class
public function bootstrap(PhpUnit\Runner\BeforeTestHook $hook) {
$app = require __DIR__.'/../../bootstrap/app.php';
$hook->addTestListener(new LaravelTestListener($app));
}
Test Isolation:
Use Contributte\Phpunit\Traits\RefreshDatabase for Laravel migrations:
use Contributte\Phpunit\Traits\RefreshDatabase;
class UserTest extends TestCase {
use RefreshDatabase;
// Tests run with a fresh DB
}
Custom Assertions:
Add assertions via Contributte\Phpunit\Extension\AssertionExtension:
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
Parallel Testing:
Configure in phpunit.xml:
<phpunit parallel="true" processes="4">
<!-- ... -->
</phpunit>
phpunit in package.json scripts:
"scripts": {
"test": "php artisan test",
"test:unit": "./vendor/bin/phpunit --testdox-html=tests/_output/coverage.html"
}
vendor/ and storage/logs/ for faster runs:
# .github/workflows/test.yml
jobs:
test:
steps:
- uses: actions/cache@v3
with:
path: |
vendor
storage/logs
key: ${{ runner.os }}-phpunit-${{ hashFiles('**/composer.lock') }}
Extension Conflicts:
laravel/phpunit, disable its extensions in phpunit.xml:
<extensions>
<extension class="Contributte\Phpunit\Extension\BootstrapExtension"/>
<!-- Exclude Laravel's default extensions -->
</extensions>
Database Traits:
RefreshDatabase does not roll back transactions—it truncates tables. Use sparingly in CI.SOFT_DELETE columns to avoid foreign key errors:
Schema::table('users', function (Blueprint $table) {
$table->softDeletes();
});
Parallel Testing Quirks:
config() caches) in tests. Use dependency injection.innodb_file_per_table must be enabled for parallel DB tests../vendor/bin/phpunit -v
phpunit.xml:
<extensions>
<extension class="Contributte\Phpunit\Extension\DebugExtension"/>
</extensions>
This dumps extension calls to storage/logs/phpunit.log.Custom Test Listeners:
Implement PhpUnit\Framework\TestListener:
class LaravelTestListener implements TestListener {
public function addError(Test $test, Throwable $t, float $time) {
Log::error("Test failed: {$test->getName()}", ['exception' => $t]);
}
}
Hooks:
Override bootstrap() in your extension to inject Laravel’s AppServiceProvider:
public function bootstrap(BeforeTestHook $hook) {
$hook->addTestListener(new LaravelServiceProviderListener());
}
Mocking Facades:
Use Contributte\Phpunit\Traits\MockFacades:
use Contributte\Phpunit\Traits\MockFacades;
class CacheTest extends TestCase {
use MockFacades;
public function testCache() {
$this->mockFacade(Cache::class);
Cache::shouldReceive('get')->andReturn('mocked');
}
}
phpunit.xml to match Laravel’s config:
<php>
<env name="TZ" value="UTC"/>
</php>
<php>
<memoryLimit>1G</memoryLimit>
</php>
How can I help you explore Laravel packages today?