
=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 assumption
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<assume> assumption

Basic assumption L<Test::YAFT> provides is an C<assume>. 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 {
		assume "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 assumption.

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@gmail.com>

=head1 COPYRIGHT AND LICENCE

This file is part of L<Test::YAFT> distribution.

=cut
