24 days of Perl code from RJBS! Feed

In Pod We Trust

Pod::Coverage::TrustPod - 2009-12-04

Testing Pod Coverage

Andy Lester's fantastic Test::Pod::Coverage makes it easy to check whether you've covered all your code. The standard usage is to make a file named something like t/pod-coverage.t, with these contents:


1: 
2: 
3: 
4: 

 

use Test::More;
plan skip_all => "Test::Pod::Coverage 1.08 required for this test"
  unless eval "use Test::Pod::Coverage 1.08; 1";
all_pod_coverage_ok();

 

The test will find all the Perl libraries in your distribution, find all the public subroutines or methods, and then try to ensure that they're documented. It does this by finding all defined subroutines, ignoring ones that it thinks are private (anything starting with an underscore and Perl-wide things like import or DESTROY). Then it looks for =headn or =item entries. There's even a mechanism to supply your own coverage_class to, for example, allow documentation in parent classes to suffice -- that way you don't have to document new in every subclass you write.

Sometimes, though, you want to note that a symbol doesn't need to be checked. Maybe it's documented without having its own header, or maybe it's from a documented source more complex than an is-a relationship, like a role or trait. With Test::Pod::Coverage's default behavior, this is sort of a mess. You can either specify global options:


1: 
 

all_pod_coverage_ok({ trustme => [ qw( weird_doc_sub ) ] });
 

...but this will trust that symbol to be documented in all your modules. So instead, you could test libraries one by one, expanding that all_pod_coverage call into a bunch of single-module calls with the right arguments:


1: 
2: 
3: 

 

pod_coverage_ok('Library::Alpha', { trustme => [ qw( weird_doc_sub ) ] });
pod_coverage_ok('Library::Beta', { trustme => [ qw( weird_doc_method ) ] });
pod_coverage_ok($_) for qw(Library::Gamma Library::Epsilon);

 

...but this is a bunch more work, and you won't realize until it's too late that you forgot to add Library::Delta to the list of "no special treatment" routines.

Putting Trust Where it Belongs

Pod::Coverage::TrustPod is built on the idea that the best place to make a note about things already documented is in the documentation itself. You don't need to write a bunch of documentation for weird_doc_method, but you can make a note about it in the Pod. That way, every file has its own list of routines to consider already documented, but you can still call all_pod_coverage_ok.

When you write your library, you'd write something like this:


1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 

 

package Library::Alpha;
use parent 'Library::Common';

=for Pod::Coverage
  new
  weird_doc_method

=cut

sub new { ... }

sub weird_doc_method { ... }

=head2 documented_method

This method is really documented!

=cut

sub documented_method { ... }

 

And you'd write your t/pod-coverage.t file like this:


1: 
 

all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' });
 

That's it! Now all your documentation's coverage is easy to test, and exceptions are easy to maintain by putting the exceptions right where they belong: in the Pod document itself.

A final request...

Having Pod coverage tests is great. It helps you make sure that you documented things. What isn't great is when you let those tests run on the computer of anybody who's installing your code and they fail for some stupid reason. It prevents the user from installing your code just because it thinks you forgot to write enough documentation.

So, always write this t/pod-coverage.t


1: 
2: 
3: 
4: 
5: 
6: 

 

use Test::More;
plan skip_all => "author test only" unless $ENV{RELEASE_TESTING};
plan skip_all => "Test::Pod::Coverage 1.08 required for this test"
  unless eval "use Test::Pod::Coverage 1.08; 1";

all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' });

 

That way, the tests will only be run when you're testing your distribution before release.

See Also