Advanced use of Devel::Cover
Braga, Portugal -- 1st September 2005
Paul Johnson
www.pjcj.net
Devel::Cover
- Aimed at those who have used Devel::Cover
- or at least been to the introductory talk
- How to be more productive using Devel::Cover
Integration into the build process
- Using Devel::Cover should be easy
- in fact, everything should be easy
- Automate it!
ExtUtils::MakeMaker
$ cover -test
ExtUtils::MakeMaker
Add to Makefile.PL:
sub MY::postamble
{
qq[
testcover :
\t cover -test
]
}
ExtUtils::MakeMaker
Add to Makefile.PL:
sub MY::postamble
{
qq[
testcover :
\t cover -delete && \\
HARNESS_PERL_SWITCHES=-MDevel::Cover \$(MAKE) test && \\
cover -report text
]
}
ExtUtils::MakeMaker
Add to Makefile.PL:
use ExtUtils::MakeMaker::Coverage;
Written by Steve Peters
Module::Build
$ ./Build testcover
$ DEVEL_COVER_OPTIONS=-ignore,Build ./Build testcover
File Selection
- Collecting coverage data is expensive
- So don't collect more than necessary
- Pass options into Devel::Cover
- -select
- -ignore
- -inc
File Selection
- These are regular expressions
- Any file that is selected is selected
- otherwise any file that is ignored is ignored
- otherwise any file in one of the inc directories is ignored
- otherwise the file is selected
File Selection
- Add to the REs to select by using +select
- Reset the selections using -select
- The same principle applies to the REs to ignore
- inc directories are populated by @INC at the time Devel::Cover is built
- +inc adds to the list, -inc resets it
- defaults for ignore if blib exists: '^t/', '\.t', '^test\.pl'
-
-MDevel::Cover=-select,Mylib,+ignore,fools
Covering mod_perl
- Use Apache::Test
- make testcover
- Read the docs
Covering XS code
- C code coverage tool required
- For example, gcov
-
CCFLAGS=-fprofile-arcs\ -ftest-coverage
-
OTHERLDFLAGS=-fprofile-arcs\ -ftest-coverage
-
$ make testcover
-
$ gcov Mylib.xs
-
$ gcov2perl Mylib.xs.gcov
-
$ cover
Covering XS code
- Let the train take the strain
-
$ cover -test
Increasing Coverage
- Write more tests
- Remove unused code
- Merge databases from different runs
Merging Databases
- Database is normally cover_db directory and contents
- Parts stored using Storable
- Uses nstore for portability
- Run tests on different platforms
- Use NFS or copy the directories somehow
-
$ cover db1 db2 db3
Error Conditions
-
open F, ">", \$file or die "Cannot open $file: $!"
-
close F or die "Cannot close $file: $!"
Error Conditions
- Is it worth checking those error conditions?
-
BEGIN { *CORE::GLOBAL::close = sub { 0 } }
-
{ local *Mylib::meth = sub { 0 }; tst }
Uncoverable code
- What if it is impossible to test some code?
-
$x = shift || 7;
-
sub def { 1 } $x = shift || def;
- In general, Devel::Cover can't know that a sub always returns true
- Some people will rewrite the construct
- Pah! It's a bug in Devel::Cover!
- Tell Devel::Cover what code is uncovered
Uncoverable code
- Currently in development
- Principles tested
- Uses .uncoverable file
- md5sum of text on line
- People seem keen on comments in code
- Fixing up html report
Annotations
- Sometimes viewing other information can be useful
- Who last changed the untested code?
- Write an annotation!
- Currently available for svk
- Use the API
Reports
- Still not satisfied?
- Write a report!
- Please!
- CGI or mod_perl
- AJAX
- Tk, GTK+, wx
- curses
- Use the API
Problems Opportunities
- Threads
- Not running END blocks
-
eval "use $mod" if int rand 2;
- ... and many more ...
Future
- TODO
- Optimal test ordering and redundancy checking
- Mutation Coverage