File Coverage

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

linestmtbrancondsubtimecode
1package App::Test::Generator::Planner::Grouping;
2
3
11
11
11
66008
9
107
use strict;
4
11
11
11
15
10
195
use warnings;
5
11
11
11
18
6
170
use Carp    qw(croak);
6
11
11
11
230
1596
1420
use Readonly;
7
8# --------------------------------------------------
9# Purity level strings from Analyzer::SideEffect
10# --------------------------------------------------
11Readonly my $PURITY_PURE          => 'pure';
12Readonly my $PURITY_SELF_MUTATING => 'self_mutating';
13
14# --------------------------------------------------
15# Group keys in the output plan.
16# Note: self_mutating maps to 'mutating' in the
17# group key to keep the output API concise.
18# --------------------------------------------------
19Readonly my $GROUP_PURE     => 'pure';
20Readonly my $GROUP_MUTATING => 'mutating';
21Readonly my $GROUP_IMPURE   => 'impure';
22
23our $VERSION = '0.46';
24
25 - 62
=head1 VERSION

Version 0.46

=head1 DESCRIPTION

Groups methods by their purity level for more efficient test file
organisation. Pure methods can share setup; mutating methods need
per-test objects; impure methods need full isolation blocks.

=head2 new

Construct a new Grouping planner.

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

=head3 Arguments

None.

=head3 Returns

A blessed hashref.

=head3 API specification

=head4 input

    {}

=head4 output

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

=cut
63
64sub new {
65
29
117240
        my $class = $_[0];
66
29
40
        return bless {}, $class;
67}
68
69 - 122
=head2 plan

Group all methods in the schema by their purity level.

    my $planner = App::Test::Generator::Planner::Grouping->new;
    my $groups  = $planner->plan($schema);

    printf "Pure methods:    %s\n", join(', ', @{ $groups->{pure}     });
    printf "Mutating methods:%s\n", join(', ', @{ $groups->{mutating} });
    printf "Impure methods:  %s\n", join(', ', @{ $groups->{impure}   });

=head3 Arguments

=over 4

=item * C<$schema>

A hashref of method schemas each optionally containing a C<_analysis>
key with a C<side_effects> sub-key as produced by
L<App::Test::Generator::Analyzer::SideEffect>.

=back

=head3 Returns

A hashref with three keys — C<pure>, C<mutating>, and C<impure> —
each containing an arrayref of method names assigned to that group.
Methods without purity metadata are placed in C<impure> by default.

Note: the purity level C<self_mutating> from
L<App::Test::Generator::Analyzer::SideEffect> is mapped to the
C<mutating> group key in this output.

=head3 API specification

=head4 input

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

=head4 output

    {
        type => HASHREF,
        keys => {
            pure     => { type => ARRAYREF },
            mutating => { type => ARRAYREF },
            impure   => { type => ARRAYREF },
        },
    }

=cut
123
124sub plan {
125
28
2020
        my ($self, $schema) = @_;
126
127        # Validate that schema is a hashref before iterating
128
28
74
        croak 'schema must be a hashref'
129                unless ref($schema) eq 'HASH';
130
131        # Initialise all three groups so the output always
132        # has all three keys even if some groups are empty
133
21
67
        my %groups = (
134                $GROUP_PURE     => [],
135                $GROUP_MUTATING => [],
136                $GROUP_IMPURE   => [],
137        );
138
139
21
21
128
30
        for my $method (keys %{$schema}) {
140                # Default to empty string if purity_level is absent —
141                # missing metadata falls through to the impure group
142
28
241
                my $level = $schema->{$method}{_analysis}{side_effects}{purity_level} // '';
143
144                # Map purity level to group key — self_mutating becomes
145                # 'mutating' to keep the output API concise
146
28
45
                my $group =
147                        $level eq $PURITY_PURE          ? $GROUP_PURE     :
148                        $level eq $PURITY_SELF_MUTATING ? $GROUP_MUTATING :
149                                                          $GROUP_IMPURE;
150
151
28
28
128
33
                push @{ $groups{$group} }, $method;
152        }
153
154
21
27
        return \%groups;
155}
156
1571;