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

Php Code Coverage Laravel Package

phpunit/php-code-coverage

phpunit/php-code-coverage collects, processes, and renders PHP code coverage data. Integrate it in test runs to start/stop coverage collection, filter included files, and generate reports such as OpenClover, including from serialized coverage data.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev phpunit/php-code-coverage
    

    Add to composer.json under require-dev to ensure it’s only installed for development.

  2. Basic Usage with PHPUnit: Configure PHPUnit’s phpunit.xml to generate coverage:

    <phpunit>
        <extensions>
            <extension class="SebastianBergmann\CodeCoverage\CodeCoverage"/>
        </extensions>
        <coverage>
            <include>
                <directory>./src</directory>
            </include>
            <report>
                <html>./coverage-report</html>
                <clover>./coverage.clover</clover>
            </report>
        </coverage>
    </phpunit>
    

    Run tests with coverage:

    ./vendor/bin/phpunit
    
  3. Manual Integration: For custom workflows (e.g., CI pipelines), use the CodeCoverage class directly:

    use SebastianBergmann\CodeCoverage\CodeCoverage;
    use SebastianBergmann\CodeCoverage\Driver\Selector;
    use SebastianBergmann\CodeCoverage\Filter;
    
    $filter = new Filter();
    $filter->includeFiles(['./src/**/*.php']);
    
    $coverage = new CodeCoverage(
        (new Selector())->forLineCoverage($filter),
        $filter
    );
    
    $coverage->start('My Test Suite');
    // Execute test code...
    $coverage->stop();
    
    $coverage->getReport()->render('html', './custom-report');
    

Implementation Patterns

1. Filtering Code Coverage

  • Exclude Tests/Dependencies:
    $filter = new Filter();
    $filter->excludeFiles(['./tests/**', './vendor/**']);
    $filter->includeFiles(['./src/**/*.php']);
    
  • Dynamic Filtering: Use Filter::includePath() or excludePath() for glob patterns (e.g., ./src/Modules/*).

2. Report Generation

  • Standard Reports:
    $report = $coverage->getReport();
    $report->render('html', './report');       // HTML dashboard
    $report->render('clover', './clover.xml'); // Clover XML
    $report->render('cobertura', './cobertura.xml'); // Cobertura
    
  • Custom Report Paths: Store reports in versioned directories (e.g., ./coverage/$(date +%Y-%m-%d)) for CI artifacts.

3. Serialization for CI/CD

  • Serialize Coverage Data:
    $serializer = new \SebastianBergmann\CodeCoverage\Serialization\Serializer();
    $serializer->serialize($coverage, './coverage.data');
    
  • Deserialize Later:
    $unserializer = new \SebastianBergmann\CodeCoverage\Serialization\Unserializer();
    $data = $unserializer->unserialize('./coverage.data');
    $report = \SebastianBergmann\CodeCoverage\Report\Facade::fromSerializedData($data);
    $report->render('html', './restored-report');
    

4. Integration with PHPUnit

  • Custom Test Listeners: Extend PHPUnit\Framework\TestListener to hook into coverage events:
    $coverage = new CodeCoverage(...);
    $coverage->start('Custom Suite');
    $listener = new class implements TestListener {
        public function endTest(Test $test, $time): void {
            if ($test instanceof MyTest) {
                $coverage->stop();
            }
        }
    };
    $this->listeners[] = $listener;
    

5. Branch/Path Coverage

  • Enable with Selector:
    $coverage = new CodeCoverage(
        (new Selector())->forBranchCoverage($filter), // or forPathCoverage()
        $filter
    );
    
  • View in HTML reports (requires PHP 8.1+ for path coverage).

6. Parallel Testing

  • Thread-Safe Serialization: Use Unserializer::unserialize() with relative paths (since v14.0.0) to merge coverage from parallel workers:
    # Worker 1
    ./vendor/bin/phpunit --coverage-php=coverage1.data --workers=2
    
    # Worker 2
    ./vendor/bin/phpunit --coverage-php=coverage2.data --workers=2
    
    # Merge
    php merge-coverage.php coverage1.data coverage2.data merged.data
    

Gotchas and Tips

Pitfalls

  1. Path Resolution:

    • Reports use relative paths by default (since v14.0.0). Absolute paths in serialized data may break if the working directory changes.
    • Fix: Use Filter::setAbsolutePath() or ensure consistent getcwd().
  2. PHP Version Quirks:

    • PHP 8.3+: Some features (e.g., path coverage) require PHP 8.1+. Test locally before CI.
    • Xdebug/PCOV Conflicts: If both extensions are loaded, coverage data may be corrupted. Use Selector::forLineCoverage() explicitly to avoid conflicts.
  3. Attribute Lines:

    • Lines with #[...] (PHP 8 attributes) are not executable but may be marked as covered. Exclude them with:
      $filter->excludeLinesByToken([T_ATTRIBUTE]);
      
  4. Race Conditions:

    • Parallel test runners (e.g., phpunit --parallel) may cause CachingSourceAnalyser race conditions. Use --process-isolation or merge coverage post-execution.
  5. UTF-8 Validation:

    • Reports fail if source files contain invalid UTF-8. Validate with:
      find src -type f -exec iconv -f UTF-8 -t UTF-8 {} > /dev/null || echo "Invalid UTF-8 found"
      

Debugging Tips

  1. Inspect Coverage Data:

    foreach ($coverage->getData() as $file => $lines) {
        echo "$file: " . count($lines) . " lines\n";
        print_r($lines);
    }
    
  2. Check Driver:

    • Verify the active driver (Xdebug/PCOV) with:
      echo $coverage->getDriver()->getName();
      
  3. HTML Report Issues:

    • Clear browser cache or use --force with phpunit to regenerate reports.
    • Dark mode may fail if CSS is cached. Force a hard refresh (Ctrl+F5).
  4. Serialization Errors:

    • Ensure the serialized file matches the PHP version used for unserialization (e.g., v14.1+ data won’t work with v12.x).

Extension Points

  1. Custom Report Formats: Extend SebastianBergmann\CodeCoverage\Report\Renderer\RendererInterface to create new formats (e.g., JSON for APIs):

    class JsonRenderer implements RendererInterface {
        public function render(CodeCoverage $coverage, string $path): void {
            file_put_contents($path, json_encode($coverage->getData()));
        }
    }
    
  2. Filter Logic: Override SebastianBergmann\CodeCoverage\Filter to implement custom include/exclude rules (e.g., exclude magic methods):

    $filter = new class extends Filter {
        public function apply(CodeCoverage $coverage): void {
            parent::apply($coverage);
            $coverage->removeLinesByToken([T_MAGIC_METHOD]);
        }
    };
    
  3. CI Artifacts: Use Report\Facade::summary() to extract metrics for CI badges:

    $summary = \SebastianBergmann\CodeCoverage\Report\Facade::fromObject($coverage)->summary();
    echo "Coverage: {$summary->getLineCoveragePercentage()}%";
    

    Output to a file for CI tools (e.g., GitHub Actions):

    echo "COVERAGE_PERCENTAGE=$(php get-coverage.php)" >> $GITHUB_ENV
    
  4. Performance Tuning:

    • Disable source analysis for large projects:
      $coverage->disableSourceAnalysis();
      
    • Cache coverage data in CI to avoid reprocessing:
      if [ -f coverage.data ]; then
          ./vendor/bin/phpunit --coverage-php=coverage.data
      else
          ./vendor/bin/phpunit --coverage-php=coverage.data --coverage-text
      fi
      

Config Quirks

  1. Xdebug Settings: Ensure xdebug.mode=coverage (PHP 8.2+) or xdebug.coverage_enable=1 is set in php.ini or .env:

    XDEBUG_MODE=coverage
    XDEBUG_OUTPUT_DIR=./coverage
    
  2. **PCOV

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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai