1 #######################################################################
2 # $URL: http://perlcritic.tigris.org/svn/perlcritic/tags/Test-Perl-Critic-1.01/lib/Test/Perl/Critic.pm $
3 # $Date: 2007-01-24 22:22:10 -0800 (Wed, 24 Jan 2007) $
6 ########################################################################
8 package Test::Perl::Critic;
13 use English qw(-no_match_vars);
14 use Test::Builder qw();
15 use Perl::Critic qw();
16 use Perl::Critic::Violation qw();
17 use Perl::Critic::Utils;
20 #---------------------------------------------------------------------------
24 #---------------------------------------------------------------------------
26 my $TEST = Test::Builder->new();
29 #---------------------------------------------------------------------------
33 my ( $self, %args ) = @_;
36 no strict 'refs'; ## no critic
37 *{ $caller . '::critic_ok' } = \&critic_ok;
38 *{ $caller . '::all_critic_ok' } = \&all_critic_ok;
40 $TEST->exported_to($caller);
42 # -format is supported for backward compatibility
43 if( exists $args{-format} ){ $args{-verbose} = $args{-format}; }
49 #---------------------------------------------------------------------------
53 my ( $file, $test_name ) = @_;
54 croak q{no file specified} if not defined $file;
55 croak qq{"$file" does not exist} if not -f $file;
56 $test_name ||= qq{Test::Perl::Critic for "$file"};
64 # TODO: Should $critic be a global singleton?
65 $critic = Perl::Critic->new( %CRITIC_ARGS );
66 @violations = $critic->critique( $file );
67 $ok = not scalar @violations;
71 $TEST->ok( $ok, $test_name );
74 if ($EVAL_ERROR) { # Trap exceptions from P::C
75 $TEST->diag( "\n" ); # Just to get on a new line.
76 $TEST->diag( qq{Perl::Critic had errors in "$file":} );
77 $TEST->diag( qq{\t$EVAL_ERROR} );
79 elsif ( not $ok ) { # Report Policy violations
80 $TEST->diag( "\n" ); # Just to get on a new line.
81 $TEST->diag( qq{Perl::Critic found these violations in "$file":} );
83 my $verbose = $critic->config->verbose();
84 Perl::Critic::Violation::set_format( $verbose );
85 for my $viol (@violations) { $TEST->diag("$viol") }
91 #---------------------------------------------------------------------------
95 my @dirs = @_ ? @_ : _starting_points();
96 my @files = all_code_files( @dirs );
97 $TEST->plan( tests => scalar @files );
99 my $okays = grep { critic_ok($_) } @files;
100 return $okays == @files;
103 #---------------------------------------------------------------------------
106 my @dirs = @_ ? @_ : _starting_points();
107 return Perl::Critic::Utils::all_perl_files(@dirs);
110 #---------------------------------------------------------------------------
112 sub _starting_points {
113 return -e 'blib' ? 'blib' : 'lib';
116 #---------------------------------------------------------------------------
129 Test::Perl::Critic - Use Perl::Critic in test programs
135 use Test::Perl::Critic;
136 use Test::More tests => 1;
139 Or test all files in one or more directories:
141 use Test::Perl::Critic;
142 all_critic_ok($dir_1, $dir_2, $dir_N );
144 Or test all files in a distribution:
146 use Test::Perl::Critic;
149 Recommended usage for CPAN distributions:
155 use English qw(-no_match_vars);
157 if ( not $ENV{TEST_AUTHOR} ) {
158 my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.';
159 plan( skip_all => $msg );
162 eval { require Test::Perl::Critic; };
165 my $msg = 'Test::Perl::Critic required to criticise code';
166 plan( skip_all => $msg );
169 my $rcfile = File::Spec->catfile( 't', 'perlcriticrc' );
170 Test::Perl::Critic->import( -profile => $rcfile );
176 Test::Perl::Critic wraps the L<Perl::Critic> engine in a convenient
177 subroutine suitable for test programs written using the L<Test::More>
178 framework. This makes it easy to integrate coding-standards
179 enforcement into the build process. For ultimate convenience (at the
180 expense of some flexibility), see the L<criticism> pragma.
182 If you'd like to try L<Perl::Critic> without installing anything,
183 there is a web-service available at L<http://perlcritic.com>. The
184 web-service does not yet support all the configuration features that
185 are available in the native Perl::Critic API, but it should give you a
186 good idea of what it does. You can also invoke the perlcritic
187 web-service from the command line by doing an HTTP-post, such as one
190 $> POST http://perlcritic.com/perl/critic.pl < MyModule.pm
191 $> lwp-request -m POST http://perlcritic.com/perl/critic.pl < MyModule.pm
192 $> wget -q -O - --post-file=MyModule.pm http://perlcritic.com/perl/critic.pl
194 Please note that the perlcritic web-service is still alpha code. The
195 URL and interface to the service are subject to change.
203 =item critic_ok( $FILE [, $TEST_NAME ] )
205 Okays the test if Perl::Critic does not find any violations in $FILE.
206 If it does, the violations will be reported in the test diagnostics.
207 The optional second argument is the name of test, which defaults to
208 "Perl::Critic test for $FILE".
210 If you use this form, you should emit your own L<Test::More> plan first.
212 =item all_critic_ok( [ @DIRECTORIES ] )
214 Runs C<critic_ok()> for all Perl files beneath the given list of
215 C<@DIRECTORIES>. If C<@DIRECTORIES> is empty or not given, this
216 function tries to find all Perl files in the F<blib/> directory. If
217 the F<blib/> directory does not exist, then it tries the F<lib/>
218 directory. Returns true if all files are okay, or false if any file
221 This subroutine emits its own L<Test::More> plan, so you do not need
222 to specify an expected number of tests yourself.
224 =item all_code_files ( [@DIRECTORIES] )
226 B<DEPRECATED:> Use the C<all_perl_files> subroutine that is exported
227 by L<Perl::Critic::Utils> instead.
229 Returns a list of all the Perl files found beneath each DIRECTORY, If
230 @DIRECTORIES is an empty list, defaults to F<blib/>. If F<blib/> does
231 not exist, it tries F<lib/>. Skips any files in CVS or Subversion
238 =item * Any file that ends in F<.PL>, F<.pl>, F<.pm>, or F<.t>
240 =item * Any file that has a first line with a shebang containing 'perl'
248 L<Perl::Critic> is highly configurable. By default,
249 Test::Perl::Critic invokes Perl::Critic with it's default
250 configuration. But if you have developed your code against a custom
251 Perl::Critic configuration, you will want to configure
252 Test::Perl::Critic to do the same.
254 Any arguments given to the C<use> pragma will be passed into the
255 L<Perl::Critic> constructor. So if you have developed your code using
256 a custom F<~/.perlcriticrc> file, you can direct Test::Perl::Critic to
257 use a custom file too.
259 use Test::Perl::Critic (-profile => 't/perlcriticrc');
262 Now place a copy of your own F<~/.perlcriticrc> file in the distribution
263 as F<t/perlcriticrc>. Then, C<critic_ok()> will be run on all Perl
264 files in this distribution using this same Perl::Critic configuration.
265 See the L<Perl::Critic> documentation for details on the
266 F<.perlcriticrc> file format.
268 Any argument that is supported by the L<Perl::Critic> constructor can
269 be passed through this interface. For example, you can also set the
270 minimum severity level, or include & exclude specific policies like
273 use Test::Perl::Critic (-severity => 2, -exclude => ['RequireRcsKeywords']);
276 See the L<Perl::Critic> documentation for complete details on it's
277 options and arguments.
279 =head1 DIAGNOSTIC DETAILS
281 By default, Test::Perl::Critic displays basic information about each
282 Policy violation in the diagnostic output of the test. You can
283 customize the format and content of this information by using the
284 C<-verbose> option. This behaves exactly like the C<-verbose> switch
285 on the F<perlcritic> program. For example:
287 use Test::Perl::Critic (-verbose => 6);
291 use Test::Perl::Critic (-verbose => '%f: %m at %l');
293 If given a number, Test::Perl::Critic reports violations using one of
294 the predefined formats described below. If given a string, it is
295 interpreted to be an actual format specification. If the C<-verbose>
296 option is not specified, it defaults to 3.
298 Verbosity Format Specification
299 ----------- -------------------------------------------------------------
301 2 "%f: (%l:%c) %m\n",
302 3 "%m at %f line %l\n",
303 4 "%m at line %l, column %c. %e. (Severity: %s)\n",
304 5 "%f: %m at line %l, column %c. %e. (Severity: %s)\n",
305 6 "%m at line %l, near '%r'. (Severity: %s)\n",
306 7 "%f: %m at line %l near '%r'. (Severity: %s)\n",
307 8 "[%p] %m at line %l, column %c. (Severity: %s)\n",
308 9 "[%p] %m at line %l, near '%r'. (Severity: %s)\n",
309 10 "%m at line %l, column %c.\n %p (Severity: %s)\n%d\n",
310 11 "%m at line %l, near '%r'.\n %p (Severity: %s)\n%d\n"
312 Formats are a combination of literal and escape characters similar to
313 the way C<sprintf> works. See L<String::Format> for a full explanation
314 of the formatting capabilities. Valid escape characters are:
317 ------- ----------------------------------------------------------------
318 %c Column number where the violation occurred
319 %d Full diagnostic discussion of the violation
320 %e Explanation of violation or page numbers in PBP
321 %f Name of the file where the violation occurred.
322 %l Line number where the violation occurred
323 %m Brief description of the violation
324 %P Name of the Policy module that created the violation
325 %p Name of the Policy without the Perl::Critic::Policy:: prefix
326 %r The string of source code that caused the violation
327 %s The severity level of the violation
331 Despite the convenience of using a test script to enforce your coding
332 standards, there are some inherent risks when distributing those tests
333 to others. Since you don't know which version of L<Perl::Critic> the
334 end-user has and whether they have installed any additional Policy
335 modules, you can't really be sure that your code will pass the
336 Test::Perl::Critic tests on another machine.
338 B<For these reasons, we strongly advise you to make your perlcritic
339 tests optional, or exclude them from the distribution entirely.>
341 The recommended usage in the L<"SYNOPSIS"> section illustrates one way
342 to make your F<perlcritic.t> test optional. Also, you should B<not>
343 list Test::Perl::Critic as a requirement in your build script. These
344 tests are only relevant to the author and should not be a prerequisite
347 See L<http://www.chrisdolan.net/talk/index.php/2005/11/14/private-regression-tests/>
348 for an interesting discussion about Test::Perl::Critic and other types
349 of author-only regression tests.
356 =head1 PERFORMANCE HACKS
358 If you want a small performance boost, you can tell PPI to cache
359 results from previous parsing runs. Most of the processing time is in
360 Perl::Critic, not PPI, so the speedup is not huge (only about 20%).
361 Nonetheless, if your distribution is large, it's worth the effort.
363 Add a block of code like the following to your test program, probably
364 just before the call to C<all_critic_ok()>. Be sure to adjust the
365 path to the temp directory appropriately for your system.
368 my $cache_path = File::Spec->catdir(File::Spec->tmpdir,
369 "test-perl-critic-cache-$ENV{USER}");
370 if (!-d $cache_path) {
371 mkdir $cache_path, oct 700;
374 PPI::Cache->import(path => $cache_path);
376 We recommend that you do NOT use this technique for tests that will go
377 out to end-users. They're probably going to only run the tests once,
378 so they will not see the benefit of the caching but will still have
379 files stored in their temp directory.
383 If you find any bugs, please submit them to
384 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Perl-Critic>. Thanks.
389 L<Module::Starter::PBP>
397 Andy Lester, whose L<Test::Pod> module provided most of the code and
398 documentation for Test::Perl::Critic. Thanks, Andy.
402 Jeffrey Ryan Thalhammer <thaljef@cpan.org>
406 Copyright (c) 2005-2006 Jeffrey Ryan Thalhammer. All rights reserved.
408 This program is free software; you can redistribute it and/or modify
409 it under the same terms as Perl itself. The full text of this license
410 can be found in the LICENSE file included with this module.