9. Code Coverage Analysis
In this chapter you will learn all about PHPUnit’s code coverage functionality that provides an insight into what parts of the production code are executed when the tests are run. It makes use of the php-code-coverage component, which in turn leverages the code coverage functionality provided by the or PCOV extensions for PHP or by .
Note
If you see a warning while running tests that no code coverage driver is available, it means that you are using the PHP CLI binary () and do not have Xdebug or PCOV loaded.
PHPUnit can generate an HTML-based code coverage report as well as XML-based logfiles with code coverage information in various formats (Clover, Cobertura, Crap4J, PHPUnit). Code coverage information can also be reported as text (and printed to STDOUT) and exported as PHP code for further processing.
Please refer to The Command-Line Test Runner for a list of command line switches that control code coverage functionality as well as for the relevant configuration settings.
Various software metrics exist to measure code coverage:
Line Coverage
The Line Coverage software metric measures whether each executable line was executed.
Branch Coverage
Path Coverage
Function and Method Coverage
Class and Trait Coverage
The Class and Trait Coverage software metric measures whether each method of a class or trait is covered. php-code-coverage only considers a class or trait as covered when all of its methods are covered.
Change Risk Anti-Patterns (CRAP) Index
It is mandatory to configure a filter for telling PHPUnit which sourcecode files to include in the code coverage report. This can either be done using the --coverage-filter
command line option or via the configuration file (see ).
The includeUncoveredFiles
and processUncoveredFiles
configuration settings are available to configure how the filter is used:
(default) means that all files are included in the code coverage report even if not a single line of code of such a file is executed
processUncoveredFiles="false"
(default) means that a file that has no executed lines of code will be added to the code coverage report (ifincludeUncoveredFiles="true"
is set) but it will not be loaded by PHPUnit and it will therefore not be analysed for correct executable lines of code information
Please note that the loading of sourcecode files that is performed when processUncoveredFiles="true"
is set can cause problems when a sourcecode file contains code outside the scope of a class or function, for instance.
Sometimes you have blocks of code that you cannot test and that you may want to ignore during code coverage analysis. PHPUnit lets you do this using the @codeCoverageIgnore
, @codeCoverageIgnoreStart
and annotations as shown in .
Example 9.1 Using the @codeCoverageIgnore
, @codeCoverageIgnoreStart
and @codeCoverageIgnoreEnd
annotations
The ignored lines of code (marked as ignored using the annotations) are counted as executed (if they are executable) and will not be highlighted.
The @covers
annotation (see the ) can be used in the test code to specify which code parts a test class (or test method) wants to test. If provided, this effectively filters the code coverage report to include executed code from the referenced code parts only. Example 9.2 shows an example.
Note
If a method is specified with the @covers
annotation, only the referenced method will be considered as covered, but not methods called by this method. Hence, when a covered method is refactored using the extract method refactoring, corresponding @covers
annotations need to be added. This is the reason it is recommended to use this annotation with class scope, not with method scope.
Example 9.2 Test class that specifies which class it wants to cover
Example 9.3 Tests that specify which method they want to cover
It is also possible to specify that a test should not cover any method by using the annotation (see ). This can be helpful when writing integration tests to make sure you only generate code coverage with unit tests.
Example 9.4 A test that specifies that no method should be covered
This section shows noteworthy edge cases that lead to confusing code coverage information.