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

NAME

Test::Stream::Plugin::Spec - SPEC testing tools

EXPERIMENTAL CODE WARNING

This is an experimental release! Test-Stream, and all its components are still in an experimental phase. This dist has been released to cpan in order to allow testers and early adopters the chance to write experimental new tools with it, or to add experimental support for it into old tools.

PLEASE DO NOT COMPLETELY CONVERT OLD TOOLS YET. This experimental release is very likely to see a lot of code churn. API's may break at any time. Test-Stream should NOT be depended on by any toolchain level tools until the experimental phase is over.

DESCRIPTION

SYNOPSIS

    use Test::Stream qw/-V1 Spec/

    describe fruit_shipment => sub {
        my $crates;
        before_all unload_crates => sub { $crates = get_crates() };
        after_all deliver_crates => sub { deliver($crates) };

        my $fruit;
        for my $f ($crates->types) { # 'pear' and 'apple'
            case $f => sub { $fruit = $f };
        }

        my $crate;
        before_each open_crate => sub { $crate = $crates->open_first($fruit) };
        after_each close_crate => sub { $crates->store($crate) };

        tests squishability => sub {
            my $sample = $crate->grab();
            ok($sample->squishability > 5, "squish rating is greater than 5");
            ok($sample->squishability < 10, "squish rating is less than 10");
        };

        tests flavor => sub {
            my $sample = $crate->grab();
            ok($sample->is_tasty, "sample is tasty");
            ok(!$sample->is_sour, "sample is not sour");
        };

        tests ripeness => sub {
            my $sample1 = $crate->grab();
            my $sample2 = $crate->grab();

            my $overripe  = grep { $_->is_overripe }  $sample1, $sample2;
            my $underripe = grep { $_->is_underripe } $sample1, $sample2;

            ok($overripe  < 2, "at least 1 sample is not overripe");
            ok($underripe < 2, "at least 1 sample is not underripe");
        };
    };

    done_testing;

In this sample we are describing a fruit shipment. Before anything else we unload the crates. Next we handle 2 types of fruit, a crate of pears and a crate of apples. For each create we need to run tests on squishability, flavor, and ripeness. In order to run these tests the creates need to be opened, when the tests are done the crates need to be closed again.

We use the before_all and after_all to specify the first and last tasks to be run, each one will run exactly once. The 3 sets of tests will be run once per fruit type, we have cases for pears and apples, so in total there will be 6 sets of tests run, 3 per fruit type. Opening and closing the crate is something we need to do for each test block, so we use before_each and after_each.

Each test block needs unique samples, so the sample is aquired within the test. We do not use a before_each as some tests require different numbers of samples.

EXPORTS

All exports have the exact same syntax, there are 2 forms:

    FUNCTION($NAME, \&CODE);
    FUNCTION($NAME, \%PARAMS, \&CODE);

Both can also be used in a style that is more pleasingto the eye:

    FUNCTION $NAME => sub { ... };
    FUNCTION $NAME => {...}, sub { ... }

The name and codeblock are required. Optionally you can provide a hashref of parameters between the name and coderef with parameters. Valid parameters depends on what runner is used, but the parameters supported by default are:

Note: The default runner is Test::Stream::Workflow::Runner.

todo => 'reason'

This will mark the entire block as todo with the given reason. This parameter is inherited by nested blocks.

skip => 'reason'

This will skip the entire block, it will generate a single 'Ok' event with the skip reason set.

iso => $bool
isolate => $bool

This tells the runner to isolate the task before running the block. This allows you to isolate blocks that may modify state in ways that should not be seen by later tests. Isolation is achieved either by forking, or by spawning a child thread, depending on the platform. If no isolation method is available the block will simply be skipped.

CAVEAT: Since the isolation may be threads (specially if you are on windows) it may fail to isolate shared variables. If you use variables that are shared between threads you cannot rely on this isolation mechanism.

Note: The tests you declare are deferred, that is they run after everything else is done, typically when you call done_testing.

TEST DECLARATIONS

Test declarations are used to declare blocks of tests. You can put pretty much anything you want inside a test block, the only exceptions to this is that other test blocks, groups, modifiers, etc, cannot be specified inside the test block.

If a test block does not produce any events then it will be considered an error. Test blocks are run as subtests.

tests $name => sub { ... }
it $name => sub { ... }
tests $name => \%params, sub { ... }
it $name => \%params, sub { ... }

tests() and it() are both aliases to the same function. The name tests() is present as the authors preference. it() is present to reflect the name used in RSPEC for the Ruby programming language.

Note: The subs get no arguments, and their return is ignored.

TEST SETUP AND TEARDOWN

These blocks attach themselves to test blocks. The setup/teardown will run once for each test block. These are all inherited by test blocks declared in nested groups.

before_each $name => sub { ... }

Declare a setup that will run before each test block is run. Note: This will run before any modifier.

Note: The subs get no arguments, and their return is ignored.

after_each $name => sub { ... }

Declare a teardown that will run after each test block.

Note: The subs get no arguments, and their return is ignored.

around_each $name => sub { ... }

Declare a setup+teardown that is wrapped around the test block. This is useful if you want to localize a variable, or something similar.

    around_each foo => sub {
        my $inner = shift;

        local %ENV;

        # You need to call the 'inner' sub.
        $inner->();
    };

Note: The subs get no arguments, and their return is ignored.

TEST MODIFIERS

case $name => sub { ... }

You can specify any number of cases that should be used. All test blocks are run once per case. Cases are inherited by nested groups.

Note: The subs get no arguments, and their return is ignored.

TEST MODIFIER SETUP AND TEARDOWN

before_case $name => sub { ... }

Code to be run just before a case is run.

Note: The subs get no arguments, and their return is ignored.

after_case $name => sub { ... }

Code to be run just after a case is run (but before the test block).

Note: The subs get no arguments, and their return is ignored.

around_case $name => sub { ... }

Code that wraps around the case.

    around_case foo => sub {
        my $inner = shift;

        local %ENV;

        # You need to call the 'inner' sub.
        $inner->();
    };

Note: The subs get no arguments, and their return is ignored.

TEST GROUPS

describe $name => sub { ... }
cases $name => sub { ... }

describe() and cases() are both aliases to the same thing.

These can be used to create groups of test block along with setup/teardown subs. The cases, setups, and teardowns will not effect test blocks outside the group. All cases, setups, and teardown will be inherited by any nested group.

Note: Group subs are run as they are encountered, unlike test blocks which are run at the very end of the test script.

Note: The subs get no arguments, and their return is ignored.

GROUP MODIFIERS

before_all $name => sub { ... }

Specify a setup that gets run once at the start of the test group.

Note: The subs get no arguments, and their return is ignored.

after_all $name => sub { ... }

Specify a teardown that gets run once at the end of the test group.

Note: The subs get no arguments, and their return is ignored.

around_all $name => sub { ... }

Specify a teardown that gets run once, around the test group.

    around_all foo => sub {
        my $inner = shift;

        local %ENV;

        # You need to call the 'inner' sub.
        $inner->();
    };

Note: The subs get no arguments, and their return is ignored.

NOTE ON RUN ORDER

Within a test group (the main package counts as a group) things run in this order:

group blocks (describe, cases)
END OF SCRIPT (done_testing called)
before_all + around_all starts
before_each + around_each starts
before_case + around_case starts
case
after_case + around_case stops
tests/it
after_each + around_each stops
after_all + around_all stops

SOURCE

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

MAINTAINERS

Chad Granum <exodist@cpan.org>

AUTHORS

Chad Granum <exodist@cpan.org>

COPYRIGHT

Copyright 2015 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