The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Test::Tutorial::WritingTools - How to write testing tools.

Examples

Complete Example
    package My::Tool;
    use strict;
    use warnings;

    use Test::Stream::Toolset;
    use Test::Stream::Exporter;

    # Export 'validate_widget' by default.
    default_exports qw/validate_widget/;

    sub validate_widget {
        my ($widget, $produces, $name) = @_;
        my $ctx = context(); # Do this early as possible

        my $value = $widget->produce;
        my $ok = $value eq $produces;

        if ($ok) {
            # On success generate an ok event
            $ctx->ok($ok, $name);
        }
        else {
            # On failure generate an OK event with some diagnostics
            $ctx->ok($ok, $name, ["Widget produced '$value'\n Wanted '$produces'"]);
        }

        # It is usually polite to return a true/false value.
        return $ok ? 1 : 0;
    }

    1;
Alternate using Exporter.pm
    package My::Tool;
    use strict;
    use warnings;

    use Test::Stream::Toolset;

    # Export 'validate_widget' by default.
    use base 'Exporter';
    our @EXPORT = qw/validate_widget/;

    sub validate_widget {
        my ($widget, $produces, $name) = @_;
        my $ctx = context(); # Do this early as possible

        my $value = $widget->produce;
        my $ok = $value eq $produces;

        if ($ok) {
            # On success generate an ok event
            $ctx->ok($ok, $name);
        }
        else {
            # On failure generate an OK event with some diagnostics
            $ctx->ok($ok, $name, ["Widget produced '$value'\n Wanted '$produces'"]);
        }

        # It is usually polite to return a true/false value.
        return $ok ? 1 : 0;
    }

    1;

Explanation

Test::Stream is event based. Whenever you want to produce a result you will generate an event for it. The most common event is Test::Stream::Event::Ok. Events require some extra information such as where and how they were produced. In general you do not need to worry about these extra details, they can be filled in by Test::Stream::Context.

To get a context object you call context() which can be imported from Test::Stream::Context itself, or from Test::Stream::Toolset. Once you have a context object you can ask it to issue events for you. All event types Test::Stream::Event::* get helper methods on the context object.

IMPORTANT NOTE ON CONTEXTS

The context object has some magic to it. Essentially it is a semi-singleton. That is if you generate a context object in one place, then try to generate another one in another place, you will just get the first one again so long as it still has a reference. If however the first one has fallen out of scope or been undefined, a new context is generated.

The idea here is that if you nest functions that use contexts, all levels of depth will get the same initial context. On the other hand 2 functions run in sequence will get independant context objects. What this means is that you should NEVER store a context object in a package variable or object attribute. You should also never assign it to a variable in a higher scope.

Nesting calls to other tools

    use Test::More;
    use Test::Stream::Toolset;

    sub compound_check {
        my ($object, $name) = @_;

        # Grab the context now for nested tools to find
        my $ctx = context;

        my $ok = $object ? 1 : 0;
        $ok &&= isa_ok($object, 'Some::Class');
        $ok &&= can_ok($object, qw/foo bar baz/);
        $ok &&= is($object->foo, 'my foo', $name);

        $ctx->ok($ok, $name, $ok ? () : ['Not all object checks passed!']);

        return $ok;
    }

    1;

Nesting tools just works as expected so long as you grab the context BEFORE you call them. Errors will be reported to the correct file and line number.

Useful toolsets to look at

Test::More::Tools

This is the collection of tools used by Test::More under the hood. You can use these instead of Test::More exports to duplicate functionality without generating extra events.

Available Events

Anyone can add an event by shoving it in the Test::Stream::Event::* namespace. It will autoload if $context->event_name is called. But here is the list of events that come with Test::Stream.

Test::Stream::Event::Ok
    $ctx->ok($bool, $name);
    $ctx->ok($bool, $name, \@diag);

Generate an Ok event.

Test::Stream::Event::Diag
    $ctx->diag("Diag Message");

Generate a diagniostics (stderr) message

Test::Stream::Event::Note
    $ctx->note("Note Message");

Generate a note (stdout) message

Test::Stream::Event::Bail
    $ctx->bail("Reason we are bailing");

Stop the entire test file, something is very wrong!

Test::Stream::Event::Plan
    $ctx->plan($max);
    $ctx->plan(0, $directive, $reason);

Set the plan.

Testing your tools

See Test::Stream::Tester, which lets you intercept and validate events.

DO NOT SEE Test::Tester and Test::Builder::Tester which are both deprecated. They were once the way everyone tested their testers, but they do not allow you to test all events, and they are very fragile when upstream libs change.

SOURCE

The source code repository for Test::More can be found at http://github.com/Test-More/test-more/.

MAINTAINER

Chad Granum <exodist@cpan.org>

AUTHORS

The following people have all contributed to the Test-More dist (sorted using VIM's sort function).

Chad Granum <exodist@cpan.org>
Fergal Daly <fergal@esatclear.ie>>
Mark Fowler <mark@twoshortplanks.com>
Michael G Schwern <schwern@pobox.com>
唐鳳

COPYRIGHT

There has been a lot of code migration between modules, here are all the original copyrights together:

Test::Stream
Test::Stream::Tester

Copyright 2014 Chad Granum <exodist7@gmail.com>.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See http://www.perl.com/perl/misc/Artistic.html

Test::Simple
Test::More
Test::Builder

Originally authored by Michael G Schwern <schwern@pobox.com> with much inspiration from Joshua Pritikin's Test module and lots of help from Barrie Slaymaker, Tony Bowden, blackstar.co.uk, chromatic, Fergal Daly and the perl-qa gang.

Idea by Tony Bowden and Paul Johnson, code by Michael G Schwern <schwern@pobox.com>, wardrobe by Calvin Klein.

Copyright 2001-2008 by Michael G Schwern <schwern@pobox.com>.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See http://www.perl.com/perl/misc/Artistic.html

Test::use::ok

To the extent possible under law, 唐鳳 has waived all copyright and related or neighboring rights to Test-use-ok.

This work is published from Taiwan.

http://creativecommons.org/publicdomain/zero/1.0

Test::Tester

This module is copyright 2005 Fergal Daly <fergal@esatclear.ie>, some parts are based on other people's work.

Under the same license as Perl itself

See http://www.perl.com/perl/misc/Artistic.html

Test::Builder::Tester

Copyright Mark Fowler <mark@twoshortplanks.com> 2002, 2004.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.