| File: | blib/lib/App/Test/Generator/Planner.pm |
| Coverage: | 95.4% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package 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 | ||||||
| 14 | our $VERSION = '0.36'; | |||||
| 15 | ||||||
| 16 | # Accessor type strings used in plan_all() strategy mapping | |||||
| 17 | Readonly my $ACCESSOR_GET => 'get'; | |||||
| 18 | Readonly my $ACCESSOR_GETSET => 'getset'; | |||||
| 19 | Readonly my $ACCESSOR_INJECTOR => 'injector'; | |||||
| 20 | ||||||
| 21 | # Output type string for boolean detection | |||||
| 22 | Readonly 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 | ||||||
| 53 | sub 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 | ||||||
| 85 | sub 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 | # -------------------------------------------------- | |||||
| 134 | sub 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 | ||||||
| 168 | 1; | |||||