Coverage: which code your tests run#

A coverage report answers a question the debugger cannot: which statements, branches, conditions and subroutines a test run never reached. pperl runs Devel::Cover, the coverage tool perl5 uses, and reports the same numbers perl5 does.

Installing Devel::Cover#

The compiled part of Devel::Cover is built into pperl. Its Perl modules and its cover command come from CPAN:

pperl --cpan Devel::Cover

They land under ~/.pperl (or $PPERL_HOME, see Installing CPAN modules): the modules in ~/.pperl/lib/perl5, which pperl searches without being told, and the command as ~/.pperl/bin/cover.

If PERL5LIB points at a perl5 tree that already has Devel::Cover, pperl --cpan finds that copy, reports the module as up to date and installs nothing. Run it with PERL5LIB unset. Keep the perl5 tree’s copy out of covered runs, too: pperl needs its own.

Measuring a program#

Load Devel::Cover with -M, then run cover in the same directory:

pperl -MDevel::Cover yourprog.pl
pperl ~/.pperl/bin/cover

The run collects into cover_db/ in the current directory. cover prints a summary per file and writes an HTML report to cover_db/coverage.html. For a program prog.pl that calls one of the two subs of its module lib/Shape.pm:

------------ ------ ------ ------ ------ ------ ------
File           stmt   bran   cond    sub   time  total
------------ ------ ------ ------ ------ ------ ------
lib/Shape.pm   50.0   50.0   33.3   50.0    0.0   45.4
prog.pl       100.0    n/a    n/a  100.0  100.0  100.0
Total          81.8   50.0   33.3   75.0  100.0   70.0
------------ ------ ------ ------ ------ ------ ------

Every option of Devel::Cover and of cover works as under perl5: cover -report text for a plain-text report, -report json for JSON, cover -delete to start over. A pod column appears when Pod::Coverage is installed, as it does under perl5.

Measuring a test suite#

HARNESS_PERL_SWITCHES adds -MDevel::Cover to every test the harness starts. Run prove itself under pperl, so that the tests run under pperl too; -S finds prove on the PATH:

HARNESS_PERL_SWITCHES=-MDevel::Cover=-ignore,^t/ pperl -S prove -l t
pperl ~/.pperl/bin/cover

-ignore,^t/ keeps the test files themselves out of the report. prove --exec pperl does not apply HARNESS_PERL_SWITCHES, under perl5 either, nor -l; with --exec, put both in the command itself: prove --exec "pperl -Ilib -MDevel::Cover=-ignore,^t/" t.

Choosing what is reported#

Devel::Cover leaves out modules that belong to the installation, ~/.pperl/lib/perl5 among them. The check it uses for that does not know PPERL5LIB or PPERL_HOME, so with either set, modules from those trees are covered and reported like your own code. In that setup, choose the files with -select and -ignore, both regular expressions over file names:

pperl -MDevel::Cover=-select,^lib/,-ignore,^t/ yourprog.pl

Speed#

While Devel::Cover collects, pperl does not compile loops to machine code: compiled code would run past the counters Devel::Cover reads. A covered run is therefore as fast as pperl’s interpreter, not as fast as a normal pperl run. A run without -MDevel::Cover is unaffected.