testo/codecov
Testo code coverage plugin: collects line and branch coverage during test runs and generates CI-friendly reports (Clover, Cobertura, PHPUnit XML). Supports per-test attribution so tools can map covered lines back to the test that exercised them.
composer require --dev testo/codecov
testo.php:
return [
'plugins' => [
Testo\Codecov\CodecovPlugin::class,
],
'coverage' => [
'enabled' => true,
'output' => 'cobertura', // or 'clover', 'xml'
'format' => 'text', // or 'json', 'xml'
],
];
vendor/bin/testo --coverage
Outputs reports to storage/logs/testo/coverage/.Validate CI pipeline integration:
cobertura format for SonarQube or clover for PHPStorm integration.Local Development:
vendor/bin/testo --coverage --watch
--coverage-format=json for programmatic analysis (e.g., custom scripts).CI/CD Integration:
- name: Test with Coverage
run: |
php -dxdebug.mode=coverage vendor/bin/testo --coverage=cobertura
- name: Upload to SonarQube
uses: SonarSource/sonarqube-scan-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
Per-Test Attribution:
// In a test file
public function test_user_creation() {
// ... assertions ...
}
storage/logs/testo/coverage/coverage.json for test-to-line mappings.Database Transactions:
DatabaseTransactions trait works with coverage, but ensure Xdebug isn’t disabled in .env:
XDEBUG_MODE=coverage
Artisan Commands:
// In Testo test file
public function test_command_coverage() {
$this->artisan('command:test')
->assertExitCode(0);
}
Custom Reports:
// app/Providers/TestoServiceProvider.php
public function boot() {
Testo\Codecov\CodecovPlugin::extend(function ($plugin) {
$plugin->addReport('laravel', function () {
// Custom logic for Laravel coverage
});
});
}
Xdebug Configuration:
.phpunit.xdebug.ini or CI env includes:
xdebug.mode=coverage
xdebug.start_with_request=yes
Inline Test Coverage:
testo.php:
'coverage' => [
'include_inline_tests' => false, // or true
],
Performance Overhead:
--no-coverage for fast feedback:
vendor/bin/testo --no-coverage
Report Paths:
storage/logs/testo/coverage/, which may not exist.storage/logs/testo/ is writable or configure a custom path:
'coverage' => [
'output_dir' => storage_path('app/coverage-reports'),
],
Empty Reports:
php -m | grep xdebug).vendor/bin/testo --coverage --verbose
Format Mismatches:
xmllint --schema https://raw.githubusercontent.com/cobertura-coverage/cobertura/master/schema/coverage-04.xsd storage/logs/testo/coverage/cobertura.xml
Test Attribution:
coverage.json to map tests to lines:
{
"tests": {
"path/to/TestClass.php:test_method": ["file.php:10", "file.php:20"]
}
}
Custom Drivers:
Testo\Codecov\CodecovPlugin::extend(function ($plugin) {
$plugin->setDriver(new CustomCoverageDriver());
});
Report Filters:
vendor/, tests/):
'coverage' => [
'exclude' => [
'vendor/',
'tests/Feature/',
],
],
CI-Specific Logic:
'coverage' => [
'enabled' => app()->environment('ci'),
],
Service Container Conflicts:
// config/testo.php
'bootstrap' => [
App\Providers\TestoServiceProvider::class,
],
Artisan Command Testing:
--coverage with command tests:
public function test_command_with_coverage() {
$this->artisan('command:test', ['--coverage' => true])
->expectsOutput('Coverage: 100%')
->assertExitCode(0);
}
Pest Migration:
composer.json:
"scripts": {
"test": "testo",
"test:coverage": "testo --coverage"
}
How can I help you explore Laravel packages today?