File Coverage

lib/Test/UniqueTestNames.pm
Criterion Covered Total %
statement 42 42 100.0
branch 8 8 100.0
condition n/a
subroutine 8 8 100.0
pod 1 1 100.0
total 59 59 100.0


line stmt bran cond sub pod time code
1             package Test::UniqueTestNames;
2              
3             =head1 NAME
4              
5             Test::UniqueTestNames - Make sure all of your tests have unique names
6              
7             =head1 VERSION
8              
9             Version 0.04
10              
11             =head1 SYNOPSIS
12              
13             For scripts that have no plan:
14              
15             use Test::UniqueTestNames;
16              
17             that's it, you don't need to do anything else.
18              
19             For scripts that have a plan, like this:
20              
21             use Test::More tests => x;
22              
23             change to
24              
25             use Test::More tests => x + 1;
26             use Test::UniqueTestNames;
27              
28             =head1 DESCRIPTION
29              
30             Test names are useful in assessing the contents of a test file. They're also useful in debugging. And when a test breaks, it's much easier to figure out what test broke if the test names are unique. This module checks the names of every test to make sure that they're all unique. If there are any tests that have duplicate names, it wil give a "not ok" and diagnostics of which test names have been used for multiple tests.
31              
32             Test names aren't required by most testing modules, but B. You can change that behavior by importing C.
33              
34             Specifically, this module is useful in the situation where tests are run in a loop, such as these:
35              
36             for( @fixture_data ) {
37             my( $input, $output ) = @$_;
38              
39             ok( Some::Class->method( $input ), "...and the method works"; # test name will be the same each time
40              
41             is( Some::Class->method( $input ), $output, "...and the method works with $input"; # names could be the same
42             # if there is a duplicate in $input
43             }
44              
45             This test is similar in most respects to L.
46              
47             =head1 CAVEATS
48              
49             Some tests generate their own test names, and thus shouldn't be counted as failures when they have non-unique test names. This currently only applies to Test::More's C.
50              
51             =cut
52              
53 11     11   8478 use warnings;
  11         23  
  11         516  
54 11     11   71 use strict;
  11         19  
  11         436  
55              
56 11     11   72 use base 'Test::Builder::Module';
  11         23  
  11         1176  
57 11     11   4979 use Test::UniqueTestNames::Tracker;
  11         658  
  11         858  
58 11     11   13125 use Hook::LexWrap;
  11         19177  
  11         65  
59              
60             my $CLASS = __PACKAGE__;
61              
62 11         6485 use vars qw(
63             @EXPORT_OK @ISA $VERSION
64             $do_end_test
65             @non_unique_tests
66 11     11   535 );
  11         19  
67              
68             $VERSION = '0.04';
69              
70             #require Exporter;
71             #@ISA = qw( Exporter );
72              
73             @EXPORT_OK = qw(
74             had_unique_test_names
75             unnamed_ok
76             );
77              
78             $do_end_test = 0;
79              
80             sub import {
81 11     11   724 $do_end_test = 1;
82 11 100       22 Test::UniqueTestNames::Tracker->unnamed_ok(1) if grep { $_ eq 'unnamed_ok' } @_;
  23         93  
83              
84 11         545 goto &Exporter::import;
85             }
86              
87             # idea courtesty Schwern:
88             # http://www.mail-archive.com/perl-qa@perl.org/msg06368.html
89             wrap 'Test::Builder::ok', post => sub {
90             my($self, $ok, $name) = @_;
91             local $Test::Builder::Level = $Test::Builder::Level + 1;
92             my ( $package, $file, $line ) = $self->caller();
93              
94             Test::UniqueTestNames::Tracker->add_test( $name, $line );
95             };
96              
97             # the END block must be after the "use Test::Builder" to make sure it runs
98             # before Test::Builder's end block
99             # only run the test if there have been other tests
100             END {
101             had_unique_test_names() if $do_end_test;
102             }
103              
104             =head1 EXPORTED FUNCTIONS
105              
106             =head2 had_unique_test_names()
107              
108             This checks to see that all tests had unique names. Usually you will not call this explicitly as it is called automatically when your script finishes.
109              
110             =cut
111              
112             sub had_unique_test_names {
113 11     11 1 411 $do_end_test = 0;
114              
115 11         272 my $builder = $CLASS->builder;
116              
117 11         87 my ( $ok, $diag );
118 11 100       22 if( @{ Test::UniqueTestNames::Tracker->failing_tests } > 0 ) {
  11         57  
119 8         14 $ok = 0;
120              
121 8         15 my $num_failures = scalar @{ Test::UniqueTestNames::Tracker->failing_tests };
  8         34  
122 8         45 $diag = "The following $num_failures test name(s) were not unique:\n"
123             . "Test Name Occurrences Line(s)\n"
124             . "----------------------------------------------------------------";
125              
126 8         16 for my $test ( @{ Test::UniqueTestNames::Tracker->failing_tests } ) {
  8         36  
127              
128             # add the line numbers in sorted order
129 13         46 my $line_numbers = $test->line_numbers;
130 13         25 my @line_number_output;
131 13         65 for( sort keys %$line_numbers ) {
132 25 100       62 if( $line_numbers->{ $_ } > 1 ){
133 4         27 push @line_number_output, $_ . sprintf( " (%d times)", $line_numbers->{ $_ } );
134             }
135             else {
136 21         47 push @line_number_output, $_;
137             }
138              
139             }
140              
141 13         66 $diag .= sprintf(
142             "\n%-43s %d %s",
143             $test->short_name,
144             $test->occurrences,
145             join(', ', @line_number_output),
146             );
147             }
148             }
149             else {
150 3         5 $ok = 1;
151             }
152              
153             # TODO this should be exportable so that we don't have to set the line number manually,
154             # but use_ok seems to be interferring.
155             #$test_line_number = __LINE__ + 1;
156 11 100       60 $builder->ok($ok, 'all test names unique') || $builder->diag($diag);
157             }
158              
159             1;
160              
161             =head1 AUTHOR
162              
163             Josh Heumann, C<< >>
164              
165             =head1 BUGS
166              
167             =head2 Using with Test::Exception
168              
169             This module currently throws a warning when used with L. This is due to a bug in L, and a patch has been submitted to correct the problem.
170              
171             Please report any bugs or feature requests to C, or through
172             the web interface at L. I will be notified, and then you'll
173             automatically be notified of progress on your bug as I make changes.
174              
175             =head1 SEE ALSO
176              
177             L
178              
179             =head1 COPYRIGHT & LICENSE
180              
181             Copyright 2008 Josh Heumann, all rights reserved.
182              
183             This program is free software; you can redistribute it and/or modify it
184             under the same terms as Perl itself.
185              
186             =cut