File Coverage

blib/lib/Test/Exports.pm
Criterion Covered Total %
statement 57 57 100.0
branch 12 12 100.0
condition 8 10 80.0
subroutine 10 10 100.0
pod 5 5 100.0
total 92 94 97.8


line stmt bran cond sub pod time code
1             package Test::Exports;
2              
3             =head1 NAME
4              
5             Test::Exports - Test that modules export the right symbols
6              
7             =head1 SYNOPSIS
8              
9             use Test::More;
10             use Test::Exports;
11            
12             require_ok "My::Module" or BAIL_OUT "can't load module";
13              
14             import_ok "My::Module", [], "default import OK";
15             is_import qw/foo bar/, "My::Module", "imports subs";
16              
17             new_import_pkg;
18              
19             import_ok "My::Module", ["foo"], "named import OK";
20             is_import "foo", "My::Module", "imports foo";
21             cant_ok "bar", "doesn't import bar";
22              
23             =head1 DESCRIPTION
24              
25             This module provides simple test functions for testing other modules'
26             C methods. Testing is currently limited to checking which subs
27             have been imported.
28              
29             In order to keep different calls to C<< ->import >> separate,
30             Test::Exports performs these calls from a private package. The
31             symbol-testing functions then test whether or not symbols are present in
32             this private package, ensuring none of this interferes with your test
33             script itself.
34              
35             =head1 FUNCTIONS
36              
37             These are all exported by default, as is usual with testing modules.
38              
39             =cut
40              
41 4     4   268384 use warnings;
  4         11  
  4         161  
42 4     4   24 use strict;
  4         14  
  4         142  
43              
44 4     4   35 use B;
  4         8  
  4         245  
45              
46 4     4   4663 use parent "Test::Builder::Module";
  4         1537  
  4         21  
47              
48             our @EXPORT = qw/
49             new_import_pkg
50             import_ok import_nok
51             is_import cant_ok
52             /;
53              
54             our $VERSION = "1";
55              
56             my $CLASS = __PACKAGE__;
57              
58             =head2 C
59              
60             Create a new package to perform imports into. This is useful when you
61             want to test C<< ->import >> with different arguments: otherwise you'd
62             need to find some way of going back and clearing up the imports from the
63             last call.
64              
65             This returns the name of the new package (which will look like
66             C) in case you need it.
67              
68             =cut
69              
70             my $counter = "AAAAA";
71             my $PKG;
72              
73 11     11 1 19371 sub new_import_pkg { $counter++; $PKG = "$CLASS\::Test$counter" }
  11         57  
74             new_import_pkg;
75              
76             =head2 C
77              
78             Call C<< $module->import >> from the current testing package, passing
79             C<@args>, and check the call succeeded. 'Success' means not throwing an
80             exception: C doesn't care if C returns false, so neither do
81             we.
82              
83             C<@args> defaults to the empty list; C<$name> defaults to something
84             sensible.
85              
86             =cut
87              
88             sub import_ok {
89 8     8 1 24831 my ($mod, $args, $msg) = @_;
90 8         47 my $tb = $CLASS->builder;
91              
92 8         88 local $" = ", ";
93 8   100     34 $args ||= [];
94 8   66     38 $msg ||= "$mod->import(@$args) succeeds";
95              
96 8         32 my $code = "package $PKG; $mod->import(\@\$args); 1";
97              
98             #$tb->diag($code);
99              
100 8         727 my $eval = eval $code;
101              
102 8 100       88 $tb->ok($eval, $msg) or $tb->diag(<
103             $mod->import(@$args) failed:
104             $@
105             DIAG
106             }
107              
108             =head2 C
109              
110             Call C<< $module->import(@args) >> and expect it to throw an exception.
111             Defaults as for L.
112              
113             =cut
114              
115             sub import_nok {
116 8     8 1 29728 my ($mod, $args, $msg) = @_;
117 8         43 my $tb = $CLASS->builder;
118              
119 8         53 local $" = ", ";
120 8   100     38 $args ||= [];
121 8   66     33 $msg ||= "$mod->import(@$args) fails";
122              
123 8         759 my $eval = eval "package $PKG; $mod->import(\@\$args); 1";
124              
125 8 100       116 $tb->ok(!$eval, $msg) or $tb->diag(<
126             $mod->import(@$args) succeeded where it should have failed.
127             DIAG
128             }
129              
130             =head2 C
131              
132             For each name in C<@subs>, check that the current testing package has a
133             sub by that name and that it is the same as the equinominal sub in the
134             C<$module> package.
135              
136             Neither C<$module> nor C<$name> are optional.
137              
138             =cut
139              
140             sub is_import {
141 7     7 1 26220 my $msg = pop;
142 7         14 my $from = pop;
143 7         45 my $tb = $CLASS->builder;
144              
145 7         51 my @nok;
146              
147 7         19 for (@_) {
148 9         25 my $to = "$PKG\::$_";
149              
150 4     4   3167 no strict 'refs';
  4         14  
  4         1731  
151 9 100       97 unless (defined &$to) {
152 3         11 push @nok, <
153             \&$to is not defined
154             DIAG
155 3         10 next;
156             }
157              
158 6 100       22 \&$to == \&{"$from\::$_"} or push @nok, <
  6         58  
159             \&$to is not imported correctly
160             DIAG
161             }
162              
163 7 100       62 my $ok = $tb->ok(!@nok, $msg) or $tb->diag(<
164             Expected subs to be imported from $from:
165             DIAG
166 7         1565 $tb->diag($_) for @nok;
167 7         157 return $ok;
168             }
169              
170             =head2 C
171              
172             For each sub in @subs, check that a sub of that name does not exist in
173             the current testing package. If one is found the diagnostic will
174             indicate where it was originally defined, to help track down the stray
175             export.
176              
177             =cut
178              
179             sub cant_ok {
180 4     4 1 11741 my $msg = pop;
181 4         19 my $tb = $CLASS->builder;
182              
183 4         24 my @nok;
184              
185 4         12 for (@_) {
186 6         44 my $can = $PKG->can($_);
187 6 100       649 $can and push @nok, $_;
188             }
189              
190 4         30 my $ok = $tb->ok(!@nok, $msg);
191            
192 4         487 for (@nok) {
193 4         96 my $from = B::svref_2object($PKG->can($_))->GV->STASH->NAME;
194 4         31 $tb->diag(<
195             \&$PKG\::$_ is imported from $from
196             DIAG
197             }
198              
199 4         96 return $ok;
200             }
201              
202             =head1 TODO
203              
204             =head2 C
205              
206             Currently this just checks that C<\&Our::Pkg::sub == \&Your::Pkg::sub>,
207             which means
208              
209             =over 4
210              
211             =item *
212              
213             it is impossible to test for exports which have been renamed, and
214              
215             =item *
216              
217             we can't be sure the sub originally came from Your::Pkg: it may have
218             been exported into both packages from somewhere else.
219              
220             =back
221              
222             It would be good to fix at least the former.
223              
224             =head1 AUTHOR
225              
226             Ben Morrow
227              
228             =head1 BUGS
229              
230             Please report any bugs to .
231              
232             =head1 COPYRIGHT
233              
234             Copyright 2010 Ben Morrow.
235              
236             Redistribution and use in source and binary forms, with or without
237             modification, are permitted provided that the following conditions are met:
238              
239             =over 4
240              
241             =item *
242              
243             Redistributions of source code must retain the above copyright
244             notice, this list of conditions and the following disclaimer.
245              
246             =item *
247              
248             Redistributions in binary form must reproduce the above copyright
249             notice, this list of conditions and the following disclaimer in the
250             documentation and/or other materials provided with the distribution.
251              
252             =back
253              
254             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
255             ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
256             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
257             DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
258             DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
259             (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
260             LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
261             ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262             (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
263             SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
264              
265             =cut
266              
267             1;