<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package Test::Builder::Module;

use strict;

use Test::Builder;

require Exporter;
our @ISA = qw(Exporter);

our $VERSION = '1.302199';


=head1 NAME

Test::Builder::Module - Base class for test modules

=head1 SYNOPSIS

  # Emulates Test::Simple
  package Your::Module;

  my $CLASS = __PACKAGE__;

  use parent 'Test::Builder::Module';
  @EXPORT = qw(ok);

  sub ok ($;$) {
      my $tb = $CLASS-&gt;builder;
      return $tb-&gt;ok(@_);
  }
  
  1;


=head1 DESCRIPTION

This is a superclass for L&lt;Test::Builder&gt;-based modules.  It provides a
handful of common functionality and a method of getting at the underlying
L&lt;Test::Builder&gt; object.


=head2 Importing

Test::Builder::Module is a subclass of L&lt;Exporter&gt; which means your
module is also a subclass of Exporter.  @EXPORT, @EXPORT_OK, etc...
all act normally.

A few methods are provided to do the C&lt;&lt; use Your::Module tests =&gt; 23 &gt;&gt; part
for you.

=head3 import

Test::Builder::Module provides an C&lt;import()&gt; method which acts in the
same basic way as L&lt;Test::More&gt;'s, setting the plan and controlling
exporting of functions and variables.  This allows your module to set
the plan independent of L&lt;Test::More&gt;.

All arguments passed to C&lt;import()&gt; are passed onto 
C&lt;&lt; Your::Module-&gt;builder-&gt;plan() &gt;&gt; with the exception of 
C&lt;&lt; import =&gt;[qw(things to import)] &gt;&gt;.

    use Your::Module import =&gt; [qw(this that)], tests =&gt; 23;

says to import the functions C&lt;this()&gt; and C&lt;that()&gt; as well as set the plan
to be 23 tests.

C&lt;import()&gt; also sets the C&lt;exported_to()&gt; attribute of your builder to be
the caller of the C&lt;import()&gt; function.

Additional behaviors can be added to your C&lt;import()&gt; method by overriding
C&lt;import_extra()&gt;.

=cut

sub import {
    my($class) = shift;

    Test2::API::test2_load() unless Test2::API::test2_in_preload();

    # Don't run all this when loading ourself.
    return 1 if $class eq 'Test::Builder::Module';

    my $test = $class-&gt;builder;

    my $caller = caller;

    $test-&gt;exported_to($caller);

    $class-&gt;import_extra( \@_ );
    my(@imports) = $class-&gt;_strip_imports( \@_ );

    $test-&gt;plan(@_);

    local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
    $class-&gt;Exporter::import(@imports);
}

sub _strip_imports {
    my $class = shift;
    my $list  = shift;

    my @imports = ();
    my @other   = ();
    my $idx     = 0;
    while( $idx &lt;= $#{$list} ) {
        my $item = $list-&gt;[$idx];

        if( defined $item and $item eq 'import' ) {
            push @imports, @{ $list-&gt;[ $idx + 1 ] };
            $idx++;
        }
        else {
            push @other, $item;
        }

        $idx++;
    }

    @$list = @other;

    return @imports;
}

=head3 import_extra

    Your::Module-&gt;import_extra(\@import_args);

C&lt;import_extra()&gt; is called by C&lt;import()&gt;.  It provides an opportunity for you
to add behaviors to your module based on its import list.

Any extra arguments which shouldn't be passed on to C&lt;plan()&gt; should be
stripped off by this method.

See L&lt;Test::More&gt; for an example of its use.

B&lt;NOTE&gt; This mechanism is I&lt;VERY ALPHA AND LIKELY TO CHANGE&gt; as it
feels like a bit of an ugly hack in its current form.

=cut

sub import_extra { }

=head2 Builder

Test::Builder::Module provides some methods of getting at the underlying
Test::Builder object.

=head3 builder

  my $builder = Your::Class-&gt;builder;

This method returns the L&lt;Test::Builder&gt; object associated with Your::Class.
It is not a constructor so you can call it as often as you like.

This is the preferred way to get the L&lt;Test::Builder&gt; object.  You should
I&lt;not&gt; get it via C&lt;&lt; Test::Builder-&gt;new &gt;&gt; as was previously
recommended.

The object returned by C&lt;builder()&gt; may change at runtime so you should
call C&lt;builder()&gt; inside each function rather than store it in a global.

  sub ok {
      my $builder = Your::Class-&gt;builder;

      return $builder-&gt;ok(@_);
  }


=cut

sub builder {
    return Test::Builder-&gt;new;
}

=head1 SEE ALSO

L&lt;&lt; Test2::Manual::Tooling::TestBuilder &gt;&gt; describes the improved
options for writing testing modules provided by L&lt;&lt; Test2 &gt;&gt;.

=cut

1;
</pre></body></html>