1package Test::Builder::Module;
2
3use strict;
4
5use Test::Builder;
6
7require Exporter;
8our @ISA = qw(Exporter);
9
10our $VERSION = '1.302162';
11
12
13=head1 NAME
14
15Test::Builder::Module - Base class for test modules
16
17=head1 SYNOPSIS
18
19  # Emulates Test::Simple
20  package Your::Module;
21
22  my $CLASS = __PACKAGE__;
23
24  use parent 'Test::Builder::Module';
25  @EXPORT = qw(ok);
26
27  sub ok ($;$) {
28      my $tb = $CLASS->builder;
29      return $tb->ok(@_);
30  }
31
32  1;
33
34
35=head1 DESCRIPTION
36
37This is a superclass for L<Test::Builder>-based modules.  It provides a
38handful of common functionality and a method of getting at the underlying
39L<Test::Builder> object.
40
41
42=head2 Importing
43
44Test::Builder::Module is a subclass of L<Exporter> which means your
45module is also a subclass of Exporter.  @EXPORT, @EXPORT_OK, etc...
46all act normally.
47
48A few methods are provided to do the C<< use Your::Module tests => 23 >> part
49for you.
50
51=head3 import
52
53Test::Builder::Module provides an C<import()> method which acts in the
54same basic way as L<Test::More>'s, setting the plan and controlling
55exporting of functions and variables.  This allows your module to set
56the plan independent of L<Test::More>.
57
58All arguments passed to C<import()> are passed onto
59C<< Your::Module->builder->plan() >> with the exception of
60C<< import =>[qw(things to import)] >>.
61
62    use Your::Module import => [qw(this that)], tests => 23;
63
64says to import the functions C<this()> and C<that()> as well as set the plan
65to be 23 tests.
66
67C<import()> also sets the C<exported_to()> attribute of your builder to be
68the caller of the C<import()> function.
69
70Additional behaviors can be added to your C<import()> method by overriding
71C<import_extra()>.
72
73=cut
74
75sub import {
76    my($class) = shift;
77
78    Test2::API::test2_load() unless Test2::API::test2_in_preload();
79
80    # Don't run all this when loading ourself.
81    return 1 if $class eq 'Test::Builder::Module';
82
83    my $test = $class->builder;
84
85    my $caller = caller;
86
87    $test->exported_to($caller);
88
89    $class->import_extra( \@_ );
90    my(@imports) = $class->_strip_imports( \@_ );
91
92    $test->plan(@_);
93
94    local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
95    $class->Exporter::import(@imports);
96}
97
98sub _strip_imports {
99    my $class = shift;
100    my $list  = shift;
101
102    my @imports = ();
103    my @other   = ();
104    my $idx     = 0;
105    while( $idx <= $#{$list} ) {
106        my $item = $list->[$idx];
107
108        if( defined $item and $item eq 'import' ) {
109            push @imports, @{ $list->[ $idx + 1 ] };
110            $idx++;
111        }
112        else {
113            push @other, $item;
114        }
115
116        $idx++;
117    }
118
119    @$list = @other;
120
121    return @imports;
122}
123
124=head3 import_extra
125
126    Your::Module->import_extra(\@import_args);
127
128C<import_extra()> is called by C<import()>.  It provides an opportunity for you
129to add behaviors to your module based on its import list.
130
131Any extra arguments which shouldn't be passed on to C<plan()> should be
132stripped off by this method.
133
134See L<Test::More> for an example of its use.
135
136B<NOTE> This mechanism is I<VERY ALPHA AND LIKELY TO CHANGE> as it
137feels like a bit of an ugly hack in its current form.
138
139=cut
140
141sub import_extra { }
142
143=head2 Builder
144
145Test::Builder::Module provides some methods of getting at the underlying
146Test::Builder object.
147
148=head3 builder
149
150  my $builder = Your::Class->builder;
151
152This method returns the L<Test::Builder> object associated with Your::Class.
153It is not a constructor so you can call it as often as you like.
154
155This is the preferred way to get the L<Test::Builder> object.  You should
156I<not> get it via C<< Test::Builder->new >> as was previously
157recommended.
158
159The object returned by C<builder()> may change at runtime so you should
160call C<builder()> inside each function rather than store it in a global.
161
162  sub ok {
163      my $builder = Your::Class->builder;
164
165      return $builder->ok(@_);
166  }
167
168
169=cut
170
171sub builder {
172    return Test::Builder->new;
173}
174
1751;
176