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

NAME

Test::Given - Given/When/Then style testing for Perl.

SYNOPSIS

Given/When/Then style of testing inspired by rspec-given and jasmine-given.

Example:

    # t/example.t
    use Test::Given;
    use strict;
    use warnings;

    use Subject;

    # or no strict 'vars';
    our ($subject, $result);

    describe 'Subject Under Test' => sub {
      Given subject => sub { Subject->new() };

      When result => sub { $subject->state() };

      Invariant sub { defined $subject };

      Then sub { $result eq 'uninitialized' };

      context 'When used' => {
        Given sub { $subject->init() };

        When sub { $subject->use() };
        And result => sub { $subject->state() };

        Then sub { $result eq 'passed' };
        And sub { $result ne 'failed' };

        context 'and re-used' => sub {
          When sub { $subject->use() };

          Then sub { has_failed(shift, qr/cannot re-use/i) };
        };
      };
    };

    # prove -v --lib t/example.t

EXPORT

context

  describe 'description', \&sub
  context 'description', \&sub

Group and nest test steps.

Given

  Given \&sub
  Given 'name', \&sub

Code to run before each test. Use to setup test.

If name is given, assign result to symbol in current package. Assumes name is scalar unless a [@%&] sigil is included.

    Given name => sub { 1 };
    Given 'name' => sub { 1 };  # same as above
    Given '$name' => sub { 1 }; # same as above
    Given '@name' => sub { (1, 2, 3) };
    Given '%name' => sub { (a=>1, b=>2) };
    Given '&name' => sub { sub {1} };

Givens within a context are run in the order declared. Givens in outer contexts are run before ones in inner contexts.

Givens are run once per Then in the current and nested contexts.

Exceptions in a Given cause test script to abort.

When

  When \&sub
  When 'name', \&sub

Code to run before each test. Use to perform action under test.

Whens are run after all Givens of current and ancestor contexts.

The optional name parameter behaves the same as for Given.

Whens within a context are run in the order declared. Whens in outer contexts are run before ones in inner contexts.

Whens are run once per Then in the current and nested contexts.

Exceptions in a When are are caught, saved, and passed to each check.

Invariant

  Invariant \&sub

Check to include in each test. Use to reduce duplicate code within tests.

A false result or exception will cause the associated test to report failure.

Invariants within a context are run in the order declared. Invariants in outer contexts are run before ones in inner contexts.

Invariants are run once per Then in the current and nested contexts. They are run after the Then and its associated Ands.

See "has_failed" for checking for exceptions.

Then

  Then \&sub

The main code of each test. Use to check state is as expected.

A false result or exception will cause the test to report failure.

Thens are run after all Whens of current and ancestor contexts.

Thens within a context are run in the order declared. Thens in outer contexts are run before ones in inner contexts.

Thens are run once and count as one test in the TAP output.

See "has_failed" for checking for exceptions.

onDone

  onDone \&sub

Code to run after all tests complete within context. Use to clean up after tests.

onDones are run once in the order declared.

And

Given ...; And ...

When ...; And ...

Invariant ...; And ...

After a Given, When, or Invariant, 'And' is synonymous with the preceding term. In these cases, there is no difference between using the generic And and the more specific term.

Then ...; And ...

After a Then, 'And' adds a check to the preceding Then. It does not create a new test.

Ands after Thens are run once in the order declared. They run after the Then and before Invariants.

A false result or exception will cause the associated test to report failure.

See "has_failed" for checking for exceptions.

has_failed

  has_failed \@exceptions, qr//

Helper method for Invariant, Then, and And (after Then) to check for exceptions thrown during execution of Whens. E.g.

    Invariant sub { has_failed(shift, qr/.../) };
    Then sub { has_failed(shift, qr/.../) };
    And sub { has_failed(shift, qr/.../) };

OUTPUT

Test output conforms to TAP (Test::Builder used under the hood).

Output includes describe/context descriptions when verbose is enabled (-v to prove).

Tests are named after the last line of the Then. The code has been decompiled at this point and may differ from the actual source. Contributions welcome.

To aid diagnosing failing tests, the output includes the decompiled source code of the failing Then, And, or Invariant with the starting line number and filename. If the last line looks like a comparison, an attempt is made to display the value of each side. Values of subexpressions are not included. Contributions welcome.

AUTHOR

Robert Juliano, <rojuvano at gmail dot com>

CONTRIBUTING

Source code repository at https://github.com/rovjuvano/Test-Given

Please report any bugs or feature requests via GitHub Issues or CPAN RT or bug-test-given at rt.cpan.org.

ACKNOWLEDGEMENTS

Inspired by Jim Weirich's rspec-given and Justin Searls's jasmine-given and Matthew Boston's Test::More::Behaviour.

LICENSE AND COPYRIGHT

Copyright 2013 Robert Juliano.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.