Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,145 @@
package Test2::Manual::Tooling::FirstTool;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::FirstTool - Write your first tool with Test2.
=head1 DESCRIPTION
This tutorial will help you write your very first tool by cloning the C<ok()>
tool.
=head1 COMPLETE CODE UP FRONT
package Test2::Tools::MyOk;
use strict;
use warnings;
use Test2::API qw/context/;
use base 'Exporter';
our @EXPORT = qw/ok/;
sub ok($;$@) {
my ($bool, $name, @diag) = @_;
my $ctx = context();
return $ctx->pass_and_release($name) if $bool;
return $ctx->fail_and_release($name, @diag);
}
1;
=head1 LINE BY LINE
=over 4
=item sub ok($;$@) {
In this case we are emulating the C<ok()> function exported by
L<Test2::Tools::Basic>.
C<ok()> and similar test tools use prototypes to enforce argument parsing. Your
test tools do not necessarily need prototypes, like any perl function you need
to make the decision based on how it is used.
The prototype requires at least 1 argument, which will
be forced into a scalar context. The second argument is optional, and is also
forced to be scalar, it is the name of the test. Any remaining arguments are
treated as diagnostics messages that will only be used if the test failed.
=item my ($bool, $name, @diag) = @_;
This line does not need much explanation, we are simply grabbing the args.
=item my $ctx = context();
This is a vital line in B<ALL> tools. The context object is the primary API for
test tools. You B<MUST> get a context if you want to issue any events, such as
making assertions. Further, the context is responsible for making sure failures
are attributed to the correct file and line number.
B<Note:> A test function B<MUST> always release the context when it is done,
you cannot simply let it fall out of scope and be garbage collected. Test2 does
a pretty good job of yelling at you if you make this mistake.
B<Note:> You B<MUST NOT> ever store or pass around a I<real> context object. If
you wish to hold on to a context for any reason you must use clone to make a
copy C<< my $copy = $ctx->clone >>. The copy may be passed around or stored,
but the original B<MUST> be released when you are done with it.
=item return $ctx->pass_and_release($name) if $bool;
When C<$bool> is true, this line uses the context object to issue a
L<Test2::Event::Pass> event. Along with issuing the event this will also
release the context object and return true.
This is short form for:
if($bool) {
$ctx->pass($name);
$ctx->release;
return 1;
}
=item return $ctx->fail_and_release($name, @diag);
This line issues a L<Test2::Event::Fail> event, releases the context object,
and returns false. The fail event will include any diagnostics messages from
the C<@diag> array.
This is short form for:
$ctx->fail($name, @diag);
$ctx->release;
return 0;
=back
=head1 CONTEXT OBJECT DOCUMENTATION
L<Test2::API::Context> is the place to read up on what methods the context
provides.
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,138 @@
package Test2::Manual::Tooling::Formatter;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Formatter - How to write a custom formatter, in our
case a JSONL formatter.
=head1 DESCRIPTION
This tutorial explains a minimal formatter that outputs each event as a json
string on its own line. A true formatter will probably be significantly more
complicated, but this will give you the basics needed to get started.
=head1 COMPLETE CODE UP FRONT
package Test2::Formatter::MyFormatter;
use strict;
use warnings;
use JSON::MaybeXS qw/encode_json/;
use base qw/Test2::Formatter/;
sub new { bless {}, shift }
sub encoding {};
sub write {
my ($self, $e, $num, $f) = @_;
$f ||= $e->facet_data;
print encode_json($f), "\n";
}
1;
=head1 LINE BY LINE
=over 4
=item use base qw/Test2::Formatter/;
All formatters should inherit from L<Test2::Formatter>.
=item sub new { bless {}, shift }
Formatters need to be instantiable objects, this is a minimal C<new()> method.
=item sub encoding {};
For this example we leave this sub empty. In general you should implement this
sub to make sure you honor situations where the encoding is set. L<Test2::V0>
itself will try to set the encoding to UTF8.
=item sub write { ... }
The C<write()> method is the most important, each event is sent here.
=item my ($self, $e, $num, $f) = @_;
The C<write()> method receives 3 or 4 arguments, the fourth is optional.
=over 4
=item $self
The formatter itself.
=item $e
The event being written
=item $num
The most recent assertion number. If the event being processed is an assertion
then this will have been bumped by 1 since the last call to write. For non
assertions this number is set to the most recent assertion.
=item $f
This MAY be a hashref containing all the facet data from the event. More often
then not this will be undefined. This is only set if the facet data was needed
by the hub, and it usually is not.
=back
=item $f ||= $e->facet_data;
We want to dump the event facet data. This will set C<$f> to the facet data
unless we already have the facet data.
=item print encode_json($f), "\n";
This line prints the JSON encoded facet data, and a newline.
=back
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,140 @@
package Test2::Manual::Tooling::Nesting;
use strict;
use warnings;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Nesting - Tutorial for using other tools within your
own.
=head1 DESCRIPTION
Sometimes you find yourself writing the same test pattern over and over, in
such cases you may want to encapsulate the logic in a new test function that
calls several tools together. This sounds easy enough, but can cause headaches
if not done correctly.
=head1 NAIVE WAY
Lets say you find yourself writing the same test pattern over and over for multiple objects:
my $obj1 = $class1->new;
is($obj1->foo, 'foo', "got foo");
is($obj1->bar, 'bar', "got bar");
my $obj2 = $class1->new;
is($obj2->foo, 'foo', "got foo");
is($obj2->bar, 'bar', "got bar");
... 10x more times for classes 2-12
The naive way to do this is to write a C<check_class()> function like this:
sub check_class {
my $class = shift;
my $obj = $class->new;
is($obj->foo, 'foo', "got foo");
is($obj->bar, 'bar', "got bar");
}
check_class($class1);
check_class($class2);
check_class($class3);
...
This will appear to work fine, and you might not notice any problems,
I<so long as the tests are passing.>
=head2 WHATS WRONG WITH IT?
The problems with the naive approach become obvious if things start to fail.
The diagnostics that tell you what file and line the failure occurred on will be
wrong. The failure will be reported to the line I<inside> C<check_class>, not
to the line where C<check_class()> was called. This is problem because it
leaves you with no idea which class is failing.
=head2 HOW TO FIX IT
Luckily this is extremely easy to fix. You need to acquire a context object at
the start of your function, and release it at the end... yes it is that simple.
use Test2::API qw/context/;
sub check_class {
my $class = shift;
my $ctx = context();
my $obj = $class->new;
is($obj->foo, 'foo', "got foo");
is($obj->bar, 'bar', "got bar");
$ctx->release;
}
See, that was easy. With these 2 additional lines we know have proper file+line
reporting. The nested tools will find the context we acquired here, and know to
use it's file and line numbers.
=head3 THE OLD WAY (DO NOT DO THIS ANYMORE)
With L<Test::Builder> there was a global variables called
C<$Test::Builder::Level> which helped solve this problem:
sub check_class {
my $class = shift;
local $Test::Builder::Level = $Test::Builder::Level + 1;
my $obj = $class->new;
is($obj->foo, 'foo', "got foo");
is($obj->bar, 'bar', "got bar");
}
This variable worked well enough (and will still work) but was not very
discoverable. Another problem with this variable is that it becomes cumbersome
if you have a more deeply nested code structure called the nested tools, you
might need to count stack frames, and hope they never change due to a third
party module. The context solution has no such caveats.
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,108 @@
package Test2::Manual::Tooling::Plugin::TestExit;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Plugin::TestExit - How to safely add pre-exit
behaviors.
=head1 DESCRIPTION
This describes the correct/safe way to add pre-exit behaviors to tests via a
custom plugin.
The naive way to attempt this would be to add an C<END { ... }> block. That can
work, and may not cause problems.... On the other hand there are a lot of ways
that can bite you. Describing all the potential problems of an END block, and
how it might conflict with Test2 (Which has its own END block) is beyond the
scope of this document.
=head1 COMPLETE CODE UP FRONT
package Test2::Plugin::MyPlugin;
use Test2::API qw{test2_add_callback_exit};
sub import {
my $class = shift;
test2_add_callback_exit(sub {
my ($ctx, $orig_code, $new_exit_code_ref) = @_;
return if $orig_code == 42;
$$new_exit_code_ref = 42;
});
}
1;
=head1 LINE BY LINE
=over 4
=item use Test2::API qw{test2_add_callback_exit};
This imports the C<(test2_add_callback_exit)> callback.
=item test2_add_callback_exit(sub { ... });
This adds our callback to be called before exiting.
=item my ($ctx, $orig_code, $new_exit_code_ref) = @_
The callback gets 3 arguments. First is a context object you may use. The
second is the original exit code of the C<END> block Test2 is using. The third
argument is a scalar reference which you may use to get the current exit code,
or set a new one.
=item return if $orig_code == 42
This is a short-cut to do nothing if the original exit code was already 42.
=item $$new_exit_code_ref = 42
This changes the exit code to 42.
=back
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,121 @@
package Test2::Manual::Tooling::Plugin::TestingDone;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Plugin::TestingDone - Run code when the test file is
finished, or when done_testing is called.
=head1 DESCRIPTION
This is a way to add behavior to the end of a test file. This code is run
either when done_testing() is called, or when the test file has no more
run-time code to run.
When triggered by done_testing() this will be run BEFORE the plan is calculated
and sent. This means it IS safe to make test assertions in this callback.
=head1 COMPLETE CODE UP FRONT
package Test2::Plugin::MyPlugin;
use Test2::API qw{test2_add_callback_testing_done};
sub import {
my $class = shift;
test2_add_callback_testing_done(sub {
ok(!$some_global, '$some_global was not set');
print "The test file is done, or done_testing was just called\n"
});
}
1;
=head1 LINE BY LINE
=over 4
=item use Test2::API qw{test2_add_callback_testing_done};
This imports the C<test2_add_callback_testing_done()> callback.
=item test2_add_callback_testing_done(sub { ... });
This adds our callback to be called when testing is done.
=item ok(!$some_global, '$some_global was not set')
It is safe to make assertions in this type of callback. This code simply
asserts that some global was never set over the course of the test.
=item print "The test file is done, or done_testing was just called\n"
This prints a message when the callback is run.
=back
=head1 UNDER THE HOOD
Before test2_add_callback_testing_done() this kind of thing was still possible,
but it was hard to get right, here is the code to do it:
test2_add_callback_post_load(sub {
my $stack = test2_stack();
# Insure we have at least one hub, but we do not necessarily want the
# one this returns.
$stack->top;
# We want the root hub, not the top one.
my ($root) = Test2::API::test2_stack->all;
# Make sure the hub does not believe nothing has happened.
$root->set_active(1);
# Now we can add our follow-up code
$root->follow_up(sub {
# Your callback code here
});
});
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,94 @@
package Test2::Manual::Tooling::Plugin::ToolCompletes;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Plugin::ToolCompletes - How to add behaviors that occur
when a tool completes work.
=head1 DESCRIPTION
This tutorial helps you understand how to add behaviors that occur when a tool
is done with its work. All tools need to acquire and then release a context,
for this tutorial we make use of the release hooks that are called every time a
tool releases the context object.
=head1 COMPLETE CODE UP FRONT
package Test2::Plugin::MyPlugin;
use Test2::API qw{test2_add_callback_context_release};
sub import {
my $class = shift;
test2_add_callback_context_release(sub {
my $ctx_ref = shift;
print "Context was released\n";
});
}
1;
=head1 LINE BY LINE
=over 4
=item use Test2::API qw{test2_add_callback_context_release};
This imports the C<test2_add_callback_context_release()> callback.
=item test2_add_callback_context_release(sub { ... })
=item my $ctx_ref = shift
The coderefs for test2_add_callback_context_release() will receive exactly 1
argument, the context being released.
=item print "Context was released\n"
Print a notification whenever the context is released.
=back
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,126 @@
package Test2::Manual::Tooling::Plugin::ToolStarts;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Plugin::ToolStarts - How to add behaviors that occur
when a tool starts work.
=head1 DESCRIPTION
This tutorial will help you write plugins that have behavior when a tool
starts. All tools should start by acquiring a context object. This tutorial
shows you the hooks you can use to take advantage of the context acquisition.
=head1 COMPLETE CODE UP FRONT
package Test2::Plugin::MyPlugin;
use Test2::API qw{
test2_add_callback_context_init
test2_add_callback_context_acquire
};
sub import {
my $class = shift;
# Let us know every time a tool requests a context, and give us a
# chance to modify the parameters before we find it.
test2_add_callback_context_acquire(sub {
my $params_ref = shift;
print "A tool has requested the context\n";
});
# Callback every time a new context is created, not called if an
# existing context is found.
test2_add_callback_context_init(sub {
my $ctx_ref = shift;
print "A new context was created\n";
});
}
1;
=head1 LINE BY LINE
=over 4
=item use Test2::API qw{test2_add_callback_context_init test2_add_callback_context_acquire};
This imports the C<test2_add_callback_context_init()> and
C<test2_add_callback_context_acquire()> callbacks.
=item test2_add_callback_context_acquire(sub { ... })
This is where we add our callback for context acquisition. Every time
C<Test2::API::context()> is called the callback will be run.
=item my $params_ref = shift
In the test2_add_callback_context_acquire() callbacks we get exactly 1
argument, a reference to the parameters that C<context()> will use to find the
context.
=item print "A tool has requested the context\n"
Print a notification whenever a tool asks for a context.
=item test2_add_callback_context_init(sub { ... })
Add our context init callback. These callbacks are triggered whenever a
completely new context is created. This is not called if an existing context is
found. In short this only fires off for the top level tool, not nested tools.
=item my $ctx_ref = shift
The coderefs for test2_add_callback_context_init() will receive exactly 1
argument, the newly created context.
=item print "A new context was created\n"
Print a notification whenever a new context is created.
=back
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,164 @@
package Test2::Manual::Tooling::Subtest;
use strict;
use warnings;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Subtest - How to implement a tool that makes use of
subtests.
=head1 DESCRIPTION
Subtests are a nice way of making related events visually, and architecturally
distinct.
=head1 WHICH TYPE OF SUBTEST DO I NEED?
There are 2 types of subtest. The first type is subtests with user-supplied
coderefs, such as the C<subtest()> function itself. The second type is subtest
that do not have any user supplied coderefs.
So which type do you need? The answer to that is simple, if you are going to
let the user define the subtest with their own codeblock, you have the first
type, otherwise you have the second.
In either case, you will still need use the same API function:
C<Test2::API::run_subtest>.
=head2 SUBTEST WITH USER SUPPLIED CODEREF
This example will emulate the C<subtest> function.
use Test2::API qw/context run_subtest/;
sub my_subtest {
my ($name, $code) = @_;
# Like any other tool, you need to acquire a context, if you do not then
# things will not report the correct file and line number.
my $ctx = context();
my $bool = run_subtest($name, $code);
$ctx->release;
return $bool;
}
This looks incredibly simple... and it is. C<run_subtest()> does all the hard
work for you. This will issue an L<Test2::Event::Subtest> event with the
results of the subtest. The subtest event itself will report to the proper file
and line number due to the context you acquired (even though it does not I<look>
like you used the context.
C<run_subtest()> can take additional arguments:
run_subtest($name, $code, \%params, @args);
=over 4
=item @args
This allows you to pass arguments into the codeblock that gets run.
=item \%params
This is a hashref of parameters. Currently there are 3 possible parameters:
=over 4
=item buffered => $bool
This will turn the subtest into the new style buffered subtest. This type of
subtest is recommended, but not default.
=item inherit_trace => $bool
This is used for tool-side coderefs.
=item no_fork => $bool
react to forking/threading inside the subtest itself. In general you are
unlikely to need/want this parameter.
=back
=back
=head2 SUBTEST WITH TOOL-SIDE CODEREF
This is particularly useful if you want to turn a tool that wraps other tools
into a subtest. For this we will be using the tool we created in
L<Test2::Manual::Tooling::Nesting>.
use Test2::API qw/context run_subtest/;
sub check_class {
my $class = shift;
my $ctx = context();
my $code = sub {
my $obj = $class->new;
is($obj->foo, 'foo', "got foo");
is($obj->bar, 'bar', "got bar");
};
my $bool = run_subtest($class, $code, {buffered => 1, inherit_trace => 1});
$ctx->release;
return $bool;
}
The C<run_subtest()> function does all the heavy lifting for us. All we need
to do is give the function a name, a coderef to run, and the
C<< inherit_trace => 1 >> parameter. The C<< buffered => 1 >> parameter is
optional, but recommended.
The C<inherit_trace> parameter tells the subtest tool that the contexts acquired
inside the nested tools should use the same trace as the subtest itself. For
user-supplied codeblocks you do not use inherit_trace because you want errors
to report to the user-supplied file+line.
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,171 @@
package Test2::Manual::Tooling::TestBuilder;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::TestBuilder - This section maps Test::Builder methods
to Test2 concepts.
=head1 DESCRIPTION
With Test::Builder tools were encouraged to use methods on the Test::Builder
singleton object. Test2 has a different approach, every tool should get a new
L<Test2::API::Context> object, and call methods on that. This document maps
several concepts from Test::Builder to Test2.
=head1 CONTEXT
First thing to do, stop using the Test::Builder singleton, in fact stop using
or even loading Test::Builder. Instead of Test::Builder each tool you write
should follow this template:
use Test2::API qw/context/;
sub my_tool {
my $ctx = context();
... do work ...
$ctx->ok(1, "a passing assertion");
$ctx->release;
return $whatever;
}
The original Test::Builder style was this:
use Test::Builder;
my $tb = Test::Builder->new; # gets the singleton
sub my_tool {
... do work ...
$tb->ok(1, "a passing assertion");
return $whatever;
}
=head1 TEST BUILDER METHODS
=over 4
=item $tb->BAIL_OUT($reason)
The context object has a 'bail' method:
$ctx->bail($reason)
=item $tb->diag($string)
=item $tb->note($string)
The context object has diag and note methods:
$ctx->diag($string);
$ctx->note($string);
=item $tb->done_testing
The context object has a done_testing method:
$ctx->done_testing;
Unlike the Test::Builder version, no arguments are allowed.
=item $tb->like
=item $tb->unlike
These are not part of context, instead look at L<Test2::Compare> and
L<Test2::Tools::Compare>.
=item $tb->ok($bool, $name)
# Preferred
$ctx->pass($name);
$ctx->fail($name, @diag);
# Discouraged, but supported:
$ctx->ok($bool, $name, \@failure_diags)
=item $tb->subtest
use the C<Test2::API::run_subtest()> function instead. See L<Test2::API> for documentation.
=item $tb->todo_start
=item $tb->todo_end
See L<Test2::Tools::Todo> instead.
=item $tb->output, $tb->failure_output, and $tb->todo_output
These are handled via formatters now. See L<Test2::Formatter> and
L<Test2::Formatter::TAP>.
=back
=head1 LEVEL
L<Test::Builder> had the C<$Test::Builder::Level> variable that you could
modify in order to set the stack depth. This was useful if you needed to nest
tools and wanted to make sure your file and line number were correct. It was
also frustrating and prone to errors. Some people never even discovered the
level variable and always had incorrect line numbers when their tools would
fail.
L<Test2> uses the context system, which solves the problem a better way. The
top-most tool get a context, and holds on to it until it is done. Any tool
nested under the first will find and use the original context instead of
generating a new one. This means the level problem is solved for free, no
variables to mess with.
L<Test2> is also smart enough to honor c<$Test::Builder::Level> if it is set.
=head1 TODO
L<Test::Builder> used the C<$TODO> package variable to set the TODO state. This
was confusing, and easy to get wrong. See L<Test2::Tools::Todo> for the modern
way to accomplish a TODO state.
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut

View File

@@ -0,0 +1,151 @@
package Test2::Manual::Tooling::Testing;
use strict;
use warnings;
our $VERSION = '0.000139';
1;
__END__
=head1 NAME
Test2::Manual::Tooling::Testing - Tutorial on how to test your testing tools.
=head1 DESCRIPTION
Testing your test tools used to be a complex and difficult prospect. The old
tools such as L<Test::Tester> and L<Test::Builder::Tester> were limited, and
fragile. Test2 on the other hand was designed from the very start to be easily
tested! This tutorial shows you how.
=head1 THE HOLY GRAIL OF TESTING YOUR TOOLS
The key to making Test2 easily testable (specially when compared to
Test::Builder) is the C<intercept> function.
use Test2::API qw/intercept/;
my $events = intercept {
ok(1, "pass");
ok(0, "fail");
diag("A diag");
};
The intercept function lets you use any test tools you want inside a codeblock.
No events or contexts generated within the intercept codeblock will have any
effect on the outside testing state. The C<intercept> function completely
isolates the tools called within.
B<Note:> Plugins and things that effect global API state may not be fully
isolated. C<intercept> is intended specifically for event isolation.
The C<intercept> function will return an arrayref containing all the events
that were generated within the codeblock. You can now make any assertions you
want about the events you expected your tools to generate.
[
bless({...}, 'Test2::Event::Ok'), # pass
bless({...}, 'Test2::Event::Ok'), # fail
bless({...}, 'Test2::Event::Diag'), # Failure diagnostics (not always a second event)
bless({...}, 'Test2::Event::Diag'), # custom 'A diag' message
]
Most test tools eventually produce one or more events. To effectively verify
the events you get from intercept you really should read up on how events work
L<Test2::Manual::Anatomy::Event>. Once you know about events you can move on to
the next section which points you at some helpers.
=head1 ADDITIONAL HELPERS
=head2 Test2::Tools::Tester
This is the most recent set of tools to help you test your events. To really
understand these you should familiarize yourself with
L<Test2::Manual::Anatomy::Event>. If you are going to be writing anything more
than the most simple of tools you should know how events work.
The L<Test2::Tools::Tester> documentation is a good place for further reading.
=head2 Test2::Tools::HarnessTester
The L<Test2::Tools::HarnessTester> can export the C<summarize_events()> tool.
This tool lets you run your event arrayref through L<Test2::Harness> so that you
can get a pass/fail summary.
my $summary = summarize_events($events);
The summary looks like this:
{
plan => $plan_facet, # the plan event facet
pass => $bool, # true if the events result in a pass
fail => $bool, # true if the events result in a fail
errors => $error_count, # Number of error facets seen
failures => $failure_count, # Number of failing assertions seen
assertions => $assertion_count, # Total number of assertions seen
}
=head2 Test2::Tools::Compare
B<DEPRECATED> These tools were written before the switch to faceted events.
These will still work, but are no longer the recommended way to test your
tools.
The L<Test2::Tools::Compare> library exports a handful of extras to help test
events.
=over 4
=item event $TYPE => ...
Use in an array check against $events to check for a specific type of event
with the properties you specify.
=item fail_events $TYPE => ...
Use when you expect a failing assertion of $TYPE. This will automatically check
that the next event following it is a diagnostics message with the default
failure text.
B<Note:> This is outdated as a single event may now possess both the failing
assertion AND the failing text, such events will fail this test.
=back
=head1 SEE ALSO
L<Test2::Manual> - Primary index of the manual.
=head1 SOURCE
The source code repository for Test2-Manual can be found at
F<https://github.com/Test-More/Test2-Suite/>.
=head1 MAINTAINERS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 AUTHORS
=over 4
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
=back
=head1 COPYRIGHT
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>
=cut