Code Coverage

Once you've written a handful of tests, a natural question comes up: how much of my actual code is being exercised by all of this? Code coverage answers that question — it measures what percentage of your source code's lines actually ran while the test suite executed.

What Code Coverage Measures

Coverage tools watch your source code line-by-line while the test suite runs and record which lines were actually executed at least once. A file with 100 lines where 80 of them ran during testing has 80% coverage. It's a measurement of execution, not correctness — a line can run and still be covered by a test that doesn't check its result properly.

Coverage Requires a Driver: Xdebug or PCOV

PHPUnit can't measure coverage on its own — it needs a coverage driver installed and enabled in PHP to hook into code execution. The two common options are Xdebug (a full debugging and profiling extension that also does coverage) and PCOV (a lightweight extension built specifically for coverage, and noticeably faster since it does nothing else). Either one needs to be installed as a PHP extension and enabled in your php.ini before PHPUnit can generate a report — the full install steps are specific to your OS and PHP setup, so they're not repeated here.

Note: If neither driver is installed, PHPUnit will still run your tests normally — it just can't produce a coverage report, and will tell you so if you ask for one.

Generating a Coverage Report

With a driver enabled, PHPUnit can generate coverage output in several formats. Two of the most commonly used:

# A browsable HTML report — open coverage/index.html in a browser afterward
./vendor/bin/phpunit --coverage-html coverage/

# A quick per-file summary printed straight to the terminal
./vendor/bin/phpunit --coverage-text

The HTML report is the most useful for actually digging in — it highlights covered lines in green and uncovered ones in red, file by file, so you can see exactly which parts of a class were never exercised. The text report is handy for a fast check, e.g. in a CI log.

FlagOutput
--coverage-html coverage/Browsable HTML report with line-by-line highlighting
--coverage-textPlain-text percentage summary in the terminal

100% Coverage Is Not the Same as Bug-Free

Warning: Code coverage only proves that a line of code ran during testing — it says nothing about whether the test actually checked that the line did the right thing. A test with no assertions at all can still produce 100% coverage for the code it happens to execute. Treat coverage as a signal pointing you toward code that has no tests at all, not as a scoreboard to max out for its own sake. A codebase with 70% coverage and carefully-written assertions can be far more trustworthy than one with 100% coverage and sloppy tests.

Used well, coverage reports are a map of the gaps — "this branch of the if statement has never been tested" is genuinely useful information. Used poorly, chasing a coverage percentage as the only goal can encourage writing tests that touch a lot of code without actually verifying much of anything.

Next up: Organizing Tests covers structuring a growing test suite with phpunit.xml and a tests/ folder that mirrors your source code.