File Coverage

File:blib/lib/App/Test/Generator/Planner/Fixture.pm
Coverage:100.0%

linestmtbrancondsubtimecode
1package App::Test::Generator::Planner::Fixture;
2
3
11
11
11
128208
11
135
use strict;
4
11
11
11
16
9
186
use warnings;
5
11
11
11
15
9
193
use Carp    qw(croak);
6
11
11
11
428
3340
1146
use Readonly;
7
8# --------------------------------------------------
9# Isolation mode that triggers shared fixture reuse
10# --------------------------------------------------
11Readonly my $MODE_SHARED_FIXTURE => 'shared_fixture';
12
13# --------------------------------------------------
14# Fixture mode labels written to the plan output
15# --------------------------------------------------
16Readonly my $FIXTURE_SHARED       => 'shared';
17Readonly my $FIXTURE_NEW_PER_TEST => 'new_per_test';
18
19our $VERSION = '0.41';
20
21 - 59
=head1 VERSION

Version 0.41

=head1 DESCRIPTION

Plans fixture setup strategy for each method under test, based on the
isolation requirements provided by
L<App::Test::Generator::Planner::Isolation>. Methods that share state
are assigned a shared fixture; all others get a fresh fixture per test.

=head2 new

Construct a new Fixture planner.

    my $planner = App::Test::Generator::Planner::Fixture->new;

=head3 Arguments

None.

=head3 Returns

A blessed hashref.

=head3 API specification

=head4 input

    {}

=head4 output

    {
        type => OBJECT,
        isa  => 'App::Test::Generator::Planner::Fixture',
    }

=cut
60
61sub new {
62
27
187844
        my $class = $_[0];
63
27
36
        return bless {}, $class;
64}
65
66 - 123
=head2 plan

Produce a fixture plan for each method based on its isolation mode.
Methods with isolation mode C<shared_fixture> are assigned a shared
fixture; all other methods get a fresh fixture per test.

    my $planner   = App::Test::Generator::Planner::Fixture->new;
    my $fixture   = $planner->plan($schema, $isolation);

    for my $method (keys %{$fixture}) {
        printf "%s: %s\n", $method, $fixture->{$method}{mode};
    }

=head3 Arguments

=over 4

=item * C<$schema>

A hashref representing the module schema. Currently unused but
reserved for future fixture customisation based on schema metadata.

=item * C<$isolation>

A hashref mapping method names to isolation plan hashrefs, each with
a C<fixture> key, as produced by
L<App::Test::Generator::Planner::Isolation>.

=back

=head3 Returns

A hashref mapping method names to fixture plan hashrefs, each with a
C<mode> key set to either C<shared> or C<new_per_test>.

=head3 API specification

=head4 input

    {
        self      => { type => OBJECT,  isa     => 'App::Test::Generator::Planner::Fixture' },
        schema    => { type => HASHREF },
        isolation => { type => HASHREF },
    }

=head4 output

    {
        type  => HASHREF,
        keys  => {
            '*' => {
                type => HASHREF,
                keys => { mode => { type => SCALAR } },
            },
        },
    }

=cut
124
125sub plan {
126
31
4357
        my ($self, $schema, $isolation) = @_;
127
128        # Validate that isolation is a hashref before iterating
129
31
68
        croak 'isolation must be a hashref' unless ref($isolation) eq 'HASH';
130
131
24
17
        my %fixture;
132
133        # --------------------------------------------------
134        # Assign fixture mode per method based on isolation.
135        # Shared fixture mode reuses one object across tests
136        # for methods that share state; all others get a
137        # fresh object constructed per test case.
138        # --------------------------------------------------
139
24
24
22
26
        for my $method (keys %{$isolation}) {
140
26
49
                my $mode = ($isolation->{$method}{fixture} // '') eq $MODE_SHARED_FIXTURE
141                        ? $FIXTURE_SHARED
142                        : $FIXTURE_NEW_PER_TEST;
143
144
26
129
                $fixture{$method} = { mode => $mode };
145        }
146
147
24
26
        return \%fixture;
148}
149
1501;