The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use strict;
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Test::Stream::Manual::Tooling - How to write test tools using the Test::Stream
infrastructure.
=head1 DESCRIPTION
This manual page explains the process of building a test tool using
Test::Stream.
=head1 QUICK START
If you wantd to write a module that implemented the C<ok()> function, this is
all you need to write:
package Test::Stream::Plugin::MyOk;
use strict;
use warnings;
use Test::Stream::Context qw/context/;
use Test::Stream::Exporter;
default_exports qw/ok/;
no Test::Stream::Exporter;
sub ok($;$) {
my ($bool, $name) = @_; # Get args
my $ctx = context(); # Obtain a context
$ctx->ok($bool, $name); # Issue an OK event
$ctx->release; # Release the context
return $bool; # Return the true/false
}
1;
=head2 EXPLANATION
=over 4
=item Obtaining a context
This is the B<MOST> critical thing you need to do in any testing tool. You
B<should> do this as soon as possible. The L<Test::Stream::Context> object ties
everything together. Obtaining a context object locks in the file and line
number to which errors should be reported. It also finds the current hub to
which all events should be sent. Finally the context object is the primary
interface used to generate events. In short the context object is the tool
builders 1-stop shop.
=item Issue an Ok event
The core event types, C<ok>, C<note>, C<diag>, C<bail>, and C<plan> have
shortcut functions on the context object. These shortcut functions construct
the event, and send it to the hub for processing. Other event types can be
generated as well using the C<< $ctx->build_event(...) >> or
C<< $ctx->send_event(...) >> methods. See the L<Test::Stream::Context> object
documentation for additional details.
=item Release the context
When your tool is finished it is very important that you release the context.
Failing to release the context would result in a leak condition. In most cases
the context will detect this condition and take measures to correct it, along
with issuing a very verbose warning.
=item Return the true/false
Typically testing tools will return a true or false indicating if the test has
passed or failed.
=back
=head1 ADVANCED
This covers more advanced topics for tool builders.
=head2 EVENTS
Most testing tools generate events. The most common event generated is the
L<Test::Stream::Event::Ok> event. In addition it is possible for tools to
create their own event types.
=head2 CONTEXT
The L<Test::Stream::Context> object ties
everything together. Obtaining a context object locks in the file and line
number to which errors should be reported. It also finds the current hub to
which all events should be sent. Finally the context object is the primary
interface used to generate events. In short the context object is the tool
builders 1-stop shop.
There is only ever one canonical context instance per active hub. If two tools
try to obtain a context in the same stack they will both get the same one, the
first one to request it generates it, the second gets the existing instance. In
both cases the tool B<MUST> release it when done. Tools should never send
contexts to other tools, and they should never accept them as arguments. Tools
that get broken up into multiple functions may pass the context to their
component subs.
=head2 DEBUGINFO
L<Test::Stream::DebugInfo> objects are stored inside the context object, its
job is to store filename and line number for errors. It can also be used to
issue warnings and throw exceptions. Every event generated needs to have a
DebugInfo object, typically cloned from the one in the context object.
=head2 HUBS
L<Test::Stream::Hub> objects are responsible for 2 things, the first is
tracking state. Hubs have an instance of an L<Test::Stream::State> object. When
an event is processed by a hub the state will be updated accordingly.
The second job of a hub is to make sure events get to the right place.
Typically this means processing the event through any 'filters', then handing
them off to the formatter, then finally running them through 'listeners'.
When IPC is active the hub will use the IPC driver (See L<Test::Stream::IPC>)
to send events to the correct process or thread.
=head2 HUB STACK
There is a single canonical L<Test::Stream::Stack> instance tracked by the
L<Test::Stream::Sync> package. When a context is obtained it will reference
whatever hub is on the top of the stack at the time it is created. Typically
all events will be sent to the topmost hub.
=head2 SYNC
The L<Test::Stream::Sync> package is the place where all shared state is
tracked. Part of Test::Streams design is reducing shared state to the bare
minimum. This class is kept as small as possible while still achieving the
necessary functionality. The sync package tracks IPC drivers, formatter, the
hub stack, and some global hooks.
=head2 EXPORTER
L<Test::Stream::Exporter> is an export tool built-in to Test::Stream.
Test::Stream requires export functionality well beyond what L<Exporter.pm> is
able to provide. In addition a plugin that does not need special import
functionality can simply use L<Test::Stream::Exporter> to work as a plugin.
=head2 CAPABILITIES
L<Test::Stream::Capabilities> can be used to guage the active systems fork
and/or thread support levels.
=head2 UTILITIES
The L<Test::Stream::Util> package exports many useful functions for test
authors.
=head2 PLUGINS
Plugins can either use L<Test::Stream::Export> or they can use
L<Test::Stream::Plugin> and implement the C<load_ts_plugin()> method.
=head2 BUNDLES
Bundles are used to combine several plugins into a single module that can be
used to load them all at once. This is the better alternative to the
L<Test::Builder> practice of having tools load eachother.
=head1 SOURCE
The source code repository for Test::Stream can be found at
=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 2015 Chad Granum E<lt>exodist7@gmail.comE<gt>.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut