]> git.vpit.fr Git - perl/modules/Test-Leaner.git/blob - lib/Test/Leaner.pm
Croak when importing symbols from Test::More that aren't in Test::Leaner
[perl/modules/Test-Leaner.git] / lib / Test / Leaner.pm
1 package Test::Leaner;
2
3 use 5.006;
4 use strict;
5 use warnings;
6
7 =head1 NAME
8
9 Test::Leaner - A slimmer Test::More for when you favor performance over completeness.
10
11 =head1 VERSION
12
13 Version 0.02
14
15 =cut
16
17 our $VERSION = '0.02';
18
19 =head1 SYNOPSIS
20
21     use Test::Leaner tests => 10_000;
22     for (1 .. 10_000) {
23      ...
24      is $one, 1, "checking situation $_";
25     }
26
27
28 =head1 DESCRIPTION
29
30 When profiling some L<Test::More>-based test script that contained about 10 000 unit tests, I realized that 60% of the time was spent in L<Test::Builder> itself, even though every single test actually involved a costly C<eval STRING>.
31
32 This module aims to be a partial replacement to L<Test::More> in those situations where you want to run a large number of simple tests.
33 Its functions behave the same as their L<Test::More> counterparts, except for the following differences :
34
35 =over 4
36
37 =item *
38
39 Stringification isn't forced on the test operands.
40 However, L</ok> honors C<'bool'> overloading, L</is> and L</is_deeply> honor C<'eq'> overloading (and just that one), L</isnt> honors C<'ne'> overloading, and L</cmp_ok> honors whichever overloading category corresponds to the specified operator.
41
42 =item *
43
44 L</pass>, L</fail>, L</ok>, L</is>, L</isnt>, L</like>, L</unlike>, L</cmp_ok> and L</is_deeply> are all guaranteed to return the truth value of the test.
45
46 =item *
47
48 C<isn't> (the sub C<t> in package C<isn>) is not aliased to L</isnt>.
49
50 =item *
51
52 L</like> and L</unlike> don't special case regular expressions that are passed as C<'/.../'> strings.
53 A string regexp argument is always treated as the source of the regexp, making C<like $text, $rx> and C<like $text, qr[$rx]> equivalent to each other and to C<cmp_ok $text, '=~', $rx> (and likewise for C<unlike>).
54
55 =item *
56
57 L</cmp_ok> throws an exception if the given operator isn't a valid Perl binary operator (except C<'='> and variants).
58 It also tests in scalar context, so C<'..'> will be treated as the flip-flop operator and not the range operator.
59
60 =item *
61
62 L</is_deeply> doesn't guard for memory cycles.
63 If the two first arguments present parallel memory cycles, the test may result in an infinite loop.
64
65 =item *
66
67 The tests don't output any kind of default diagnostic in case of failure ; the rationale being that if you have a large number of tests and a lot of them are failing, then you don't want to be flooded by diagnostics.
68 Moreover, this allows a much faster variant of L</is_deeply>.
69
70 =item *
71
72 C<use_ok>, C<require_ok>, C<can_ok>, C<isa_ok>, C<new_ok>, C<subtest>, C<explain>, C<TODO> blocks and C<todo_skip> are not implemented.
73
74 =back
75
76 =cut
77
78 use Exporter ();
79
80 my $main_process;
81
82 BEGIN {
83  $main_process = $$;
84
85  if ($] >= 5.008 and $INC{'threads.pm'}) {
86   my $use_ithreads = do {
87    require Config;
88    no warnings 'once';
89    $Config::Config{useithreads};
90   };
91   if ($use_ithreads) {
92    require threads::shared;
93    *THREADSAFE = sub () { 1 };
94   }
95  }
96  unless (defined &Test::Leaner::THREADSAFE) {
97   *THREADSAFE = sub () { 0 }
98  }
99 }
100
101 my ($TAP_STREAM, $DIAG_STREAM);
102
103 my ($plan, $test, $failed, $no_diag, $done_testing);
104
105 our @EXPORT = qw<
106  plan
107  skip
108  done_testing
109  pass
110  fail
111  ok
112  is
113  isnt
114  like
115  unlike
116  cmp_ok
117  is_deeply
118  diag
119  note
120  BAIL_OUT
121 >;
122
123 =head1 ENVIRONMENT
124
125 =head2 C<PERL_TEST_LEANER_USES_TEST_MORE>
126
127 If this environment variable is set, L<Test::Leaner> will replace its functions by those from L<Test::More>.
128 Moreover, the symbols that are imported when you C<use Test::Leaner> will be those from L<Test::More>, but you can still only import the symbols originally defined in L<Test::Leaner> (hence the functions from L<Test::More> that are not implemented in L<Test::Leaner> will not be imported).
129 If your version of L<Test::More> is too old and doesn't have some symbols (like L</note> or L</done_testing>), they will be replaced in L<Test::Leaner> by croaking stubs.
130
131 This may be useful if your L<Test::Leaner>-based test script fails and you want extra diagnostics.
132
133 =cut
134
135 sub _handle_import_args {
136  my @imports;
137
138  my $i = 0;
139  while ($i <= $#_) {
140   my $item = $_[$i];
141   my $splice;
142   if (defined $item) {
143    if ($item eq 'import') {
144     push @imports, @{ $_[$i+1] };
145     $splice  = 2;
146    } elsif ($item eq 'no_diag') {
147     lock $plan if THREADSAFE;
148     $no_diag = 1;
149     $splice  = 1;
150    }
151   }
152   if ($splice) {
153    splice @_, $i, $splice;
154   } else {
155    ++$i;
156   }
157  }
158
159  return @imports;
160 }
161
162 if ($ENV{PERL_TEST_LEANER_USES_TEST_MORE}) {
163  require Test::More;
164
165  my $leaner_stash = \%Test::Leaner::;
166  my $more_stash   = \%Test::More::;
167
168  my %stubbed;
169
170  for (@EXPORT) {
171   my $replacement = exists $more_stash->{$_} ? *{$more_stash->{$_}}{CODE}
172                                              : undef;
173   unless (defined $replacement) {
174    $stubbed{$_}++;
175    $replacement = sub {
176     @_ = ("$_ is not implemented in this version of Test::More");
177     goto &croak;
178    };
179   }
180   no warnings 'redefine';
181   $leaner_stash->{$_} = $replacement;
182  }
183
184  my $import = sub {
185   my $class = shift;
186
187   my @imports = &_handle_import_args;
188   @imports    = @EXPORT unless @imports;
189   my @test_more_imports;
190   for (@imports) {
191    if ($stubbed{$_}) {
192     my $pkg = caller;
193     no strict 'refs';
194     *{$pkg."::$_"} = $leaner_stash->{$_};
195    } elsif (/^!/ or !exists $more_stash->{$_} or exists $leaner_stash->{$_}) {
196     push @test_more_imports, $_;
197    } else {
198     # Croak for symbols in Test::More but not in Test::Leaner
199     Exporter::import($class, $_);
200    }
201   }
202
203   my $test_more_import = 'Test::More'->can('import');
204   return unless $test_more_import;
205
206   @_ = (
207    'Test::More',
208    @_,
209    import => \@test_more_imports,
210   );
211   {
212    lock $plan if THREADSAFE;
213    push @_, 'no_diag' if $no_diag;
214   }
215
216   goto $test_more_import;
217  };
218
219  no warnings 'redefine';
220  *import = $import;
221
222  return 1;
223 }
224
225 sub NO_PLAN  () { -1 }
226 sub SKIP_ALL () { -2 }
227
228 BEGIN {
229  if (THREADSAFE) {
230   threads::shared::share($_) for $plan, $test, $failed, $no_diag, $done_testing;
231  }
232
233  lock $plan if THREADSAFE;
234
235  $plan   = undef;
236  $test   = 0;
237  $failed = 0;
238 }
239
240 sub carp {
241  my $level = 1 + ($Test::Builder::Level || 0);
242  my @caller;
243  do {
244   @caller = caller $level--;
245  } while (!@caller and $level >= 0);
246  my ($file, $line) = @caller[1, 2];
247  warn @_, " at $file line $line.\n";
248 }
249
250 sub croak {
251  my $level = 1 + ($Test::Builder::Level || 0);
252  my @caller;
253  do {
254   @caller = caller $level--;
255  } while (!@caller and $level >= 0);
256  my ($file, $line) = @caller[1, 2];
257  die @_, " at $file line $line.\n";
258 }
259
260 sub _sanitize_comment {
261  $_[0] =~ s/\n+\z//;
262  $_[0] =~ s/#/\\#/g;
263  $_[0] =~ s/\n/\n# /g;
264 }
265
266 =head1 FUNCTIONS
267
268 The following functions from L<Test::More> are implemented and exported by default.
269
270 =head2 C<< plan [ tests => $count | 'no_plan' | skip_all => $reason ] >>
271
272 See L<Test::More/plan>.
273
274 =cut
275
276 sub plan {
277  my ($key, $value) = @_;
278
279  return unless $key;
280
281  lock $plan if THREADSAFE;
282
283  croak("You tried to plan twice") if defined $plan;
284
285  my $plan_str;
286
287  if ($key eq 'no_plan') {
288   croak("no_plan takes no arguments") if $value;
289   $plan       = NO_PLAN;
290  } elsif ($key eq 'tests') {
291   croak("Got an undefined number of tests") unless defined $value;
292   croak("You said to run 0 tests")          unless $value;
293   croak("Number of tests must be a positive integer.  You gave it '$value'")
294                                             unless $value =~ /^\+?[0-9]+$/;
295   $plan       = $value;
296   $plan_str   = "1..$value";
297  } elsif ($key eq 'skip_all') {
298   $plan       = SKIP_ALL;
299   $plan_str   = '1..0 # SKIP';
300   if (defined $value) {
301    _sanitize_comment($value);
302    $plan_str .= " $value" if length $value;
303   }
304  } else {
305   my @args = grep defined, $key, $value;
306   croak("plan() doesn't understand @args");
307  }
308
309  if (defined $plan_str) {
310   local $\;
311   print $TAP_STREAM "$plan_str\n";
312  }
313
314  exit 0 if $plan == SKIP_ALL;
315
316  return 1;
317 }
318
319 sub import {
320  my $class = shift;
321
322  my @imports = &_handle_import_args;
323
324  if (@_) {
325   local $Test::Builder::Level = ($Test::Builder::Level || 0) + 1;
326   &plan;
327  }
328
329  @_ = ($class, @imports);
330  goto &Exporter::import;
331 }
332
333 =head2 C<< skip $reason => $count >>
334
335 See L<Test::More/skip>.
336
337 =cut
338
339 sub skip {
340  my ($reason, $count) = @_;
341
342  lock $plan if THREADSAFE;
343
344  if (not defined $count) {
345   carp("skip() needs to know \$how_many tests are in the block")
346                                       unless defined $plan and $plan == NO_PLAN;
347   $count = 1;
348  } elsif ($count =~ /[^0-9]/) {
349   carp('skip() was passed a non-numeric number of tests.  Did you get the arguments backwards?');
350   $count = 1;
351  }
352
353  for (1 .. $count) {
354   ++$test;
355
356   my $skip_str = "ok $test # skip";
357   if (defined $reason) {
358    _sanitize_comment($reason);
359    $skip_str  .= " $reason" if length $reason;
360   }
361
362   local $\;
363   print $TAP_STREAM "$skip_str\n";
364  }
365
366  no warnings 'exiting';
367  last SKIP;
368 }
369
370 =head2 C<done_testing [ $count ]>
371
372 See L<Test::More/done_testing>.
373
374 =cut
375
376 sub done_testing {
377  my ($count) = @_;
378
379  lock $plan if THREADSAFE;
380
381  $count = $test unless defined $count;
382  croak("Number of tests must be a positive integer.  You gave it '$count'")
383                                                  unless $count =~ /^\+?[0-9]+$/;
384
385  if (not defined $plan or $plan == NO_PLAN) {
386   $plan         = $count; # $plan can't be NO_PLAN anymore
387   $done_testing = 1;
388   local $\;
389   print $TAP_STREAM "1..$plan\n";
390  } else {
391   if ($done_testing) {
392    @_ = ('done_testing() was already called');
393    goto &fail;
394   } elsif ($plan != $count) {
395    @_ = ("planned to run $plan tests but done_testing() expects $count");
396    goto &fail;
397   }
398  }
399
400  return 1;
401 }
402
403 =head2 C<ok $ok [, $desc ]>
404
405 See L<Test::More/ok>.
406
407 =cut
408
409 sub ok ($;$) {
410  my ($ok, $desc) = @_;
411
412  lock $plan if THREADSAFE;
413
414  ++$test;
415
416  my $test_str = "ok $test";
417  $ok or do {
418   $test_str   = "not $test_str";
419   ++$failed;
420  };
421  if (defined $desc) {
422   _sanitize_comment($desc);
423   $test_str .= " - $desc" if length $desc;
424  }
425
426  local $\;
427  print $TAP_STREAM "$test_str\n";
428
429  return $ok;
430 }
431
432 =head2 C<pass [ $desc ]>
433
434 See L<Test::More/pass>.
435
436 =cut
437
438 sub pass (;$) {
439  unshift @_, 1;
440  goto &ok;
441 }
442
443 =head2 C<fail [ $desc ]>
444
445 See L<Test::More/fail>.
446
447 =cut
448
449 sub fail (;$) {
450  unshift @_, 0;
451  goto &ok;
452 }
453
454 =head2 C<is $got, $expected [, $desc ]>
455
456 See L<Test::More/is>.
457
458 =cut
459
460 sub is ($$;$) {
461  my ($got, $expected, $desc) = @_;
462  no warnings 'uninitialized';
463  @_ = (
464   (not(defined $got xor defined $expected) and $got eq $expected),
465   $desc,
466  );
467  goto &ok;
468 }
469
470 =head2 C<isnt $got, $expected [, $desc ]>
471
472 See L<Test::More/isnt>.
473
474 =cut
475
476 sub isnt ($$;$) {
477  my ($got, $expected, $desc) = @_;
478  no warnings 'uninitialized';
479  @_ = (
480   ((defined $got xor defined $expected) or $got ne $expected),
481   $desc,
482  );
483  goto &ok;
484 }
485
486 my %binops = (
487  'or'  => 'or',
488  'xor' => 'xor',
489  'and' => 'and',
490
491  '||'  => 'hor',
492  ('//' => 'dor') x ($] >= 5.010),
493  '&&'  => 'hand',
494
495  '|'   => 'bor',
496  '^'   => 'bxor',
497  '&'   => 'band',
498
499  'lt'  => 'lt',
500  'le'  => 'le',
501  'gt'  => 'gt',
502  'ge'  => 'ge',
503  'eq'  => 'eq',
504  'ne'  => 'ne',
505  'cmp' => 'cmp',
506
507  '<'   => 'nlt',
508  '<='  => 'nle',
509  '>'   => 'ngt',
510  '>='  => 'nge',
511  '=='  => 'neq',
512  '!='  => 'nne',
513  '<=>' => 'ncmp',
514
515  '=~'  => 'like',
516  '!~'  => 'unlike',
517  ('~~' => 'smartmatch') x ($] >= 5.010),
518
519  '+'   => 'add',
520  '-'   => 'substract',
521  '*'   => 'multiply',
522  '/'   => 'divide',
523  '%'   => 'modulo',
524  '<<'  => 'lshift',
525  '>>'  => 'rshift',
526
527  '.'   => 'concat',
528  '..'  => 'flipflop',
529  '...' => 'altflipflop',
530  ','   => 'comma',
531  '=>'  => 'fatcomma',
532 );
533
534 my %binop_handlers;
535
536 sub _create_binop_handler {
537  my ($op) = @_;
538  my $name = $binops{$op};
539  croak("Operator $op not supported") unless defined $name;
540  {
541   local $@;
542   eval <<"IS_BINOP";
543 sub is_$name (\$\$;\$) {
544  my (\$got, \$expected, \$desc) = \@_;
545  \@_ = (scalar(\$got $op \$expected), \$desc);
546  goto &ok;
547 }
548 IS_BINOP
549   die $@ if $@;
550  }
551  $binop_handlers{$op} = do {
552   no strict 'refs';
553   \&{__PACKAGE__."::is_$name"};
554  }
555 }
556
557 =head2 C<like $got, $regexp_expected [, $desc ]>
558
559 See L<Test::More/like>.
560
561 =head2 C<unlike $got, $regexp_expected, [, $desc ]>
562
563 See L<Test::More/unlike>.
564
565 =cut
566
567 {
568  no warnings 'once';
569  *like   = _create_binop_handler('=~');
570  *unlike = _create_binop_handler('!~');
571 }
572
573 =head2 C<cmp_ok $got, $op, $expected [, $desc ]>
574
575 See L<Test::More/cmp_ok>.
576
577 =cut
578
579 sub cmp_ok ($$$;$) {
580  my ($got, $op, $expected, $desc) = @_;
581  my $handler = $binop_handlers{$op};
582  unless ($handler) {
583   local $Test::More::Level = ($Test::More::Level || 0) + 1;
584   $handler = _create_binop_handler($op);
585  }
586  @_ = ($got, $expected, $desc);
587  goto $handler;
588 }
589
590 =head2 C<is_deeply $got, $expected [, $desc ]>
591
592 See L<Test::More/is_deeply>.
593
594 =cut
595
596 BEGIN {
597  local $@;
598  if (eval { require Scalar::Util; 1 }) {
599   *_reftype = \&Scalar::Util::reftype;
600  } else {
601   # Stolen from Scalar::Util::PP
602   require B;
603   my %tmap = qw<
604    B::NULL   SCALAR
605
606    B::HV     HASH
607    B::AV     ARRAY
608    B::CV     CODE
609    B::IO     IO
610    B::GV     GLOB
611    B::REGEXP REGEXP
612   >;
613   *_reftype = sub ($) {
614    my $r = shift;
615
616    return undef unless length ref $r;
617
618    my $t = ref B::svref_2object($r);
619
620    return exists $tmap{$t} ? $tmap{$t}
621                            : length ref $$r ? 'REF'
622                                             : 'SCALAR'
623   }
624  }
625 }
626
627 sub _deep_ref_check {
628  my ($x, $y, $ry) = @_;
629
630  no warnings qw<numeric uninitialized>;
631
632  if ($ry eq 'ARRAY') {
633   return 0 unless $#$x == $#$y;
634
635   my ($ex, $ey);
636   for (0 .. $#$y) {
637    $ex = $x->[$_];
638    $ey = $y->[$_];
639
640    # Inline the beginning of _deep_check
641    return 0 if defined $ex xor defined $ey;
642
643    next if not(ref $ex xor ref $ey) and $ex eq $ey;
644
645    $ry = _reftype($ey);
646    return 0 if _reftype($ex) ne $ry;
647
648    return 0 unless $ry and _deep_ref_check($ex, $ey, $ry);
649   }
650
651   return 1;
652  } elsif ($ry eq 'HASH') {
653   return 0 unless keys(%$x) == keys(%$y);
654
655   my ($ex, $ey);
656   for (keys %$y) {
657    return 0 unless exists $x->{$_};
658    $ex = $x->{$_};
659    $ey = $y->{$_};
660
661    # Inline the beginning of _deep_check
662    return 0 if defined $ex xor defined $ey;
663
664    next if not(ref $ex xor ref $ey) and $ex eq $ey;
665
666    $ry = _reftype($ey);
667    return 0 if _reftype($ex) ne $ry;
668
669    return 0 unless $ry and _deep_ref_check($ex, $ey, $ry);
670   }
671
672   return 1;
673  } elsif ($ry eq 'SCALAR' or $ry eq 'REF') {
674   return _deep_check($$x, $$y);
675  }
676
677  return 0;
678 }
679
680 sub _deep_check {
681  my ($x, $y) = @_;
682
683  no warnings qw<numeric uninitialized>;
684
685  return 0 if defined $x xor defined $y;
686
687  # Try object identity/eq overloading first. It also covers the case where
688  # $x and $y are both undefined.
689  # If either $x or $y is overloaded but none has eq overloading, the test will
690  # break at that point.
691  return 1 if not(ref $x xor ref $y) and $x eq $y;
692
693  # Test::More::is_deeply happily breaks encapsulation if the objects aren't
694  # overloaded.
695  my $ry = _reftype($y);
696  return 0 if _reftype($x) ne $ry;
697
698  # Shortcut if $x and $y are both not references and failed the previous
699  # $x eq $y test.
700  return 0 unless $ry;
701
702  # We know that $x and $y are both references of type $ry, without overloading.
703  _deep_ref_check($x, $y, $ry);
704 }
705
706 sub is_deeply {
707  @_ = (
708   &_deep_check,
709   $_[2],
710  );
711  goto &ok;
712 }
713
714 sub _diag_fh {
715  my $fh = shift;
716
717  return unless @_;
718
719  lock $plan if THREADSAFE;
720  return if $no_diag;
721
722  my $msg = join '', map { defined($_) ? $_ : 'undef' } @_;
723  _sanitize_comment($msg);
724  return unless length $msg;
725
726  local $\;
727  print $fh "# $msg\n";
728
729  return 0;
730 };
731
732 =head2 C<diag @text>
733
734 See L<Test::More/diag>.
735
736 =cut
737
738 sub diag {
739  unshift @_, $DIAG_STREAM;
740  goto &_diag_fh;
741 }
742
743 =head2 C<note @text>
744
745 See L<Test::More/note>.
746
747 =cut
748
749 sub note {
750  unshift @_, $TAP_STREAM;
751  goto &_diag_fh;
752 }
753
754 =head2 C<BAIL_OUT [ $desc ]>
755
756 See L<Test::More/BAIL_OUT>.
757
758 =cut
759
760 sub BAIL_OUT {
761  my ($desc) = @_;
762
763  lock $plan if THREADSAFE;
764
765  my $bail_out_str = 'Bail out!';
766  if (defined $desc) {
767   _sanitize_comment($desc);
768   $bail_out_str  .= "  $desc" if length $desc; # Two spaces
769  }
770
771  local $\;
772  print $TAP_STREAM "$bail_out_str\n";
773
774  exit 255;
775 }
776
777 END {
778  if ($main_process == $$ and not $?) {
779   lock $plan if THREADSAFE;
780
781   if (defined $plan) {
782    if ($failed) {
783     $? = $failed <= 254 ? $failed : 254;
784    } elsif ($plan >= 0) {
785     $? = $test == $plan ? 0 : 255;
786    }
787    if ($plan == NO_PLAN) {
788     local $\;
789     print $TAP_STREAM "1..$test\n";
790    }
791   }
792  }
793 }
794
795 =pod
796
797 L<Test::Leaner> also provides some functions of its own, which are never exported.
798
799 =head2 C<tap_stream [ $fh ]>
800
801 Read/write accessor for the filehandle to which the tests are outputted.
802 On write, it also turns autoflush on onto C<$fh>.
803
804 Note that it can only be used as a write accessor before you start any thread, as L<threads::shared> cannot reliably share filehandles.
805
806 Defaults to C<STDOUT>.
807
808 =cut
809
810 sub tap_stream (;*) {
811  if (@_) {
812   $TAP_STREAM = $_[0];
813
814   my $fh = select $TAP_STREAM;
815   $|++;
816   select $fh;
817  }
818
819  return $TAP_STREAM;
820 }
821
822 tap_stream *STDOUT;
823
824 =head2 C<diag_stream [ $fh ]>
825
826 Read/write accessor for the filehandle to which the diagnostics are printed.
827 On write, it also turns autoflush on onto C<$fh>.
828
829 Just like L</tap_stream>, it can only be used as a write accessor before you start any thread, as L<threads::shared> cannot reliably share filehandles.
830
831 Defaults to C<STDERR>.
832
833 =cut
834
835 sub diag_stream (;*) {
836  if (@_) {
837   $DIAG_STREAM = $_[0];
838
839   my $fh = select $DIAG_STREAM;
840   $|++;
841   select $fh;
842  }
843
844  return $DIAG_STREAM;
845 }
846
847 diag_stream *STDERR;
848
849 =head2 C<THREADSAFE>
850
851 This constant evaluates to true if and only if L<Test::Leaner> is thread-safe, i.e. when this version of C<perl> is at least 5.8, has been compiled with C<useithreads> defined, and L<threads> has been loaded B<before> L<Test::Leaner>.
852 In that case, it also needs a working L<threads::shared>.
853
854 =head1 DEPENDENCIES
855
856 L<perl> 5.6.
857
858 L<Exporter>, L<Test::More>.
859
860 =head1 AUTHOR
861
862 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
863
864 You can contact me by mail or on C<irc.perl.org> (vincent).
865
866 =head1 BUGS
867
868 Please report any bugs or feature requests to C<bug-test-leaner at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Leaner>.
869 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
870
871 =head1 SUPPORT
872
873 You can find documentation for this module with the perldoc command.
874
875     perldoc Test::Leaner
876
877 =head1 COPYRIGHT & LICENSE
878
879 Copyright 2010,2011 Vincent Pit, all rights reserved.
880
881 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
882
883 =cut
884
885 1; # End of Test::Leaner