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 if only needed for testing.

  2. Basic Usage:

    use SebastianBergmann\CodeCoverage\CodeCoverage;
    use SebastianBergmann\CodeCoverage\Driver\Selector;
    use SebastianBergmann\CodeCoverage\Filter;
    use SebastianBergmann\CodeCoverage\Report\Facade;
    
    $filter = new Filter;
    $filter->includeFiles([__DIR__ . '/src/**/*.php']);
    
    $coverage = new CodeCoverage(
        (new Selector)->forLineCoverage($filter),
        $filter
    );
    
    $coverage->start('Test Suite');
    // Execute your tests or code here
    $coverage->stop();
    
    Facade::fromObject($coverage)->renderHtml(__DIR__ . '/coverage-report');
    
  3. Key Classes:

    • CodeCoverage: Core class for collecting coverage data.
    • Filter: Define which files/methods to include/exclude.
    • Report\Facade: Generate reports (HTML, XML, etc.).
    • Serialization\Serializer/Unserializer: Save/load coverage data.

Implementation Patterns

Daily Workflows

1. Test-Driven Coverage

  • Pattern: Integrate coverage into CI/CD pipelines.
// In your test bootstrap file (e.g., tests/bootstrap.php)
$coverage = new CodeCoverage(
    (new Selector)->forLineCoverage(),
    new Filter
);
$coverage->start('Unit Tests');

// Run tests
$result = (new TestRunner)->run();

$coverage->stop();
Facade::fromObject($coverage)->renderCrap(__DIR__ . '/coverage-crap.txt');

2. Custom Report Generation

  • Pattern: Extend Report\Facade for custom formats.
Facade::fromObject($coverage)->render(
    new CustomReportRenderer(),
    __DIR__ . '/custom-report.json'
);

3. Filtering Logic

  • Pattern: Use Filter to focus on critical paths.
$filter = new Filter;
$filter->includeFiles([__DIR__ . '/src/Service/*.php'])
       ->excludeFiles([__DIR__ . '/src/Service/Logger.php']);

4. Serialization for CI

  • Pattern: Save coverage data for later analysis.
$serializer = new Serializer();
$serializer->serialize($coverage, __DIR__ . '/coverage.data');

// Later...
$unserializer = new Unserializer();
$data = $unserializer->unserialize(__DIR__ . '/coverage.data');
Facade::fromSerializedData($data)->renderHtml(__DIR__ . '/report');

5. Branch/Path Coverage

  • Pattern: Enable deeper analysis.
$coverage = new CodeCoverage(
    (new Selector)->forBranchCoverage($filter),
    $filter
);

Integration Tips

Laravel-Specific Use Cases

  1. Service Provider Hook:

    // In AppServiceProvider
    public function boot()
    {
        if ($this->app->environment('testing')) {
            $coverage = new CodeCoverage(
                (new Selector)->forLineCoverage(),
                new Filter
            );
            $coverage->start('Laravel Tests');
    
            // Run tests via PHPUnit
            $coverage->stop();
            Facade::fromObject($coverage)->renderHtml(storage_path('coverage'));
        }
    }
    
  2. Artisan Command:

    // app/Console/Commands/GenerateCoverage.php
    public function handle()
    {
        $coverage = new CodeCoverage(
            (new Selector)->forLineCoverage(),
            new Filter
        );
        $coverage->start('Artisan Command');
    
        // Execute logic
        $coverage->stop();
        Facade::fromObject($coverage)->renderCrap(storage_path('coverage-crap.txt'));
    }
    
  3. Pest Integration:

    // pest.php
    beforeTests(function () {
        $coverage = new CodeCoverage(
            (new Selector)->forLineCoverage(),
            new Filter
        );
        $coverage->start('Pest Tests');
    });
    
    afterTests(function () use ($coverage) {
        $coverage->stop();
        Facade::fromObject($coverage)->renderHtml(storage_path('pest-coverage'));
    });
    

Gotchas and Tips

Pitfalls

  1. Driver Conflicts:

    • Issue: Using both xdebug and pcov can cause invalid XML.
    • Fix: Ensure only one driver is active. Use Selector to explicitly choose:
      (new Selector)->forLineCoverage()->withDriver('xdebug');
      
  2. Path Coverage Overhead:

    • Issue: Path coverage (forPathCoverage()) significantly slows down tests.
    • Tip: Use sparingly and only for critical paths.
  3. UTF-8 Validation:

    • Issue: Non-UTF-8 source files may break XML reports.
    • Fix: Ensure your source files are UTF-8 encoded.
  4. Race Conditions:

    • Issue: Parallel test runners (e.g., Pest with --parallel) may cause race conditions in coverage data.
    • Fix: Use CachingSourceAnalyser or serialize coverage data per test suite.
  5. Abstract Methods:

    • Issue: Abstract methods are incorrectly counted as executable lines.
    • Fix: Update to v14.1.2+ where this is fixed.
  6. Attribute Lines:

    • Issue: Lines spanned by attributes (e.g., #[Test]) are treated as executable.
    • Fix: Update to v14.1.1+ for proper handling.
  7. Dark Mode HTML Reports:

    • Issue: Custom colors may not work in dark mode.
    • Fix: Use the built-in colorblind-friendly palette or override via CSS.

Debugging Tips

  1. Verify Coverage Data:

    $summary = Facade::fromObject($coverage)->summary();
    $this->assertGreaterThan(80, $summary->getLineCoverageInPercent());
    
  2. Inspect Filter Rules:

    • Use Filter::getIncludedFiles() and Filter::getExcludedFiles() to debug inclusion/exclusion logic.
  3. Check Driver Compatibility:

    • Run with --debug flag in PHPUnit to see active drivers:
      phpunit --debug
      
  4. Validate XML Reports:

    • Use xmllint to validate generated XML:
      xmllint --noout coverage.xml
      
  5. Performance Bottlenecks:

    • Profile report generation with Facade::fromObject($coverage)->renderHtml() to identify slow steps.

Extension Points

  1. Custom Report Formats:

    • Extend SebastianBergmann\CodeCoverage\Report\Renderer\RendererInterface:
      class CustomRenderer implements RendererInterface {
          public function render(CodeCoverage $coverage, string $path): void {
              // Custom logic
          }
      }
      
  2. Filter Extensions:

    • Override SebastianBergmann\CodeCoverage\Filter methods like isFileIncluded() for dynamic rules.
  3. Driver Plugins:

    • Implement SebastianBergmann\CodeCoverage\Driver\DriverInterface for custom coverage drivers (e.g., for PHP 8.3+).
  4. Serialization Hooks:

    • Extend SebastianBergmann\CodeCoverage\Serialization\Serializer to add custom metadata:
      $serializer = new class($coverage) extends Serializer {
          protected function getAdditionalData(): array {
              return ['custom_key' => 'custom_value'];
          }
      };
      
  5. HTML Report Customization:

    • Override templates in the SebastianBergmann\CodeCoverage\Report\Html namespace or extend the Renderer class.

Laravel-Specific Quirks

  1. Storage Paths:

    • Use storage_path() for consistent coverage report storage:
      Facade::fromObject($coverage)->renderHtml(storage_path('coverage'));
      
  2. Artisan Commands:

    • Cache coverage data to avoid recomputation:
      if (!file_exists($coveragePath)) {
          $coverage->stop();
          Facade::fromObject($coverage)->renderHtml($coveragePath);
      }
      
  3. CI/CD Integration:

    • Use phpunit/php-code-coverage in combination with phpunit/phpunit for seamless CI integration:
      # .github/workflows/coverage.yml
      - name: Run tests with coverage
        run: phpunit --coverage-clover=coverage.xml
      
  4. **Pest

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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata