File Coverage

blib/lib/Test/HasVersion.pm
Criterion Covered Total %
statement 63 63 100.0
branch 16 20 80.0
condition n/a
subroutine 14 14 100.0
pod 3 3 100.0
total 96 100 96.0


line stmt bran cond sub pod time code
1              
2             package Test::HasVersion;
3              
4 6     6   283109 use strict;
  6         17  
  6         258  
5 6     6   33 use warnings;
  6         118  
  6         402  
6              
7             our $VERSION = '0.012';
8              
9             =head1 NAME
10            
11             Test::HasVersion - Check Perl modules have version numbers
12            
13             =head1 SYNOPSIS
14            
15             C<Test::HasVersion> lets you check a Perl module has a version
16             number in a C<Test::Simple> fashion.
17            
18             use Test::HasVersion tests => 1;
19             pm_version_ok("M.pm", "Valid version");
20            
21             Module authors can include the following in a F<t/has_version.t>
22             file and let C<Test::HasVersion> find and check all
23             installable PM files in a distribution.
24            
25             use Test::More;
26             eval "use Test::HasVersion";
27             plan skip_all =>
28             'Test::HasVersion required for testing for version numbers' if $@;
29             all_pm_version_ok();
30            
31             =head1 DESCRIPTION
32            
33             Do you wanna check that every one of your Perl modules in
34             a distribution has a version number? You wanna make sure
35             you don't forget the brand new modules you just added?
36             Well, that's the module you have been looking for.
37             Use it!
38            
39             Do you wanna check someone else's distribution
40             to make sure the author have not commited the sin of
41             leaving Perl modules without a version that can be used
42             to tell if you have this or that feature? C<Test::HasVersion>
43             is also for you, nasty little fellow.
44            
45             There's a script F<test_version> which is installed with
46             this distribution. You may invoke it from within the
47             root directory of a distribution you just unpacked,
48             and it will check every F<.pm> file in the directory
49             and under F<lib/> (if any).
50            
51             $ test_version
52            
53             You may also provide directories and files as arguments.
54            
55             $ test_version *.pm lib/ inc/
56             $ test_version .
57            
58             (Be warned that many Perl modules in a F<t/> directory
59             do not receive versions because they are not used
60             outside the distribution.)
61            
62             Ok. That's not a very useful module by now.
63             But it will be. Wait for the upcoming releases.
64            
65             =head2 FUNCTIONS
66            
67             =over 4
68            
69             =cut
70              
71             # most of the following code was borrowed from Test::Pod
72              
73 6     6   34 use Test::Builder;
  6         28  
  6         181  
74 6     6   9766 use ExtUtils::MakeMaker; # to lay down my hands on MM->parse_version
  6         922403  
  6         6008  
75              
76             my $Test = Test::Builder->new;
77              
78             our @EXPORTS = qw( pm_version_ok all_pm_version_ok all_pm_files );
79              
80             sub import {
81 4     4   42     my $self = shift;
82 4         9     my $caller = caller;
83              
84 4         10     for my $func ( @EXPORTS ) {
85 6     6   382         no strict 'refs';
  6         15  
  6         2965  
86 12         24         *{$caller."::".$func} = \&$func;
  12         97  
87                 }
88              
89 4         46     $Test->exported_to($caller);
90 4         48     $Test->plan(@_);
91             }
92              
93             # from Module::Which
94              
95             #=begin private
96              
97             =item PRIVATE B<_pm_version>
98            
99             $v = _pm_version($pm);
100            
101             Parses a PM file and return what it thinks is $VERSION
102             in this file. (Actually implemented with
103             C<< use ExtUtils::MakeMaker; MM->parse_version($file) >>.)
104             C<$pm> is the filename (eg., F<lib/Data/Dumper.pm>).
105            
106             =cut
107              
108             #=end private
109              
110             sub _pm_version {
111 5     5   11     my $pm = shift;
112 5         11     my $v;
113 5         9     eval { $v = MM->parse_version($pm); };
  5         83  
114 5 50       912871     return $@ ? undef : $v;
115             }
116              
117             =item B<pm_version_ok>
118            
119             pm_version_ok('Module.pm');
120             pm_version_ok('M.pm', 'Has valid version');
121            
122             Checks to see if the given file has a valid
123             version. Actually a valid version number is
124             defined and not equal to C<'undef'> (the string)
125             which is return by C<_pm_version> if a version
126             cannot be determined.
127            
128             =cut
129              
130             sub pm_version_ok {
131 6     6 1 5260   my $file = shift;
132 6 100       33   my $name = @_ ? shift : "$file has version";
133              
134 6 100       344   if (!-f $file) {
135 1         5     $Test->ok(0, $name);
136 1         543     $Test->diag("$file does not exist");
137 1         75     return;
138               }
139              
140 5         22   my $v = _pm_version($file);
141 5         23   my $ok = _is_valid_version($v);
142 5         46   $Test->ok($ok, $name);
143             #$Test->diag("$file $v ") if $ok && $noisy;
144             }
145              
146             sub _is_valid_version {
147 5 50   5   56   defined $_[0] && $_[0] ne 'undef';
148             }
149              
150             =item B<all_pm_version_ok>
151            
152             all_pm_version_ok();
153             all_pm_version_ok(@PM_FILES);
154            
155             Checks every given file and F<.pm> files found
156             under given directories to see if they provide
157             valid version numbers. If no argument is given,
158             it defaults to check every file F<*.pm> in
159             the current directory and recurses under the
160             F<lib/> directory (if it exists).
161            
162             If no test plan was setted, C<Test::HasVersion> will set one
163             after computing the number of files to be tested. Otherwise,
164             the plan is left untouched.
165            
166             =cut
167              
168             sub all_pm_version_ok {
169 1     1 1 20   my @pm_files = all_pm_files(@_);
170 1 50       6   $Test->plan(tests => scalar @pm_files) unless $Test->has_plan;
171 1         558   for (@pm_files) {
172 1         5     pm_version_ok($_);
173               }
174             }
175              
176             #=begin private
177              
178             =item PRIVATE B<_list_pm_files>
179            
180             @pm_files = _list_pm_files(@dirs);
181            
182             Returns all PM files under the given directories.
183            
184             =cut
185              
186             #=end private
187              
188             # from Module::Which::List - eglob("**/*.pm")
189              
190 6     6   41 use File::Find qw(find);
  6         13  
  6         2072  
191              
192             sub _list_pm_files {
193 2     2   5   my @INC = @_;
194 2         3   my @files;
195              
196               my $wanted = sub {
197 13 100   13   537     push @files, $_ if /\.pm$/;
198 2         10   };
199              
200 2         5   for (@INC) {
201 2         3     my $base = $_;
202 2 50       23     if (-d $base) {
203 2         159       find({ wanted => $wanted, no_chdir => 1 }, $base);
204                 }
205               }
206 2         21   return sort @files;
207             }
208              
209             =item B<all_pm_files>
210            
211             @files = all_pm_files()
212             @files = all_pm_files(@files_and_dirs);
213            
214             Implements finding the Perl modules according to the
215             semantics of the previous function C<all_pm_version_ok>.
216            
217             =cut
218              
219             sub all_pm_files {
220 5     5 1 4069   my @args;
221 5 100       18   if (@_) {
222 2         5     @args = @_;
223               } else {
224 3         355     @args = ( grep(-f, glob("*.pm")), "lib/" );
225               }
226 5         10   my @pm_files;
227 5         13   for (@args) {
228 9 100       155     if (-f) {
    100          
229 5         13       push @pm_files, $_;
230                 } elsif (-d) {
231 2         7       push @pm_files, _list_pm_files($_);
232                 } else {
233             # not a file or directory: ignore silently
234                 }
235               }
236 5         26   return @pm_files;
237              
238             }
239              
240             =back
241            
242             =head1 USAGE
243            
244             Other usage patterns besides the ones given in the synopsis.
245            
246             use Test::More tests => $num_tests;
247             use Test::HasVersion;
248             pm_version_ok($file1);
249             pm_version_ok($file2);
250            
251             Obviously, you can't plan twice.
252            
253             use Test::More;
254             use Test::HasVersion;
255             plan tests => $num_tests;
256             pm_version_ok($file);
257            
258             C<plan> comes from C<Test::More>.
259            
260             use Test::More;
261             use Test::HasVersion;
262             plan 'no_plan';
263             pm_version_ok($file);
264            
265             C<no_plan> is ok either.
266            
267             =head1 SEE ALSO
268            
269             Test::Version
270            
271             Please reports bugs via CPAN RT,
272             http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-HasVersion
273            
274             =head1 AUTHOR
275            
276             A. R. Ferreira, E<lt>ferreira@cpan.orgE<gt>
277            
278             =head1 COPYRIGHT AND LICENSE
279            
280             Copyright (C) 2006 by A. R. Ferreira
281            
282             This library is free software; you can redistribute it and/or modify
283             it under the same terms as Perl itself.
284            
285             =cut
286              
287             1;
288              
289