File Coverage

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

linestmtbrancondsubtimecode
1package App::Test::Generator::Planner;
2
3
6
6
6
132446
7
74
use strict;
4
6
6
6
12
4
144
use warnings;
5
6
6
6
13
4
111
use Carp qw(croak);
6
6
6
6
417
3300
113
use Readonly;
7
8
6
6
6
697
8
104
use App::Test::Generator::TestStrategy;
9
6
6
6
834
7
92
use App::Test::Generator::Planner::Isolation;
10
6
6
6
776
10
95
use App::Test::Generator::Planner::Fixture;
11
6
6
6
801
8
78
use App::Test::Generator::Planner::Mock;
12
6
6
6
850
7
1273
use App::Test::Generator::Planner::Grouping;
13
14our $VERSION = '0.36';
15
16# Accessor type strings used in plan_all() strategy mapping
17Readonly my $ACCESSOR_GET      => 'get';
18Readonly my $ACCESSOR_GETSET   => 'getset';
19Readonly my $ACCESSOR_INJECTOR => 'injector';
20
21# Output type string for boolean detection
22Readonly my $OUTPUT_BOOLEAN => 'boolean';
23
24 - 51
=head1 VERSION

Version 0.36

=head2 new

Construct a new Planner instance.

    my $planner = App::Test::Generator::Planner->new(
        schemas => \%schemas,
        package => 'My::Module',
    );

=head3 Arguments

=over 4

=item * C<schemas> - hashref of method name to schema hashref. Required.

=item * C<package> - the Perl package name of the module under test. Required.

=back

=head3 Returns

A blessed hashref.

=cut
52
53sub new {
54
50
214269
        my ($class, %args) = @_;
55
56        # schemas and package are required for meaningful planning
57
50
79
        croak 'schemas required' unless defined $args{schemas};
58
50
51
        croak 'package required' unless defined $args{package};
59
60        return bless {
61                schemas => $args{schemas},
62                package => $args{package},
63
50
91
        }, $class;
64}
65
66 - 83
=head2 plan_all

Generate a test plan for every method in the schema.

    my $plans = $planner->plan_all();

=head3 Arguments

None beyond C<$self>.

=head3 Returns

A hashref mapping method name to a plan hashref. Each plan hashref
contains boolean flags such as C<getter_test>, C<getset_test>,
C<object_injection_test>, and C<boolean_test> indicating which test
types should be emitted for that method.

=cut
84
85sub plan_all {
86
44
116
        my $self = $_[0];
87
44
33
        my %method_plan;
88
89        # Build a plan for each method in the schema
90
44
44
33
73
        foreach my $method (keys %{ $self->{schemas} }) {
91
157
105
                my $schema = $self->{schemas}{$method};
92
157
83
                my %plan;
93
94                # Map accessor type to the appropriate test flag
95
157
190
                if($schema->{accessor} && $schema->{accessor}->{type}) {
96
26
22
                        my $type = $schema->{accessor}->{type};
97
26
47
                        if($type eq $ACCESSOR_GET) {
98
8
32
                                $plan{getter_test} = 1;
99                        } elsif($type eq $ACCESSOR_GETSET) {
100
6
33
                                $plan{getset_test} = 1;
101                        } elsif($type eq $ACCESSOR_INJECTOR) {
102                                # Object injection requires a mock object in the test
103
4
31
                                $plan{object_injection_test} = 1;
104                        }
105                }
106
107                # Boolean output type requires a predicate test
108
157
218
                if($schema->{output}->{type} && $schema->{output}->{type} eq $OUTPUT_BOOLEAN) {
109
10
40
                        $plan{boolean_test} = 1;
110                }
111
112
157
178
                $method_plan{$method} = \%plan;
113        }
114
115
44
62
        return \%method_plan;
116}
117
118# --------------------------------------------------
119# build_plan
120#
121# Build a comprehensive test plan using
122#     all available planning subsystems:
123#     strategy, isolation, fixture, mock,
124#     and grouping.
125#
126# Entry:      None beyond $self.
127# Exit:       Returns a hashref with keys: strategy,
128#             isolation, fixture, mock, groups.
129#
130# Notes:      TODO: This method does not appear to be
131#             called anywhere. Consider removing it or
132#             integrating it into plan_all().
133# --------------------------------------------------
134sub build_plan {
135
2
691
        my $self = $_[0];
136
137        # Generate the base strategy from the schema
138        my $strategy_engine = App::Test::Generator::TestStrategy->new(
139                schema => $self->{schemas}
140
2
3
        );
141
2
5
        my $strategy = $strategy_engine->generate_plan();
142
143        # Apply isolation, fixture, mock and grouping layers
144        my $isolation = App::Test::Generator::Planner::Isolation->new()->plan(
145
2
4
                $self->{schemas}, $strategy
146        );
147        my $fixture = App::Test::Generator::Planner::Fixture->new()->plan(
148
2
8
                $self->{schemas}, $isolation
149        );
150
2
7
        my $mock   = App::Test::Generator::Planner::Mock->new()->plan($self->{schemas});
151
2
6
        my $groups = App::Test::Generator::Planner::Grouping->new()->plan($self->{schemas});
152
153        return {
154
2
10
                strategy  => $strategy,
155                isolation => $isolation,
156                fixture   => $fixture,
157                mock      => $mock,
158                groups    => $groups,
159        };
160}
161
162 - 166
=head1 AUTHOR

Nigel Horne

=cut
167
1681;