Test-YAFT/lib/Test/YAFT/Introduction.pod
=pod
=encoding utf-8
=head1 NAME
Test::YAFT::Introduction - Introduction to Test::YAFT
=head1 DESCRIPTION
L<Test::YAFT> is manifestation of (my) opinion that tests should be so
easy to read and understand that they can (and should) act as entrypoint
into your project for newbies.
=head1 BASIC USAGE
Basic test structure doesn't differ much from usage of L<Test::Simple> /
L<Test::More>. Main differences are:
=over
=item mandatory test message
Test message is mandatory and is always a first argument of every assert
function.
Every other argument is provided using named argument approach.
=item L<Test::Deep> comparison
Every comparison uses L<Test::Deep>
=back
=head1 HOW TO USE IT
=head2 C<it> assert
Basic assert L<Test::YAFT> provides is an C<it>. Naming expects that
you have either subtests describing your testing intention or one
behaviour per test file, so C<it> can be bounded with something from
your domain.
subtest "Person" => sub {
it "should have method foo()"
=> got => defined &{ Person->can ('foo') }
=> expect => expect_true
;
};
=head2 Computed C<got>
C<it> can compute C<got> value
subtest "method birthday()" => sub {
it "should increment person's age"
=> got { $person->new (age => 41)->birthday; $person->age }
=> expect => 42
;
}
When using computed C<got> approach L<Test::YAFT> always executes given block
in C<eval> and verifies its status, so it fails with "expected to live / die"
first.
=over
=item expect code to die, if C<throws> parameter exists
=item expect code to live otherwise
=back
subtest "method birthday()" => sub {
it "should increment person's age"
=> got { $person->new (age => 41)->birthday; $person->age }
=> expect => 42
;
it "should throw an exception when called too fast"
=> got { $person->new (age => 41)->birthday->birthday; $person->age }
=> throws => expect_re (qr/Person cannot be born twice a day/)
;
}
=head2 Shared C<got> computation (with arguments)
Often there are test scenarios when you share computation of C<got> value
but with different arguments for each assert.
L<Test::YAFT> provides simple tool for that - C<act { }> block
subtest "resource /countries/:continent provides alphabetical sorted list countries on the continent" => sub {
act { GET "/countries/$_[0]" } 'continent';
it "should list North America continental countries"
=> with_continent => 'north-america'
=> expect =>
& expect_http_success
& expect_json_content_type
& expect_json_content {
countries => [
'Canada',
'Mexico',
'USA',
]
}
;
it "should list Australia continental countries"
=> with_continent => 'australia'
=> expect =>
& expect_http_success
& expect_json_content_type
& expect_json_content {
countries => [
'Australia',
]
}
;
it "should list no country in Antarctica"
=> with_continent => 'antarctica'
=> expect =>
& expect_http_success
& expect_json_content_type
& expect_json_content {
countries => [
]
}
;
};
=head2 Arrange {} block
C<act {}> block dependencies can be provided via similar C<arrange {}> block.
it "should list no country in Antarctica"
=> arrange { continent => 'antarctica' }
=> expect =>
& expect_http_success
& expect_json_content_type
& expect_json_content {
countries => [
]
}
;
Difference is that C<arrange {}> block is executed inside context of C<it>.
There can be multiple arrange blocks, executed in order of definition.
Each block should return C<<singleton => value>> pairs, one singleton can be
arranged only once.
=head1 AUTHOR
Branislav ZahradnĂk <barney@cpan.org>
=head1 COPYRIGHT AND LICENCE
This file is part of L<Test::YAFT> distribution.
=cut