File Coverage

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

linestmtbrancondsubtimecode
1package App::Test::Generator::Planner::Grouping;
2
3
8
8
8
64925
8
97
use strict;
4
8
8
8
13
6
136
use warnings;
5
8
8
8
14
6
134
use Carp    qw(croak);
6
8
8
8
204
1684
1027
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.36';
24
25 - 62
=head1 VERSION

Version 0.36

=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
24
113313
        my $class = $_[0];
66
24
30
        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
22
1315
        my ($self, $schema) = @_;
126
127        # Validate that schema is a hashref before iterating
128
22
49
        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
16
28
        my %groups = (
134                $GROUP_PURE     => [],
135                $GROUP_MUTATING => [],
136                $GROUP_IMPURE   => [],
137        );
138
139
16
16
87
19
        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
22
29
                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
22
17
                my $group =
147                        $level eq $PURITY_PURE          ? $GROUP_PURE     :
148                        $level eq $PURITY_SELF_MUTATING ? $GROUP_MUTATING :
149                                                          $GROUP_IMPURE;
150
151
22
22
90
27
                push @{ $groups{$group} }, $method;
152        }
153
154
16
18
        return \%groups;
155}
156
1571;