5.6. Observing Code Coverage

Code coverage tools allow a programmer to determine what parts of
their code have been actually executed, and which parts have
never actually been invoked. GHC has an option for generating
instrumented code that records code coverage as part of the
Haskell Program Coverage
(HPC) toolkit, which is included with GHC. HPC tools can
be used to render the generated code coverage information into
human understandable format.

Correctly instrumented code provides coverage information of two
kinds: source coverage and boolean-control coverage. Source
coverage is the extent to which every part of the program was
used, measured at three different levels: declarations (both
top-level and local), alternatives (among several equations or
case branches) and expressions (at every level). Boolean
coverage is the extent to which each of the values True and
False is obtained in every syntactic boolean context (ie. guard,
condition, qualifier).

HPC displays both kinds of information in two primary ways:
textual reports with summary statistics (hpc report) and sources
with color mark-up (hpc markup). For boolean coverage, there
are four possible outcomes for each guard, condition or
qualifier: both True and False values occur; only True; only
False; never evaluated. In hpc-markup output, highlighting with
a yellow background indicates a part of the program that was
never evaluated; a green background indicates an always-True
expression and a red background indicates an always-False one.

5.6.1. A small example: Reciprocation

For an example we have a program, called Recip.hs, which computes exact decimal
representations of reciprocals, with recurring parts indicated in
brackets.

5.6.2. Options for instrumenting code for coverage

Turning on code coverage is easy, use the -fhpc flag.
Instrumented and non-instrumented can be freely mixed.
When compiling the Main module GHC automatically detects when there
is an hpc compiled file, and adds the correct initialization code.

5.6.3. The hpc toolkit

The hpc toolkit uses a cvs/svn/darcs-like interface, where a
single binary contains many function units.

$ hpc
Usage: hpc COMMAND ...
Commands:
help Display help for hpc or a single command
Reporting Coverage:
report Output textual report about program coverage
markup Markup Haskell source with program coverage
Processing Coverage files:
sum Sum multiple .tix files in a single .tix file
combine Combine two .tix files in a single .tix file
map Map a function over a single .tix file
Coverage Overlays:
overlay Generate a .tix file from an overlay file
draft Generate draft overlay that provides 100% coverage
Others:
show Show .tix file in readable, verbose format
version Display version for hpc

In general, these options act on .tix file after an
instrumented binary has generated it, which hpc acting as a
conduit between the raw .tix file, and the more detailed reports
produced.

The hpc tool assumes you are in the top-level directory of
the location where you built your application, and the .tix
file is in the same top-level directory. You can use the
flag --srcdir to use hpc for any other directory, and use
--srcdir multiple times to analyse programs compiled from
difference locations, as is typical for packages.

We now explain in more details the major modes of hpc.

5.6.3.1. hpc report

hpc report gives a textual report of coverage. By default,
all modules and packages are considered in generating report,
unless include or exclude are used. The report is a summary
unless the --per-module flag is used. The --xml-output option
allows for tools to use hpc to glean coverage.

5.6.3.4. hpc combine

hpc combine is the swiss army knife of hpc. It can be
used to take the difference between .tix files, to subtract one
.tix file from another, or to add two .tix files. hpc combine does not
change the original .tix file; it generates a new .tix file.

5.6.4. Caveats and Shortcomings of Haskell Program Coverage

HPC does not attempt to lock the .tix file, so multiple concurrently running
binaries in the same directory will exhibit a race condition. There is no way
to change the name of the .tix file generated, apart from renaming the binary.
HPC does not work with GHCi.