Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/pvande/test-mini-unit

Declarative Sugar for Test::Mini
https://github.com/pvande/test-mini-unit

perl preprocessor test-framework

Last synced: 3 months ago
JSON representation

Declarative Sugar for Test::Mini

Awesome Lists containing this project

README

        

=for comment Documentation generated by YARD v0.6.1 and yard-pod-plugin v0.1.

=head1 NAME

Test::Mini::Unit - Declarative Sugar for Test::Mini

=head1 DESCRIPTION

Test::Mini::Unit aims to provide a simpler, boilerplate-free environment
for writing new L<<<< S<<<<< Test::Mini >>>>>|Test::Mini >>>> test
cases. While Test::Mini itself is a fairly reasonable environment with
very little overhead verbosity, the overhead of creating a new class --
or set of classes -- in Perl can still be a bit more distracting than
you'd really like.

=head2 Enter Test::Mini::Unit

At first glance, Test::Mini::Unit provides moderate improvements over
the traditional style, transforming this:

package t::Test
use base 'Test::Mini::TestCase';
use strict;
use warnings;

use Test::Mini::Assertions;

sub setup {
# do something
}

sub test_some_code {
assert($something_true);
}

sub teardown {
# undo something
}

1;

Into this:

use Test::Mini::Unit;

case t::Test {
setup {
# do something
}

test some_code {
assert($something_true);
}

teardown {
# undo something
}
}

=head2 Advice

But Test::Mini::Unit really begins to shine as your test cases take on
more complexity. Multiple calls to the test advice methods (C<<<< setup
>>>> and C<<<< teardown >>>>) will stack like C<<<< BEGIN >>>> and C<<<<
END >>>> blocks, allowing you to co-locate tests and relevant advice.

# Traditional
sub setup {
# do a bunch of setup for test_one
# ...
# do a bunch of setup for test_two
# ...
}

sub test_one { ... }
sub test_two { ... }

# Test::Mini::Unit
setup { "do setup for test_one" }
sub test_one { ... }

setup { "do setup for test_two" }
sub test_two { ... }

=head2 Test-Local Storage

Per-test local storage is automatically available as C<<<< $self >>>>
from all advice and test blocks.

setup { $self->{data} = Package->new() }
test data { assert_isa($self->{data}, 'Package') }

teardown { unlink $self->{tmpfile} }

=head2 Nesting

And perhaps most usefully, test cases can be B<<<< nested >>>>. Nested
test cases inherit all their outer scope's test advice, allowing you to
build richer tests with far less code.

case t::IO::Scalar {
setup { $self->{buffer} = IO::Scalar->new() }
test can_read { assert_can($self->{buffer}, 'read') }
test can_write { assert_can($self->{buffer}, 'write') }
test is_empty { assert_empty("@{[$self->{buffer}]}") }

case AfterWritingString {
setup { $self->{buffer}->print('String!') }
test contents {
assert_equal("@{[$self->{buffer}]}", 'String!');
}
}

case AfterWritingObject {
setup { $self->{buffer}->print($self) }
test contents {
assert_equal("@{[$self->{buffer}]}", "$self");
}
}
}

=head2 Sharing Tests...

In some cases, you may find it useful to reuse the same tests in
different cases. For this purpose, the C<<<< shared >>>> and C<<<<
reuse >>>> keywords exist:

shared BasicBookTests {
test has_pages { ... }
test pages_have_text { ... }
}

case Book {
reuse BasicBookTests;
}

case LargePrintBook {
reuse BasicBookTests;
test words_should_be_big { ... }
}

=head2 ... And Reusing Them

Groups of shared tests may also be nested inside C<<<< case >>>> blocks,
where they will inherit the namespace of their parent. Since shared
tests will most commonly see reuse inside either the C<<<< case >>>>
they're declared in or a nested case, it's not usually necessary to
specify the full package name. The C<<<< reuse >>>> keyword will try,
therefore, to infer the fully qualified package name from the name it's
given. (You can always specify the full name yourself by prepending
'::'.)

shared CommonTests {
# __PACKAGE__ is 'Nested::CommonTests'
}

case Nested {
shared CommonTests {
# __PACKAGE__ is 'Nested::CommonTests'
}

case Deeply {
shared CommonTests {
# __PACKAGE__ is 'Nested::Deeply::CommonTests'
}

# includes Nested::Deeply::CommonTests
reuse CommonTests;

# includes Nested::CommonTests
reuse Nested::CommonTests;

# includes CommonTests
reuse ::CommonTests;
}

# includes Nested::CommonTests
reuse CommonTests;
}

=head2 Automatic 'use'

To automatically use packages inside all your test cases (for example,
your own custom assertions), simply pass the 'with' option to
Test::Mini::Unit; it can accept either a single package name or an
array.

use Test::Mini::Unit (with => [ My::Assertions, My::HelperFuncs ]);

case t::TestCase {
# My::Assertions and My::HelperFuncs are already imported here.
case Nested {
# In here, too.
}

shared CommonTests {
# Yup, here too.
}
}

See Also:

=over

=item *

L<<<< S<<<<< Test::Mini >>>>>|Test::Mini >>>>

=back

=head1 AUTHOR

Pieter van de Bruggen