PHP Coverage
Framework Configuration (All Projects)
Key Requirements
- Coverage report must be in LCOV format
- Report must be saved as
coverage/lcov.info - Report must be uploaded as a GitHub Actions artifact named
coverage-report
PHPUnit is the most widely used testing framework for PHP and supports generating coverage reports in various formats. While PHPUnit generates Clover XML format by default, you can convert it to LCOV format for GitAuto compatibility.
Composer Configuration (Generic PHP Projects)
{
"require-dev": {
"phpunit/phpunit": "^12.0"
},
"scripts": {
"test": "phpunit"
}
}Composer Configuration (Laravel Projects)
If you're using Laravel, use this composer.json configuration instead:
{
"require-dev": {
"phpunit/phpunit": "^12.0"
},
"scripts": {
"test": [
"@php artisan config:clear --ansi",
"@php artisan test"
]
}
}PHPUnit Configuration (All Projects)
This configuration applies to both generic PHP and Laravel projects:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
<report>
<clover outputFile="coverage/clover.xml"/>
</report>
</coverage>
</phpunit>Setting Up GitHub Actions
Create a workflow file in .github/workflows/ directory. The filename can be anything you prefer (e.g. php-coverage.yml). Add the following content to your workflow file:
name: PHPUnit Coverage
# Run on target branch (probably default branch like main) to track coverage history
on:
push:
branches:
- main
# Optional: Only run when relevant files change (customize as needed)
paths:
- '**/*.php'
- composer.json
- composer.lock
- phpunit.xml
pull_request:
branches:
- main
paths:
- '**/*.php'
- composer.json
- composer.lock
- phpunit.xml
- '!.github/workflows/**'
workflow_dispatch:
# Auto-cancel outdated runs on the same branch
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
# Use Xdebug for comprehensive coverage (line, branch, path)
# PCOV is faster but only supports line coverage
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
coverage: xdebug
- name: Install dependencies
run: composer install --prefer-dist --no-progress
# PR: tests only, Push: tests with coverage
# For generic PHP: runs 'phpunit' which reads phpunit.xml
# For Laravel: runs 'php artisan test' which internally calls PHPUnit
- name: Run tests
if: github.event_name == 'pull_request'
run: composer test
# Both generate coverage because phpunit.xml configures it
- name: Run tests with coverage
if: github.event_name == 'push'
run: composer test
# Most popular Clover-to-LCOV conversion tool
- name: Convert Clover to LCOV format
if: github.event_name == 'push'
uses: andstor/clover2lcov-action@v1
with:
src: coverage/clover.xml
dst: coverage/lcov.info
- name: Upload coverage reports
if: github.event_name == 'push'
uses: actions/upload-artifact@v6
with:
name: coverage-report
path: coverage/lcov.infoKey Configuration Points
- Configure PHPUnit to generate Clover XML coverage reports (All Projects)
- Set up Xdebug or PCOV for code coverage (All Projects)
- Upload the report as an artifact - name must be either
coverage-reportor end withlcov.info(All Projects) - Ensure the artifact contains
coverage/lcov.infofile (All Projects)
Why !.github/workflows/** on PRs Only?
On pull requests, we exclude workflow file changes to keep the setup PR minimal. When you're adding or editing a workflow file, pre-existing test failures in your codebase are irrelevant and shouldn't block the PR. On push(after merge to main), we don't exclude them so that the initial coverage report gets generated on your target branch.
Viewing Coverage Reports
After your workflow runs successfully, GitAuto automatically processes the coverage reports and displays them in the Coverage Dashboard. GitAuto only saves coverage data when the workflow runs on your target branch (configurable in your repository's Rules page, defaults to your repository's default branch, e.g., main or master). This typically happens when:
- You merge a pull request to your target branch
- You push directly to your target branch
- You manually trigger the workflow
About LCOV:LCOV (Linux Code Coverage) is a standard format for code coverage data. It's pronounced "el-cov" and is widely supported by various tools and services.
Using multiple languages? If your repository has multiple programming languages (the docs use PHP + JavaScript as an example, but any combination works), see our Multi-Language Coverage guide for setting up coverage across all languages.
PHPUnit Coverage Mysteries?
PHP coverage can be tricky with Xdebug, memory limits, and configuration quirks. Whether PHPUnit is running slow, coverage is incomplete, or GitHub Actions are failing, we're here to help!
Contact us and let's debug this together!