TER1 (Statement): 100.00%
TER2 (Branch): 78.57%
TER3 (LCSAJ): 100.0% (3/3)
Approximate LCSAJ segments: 15
● Covered — this LCSAJ path was executed during testing.
● Not covered — this LCSAJ path was never executed. These are the paths to focus on.
Multiple dots on a line indicate that multiple control-flow paths begin at that line. Hovering over any dot shows:
start → end → jump
Uncovered paths show [NOT COVERED] in the tooltip.
1: package App::Test::Generator::Planner; 2: 3: use strict; 4: use warnings; 5: use Carp qw(croak); 6: use Readonly; 7: 8: use App::Test::Generator::TestStrategy; 9: use App::Test::Generator::Planner::Isolation; 10: use App::Test::Generator::Planner::Fixture; 11: use App::Test::Generator::Planner::Mock; 12: 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: =head1 VERSION 25: 26: Version 0.36 27: 28: =head2 new 29: 30: Construct a new Planner instance. 31: 32: my $planner = App::Test::Generator::Planner->new( 33: schemas => \%schemas, 34: package => 'My::Module', 35: ); 36: 37: =head3 Arguments 38: 39: =over 4 40: 41: =item * C<schemas> - hashref of method name to schema hashref. Required. 42: 43: =item * C<package> - the Perl package name of the module under test. Required. 44: 45: =back 46: 47: =head3 Returns 48: 49: A blessed hashref. 50: 51: =cut 52: 53: sub new { 54: my ($class, %args) = @_; 55: 56: # schemas and package are required for meaningful planning 57: croak 'schemas required' unless defined $args{schemas}; 58: croak 'package required' unless defined $args{package}; 59: 60: return bless { 61: schemas => $args{schemas}, 62: package => $args{package}, 63: }, $class; 64: } 65: 66: =head2 plan_all 67: 68: Generate a test plan for every method in the schema. 69: 70: my $plans = $planner->plan_all(); 71: 72: =head3 Arguments 73: 74: None beyond C<$self>. 75: 76: =head3 Returns 77: 78: A hashref mapping method name to a plan hashref. Each plan hashref 79: contains boolean flags such as C<getter_test>, C<getset_test>, 80: C<object_injection_test>, and C<boolean_test> indicating which test 81: types should be emitted for that method. 82: 83: =cut 84: 85: sub plan_all { ●86 → 90 → 115●86 → 90 → 0 86: my $self = $_[0]; 87: my %method_plan; 88: 89: # Build a plan for each method in the schema 90: foreach my $method (keys %{ $self->{schemas} }) { 91: my $schema = $self->{schemas}{$method}; 92: my %plan; 93: 94: # Map accessor type to the appropriate test flag 95: if($schema->{accessor} && $schema->{accessor}->{type}) {Mutants (Total: 1, Killed: 1, Survived: 0)
96: my $type = $schema->{accessor}->{type}; 97: if($type eq $ACCESSOR_GET) {
Mutants (Total: 1, Killed: 1, Survived: 0)
98: $plan{getter_test} = 1; 99: } elsif($type eq $ACCESSOR_GETSET) { 100: $plan{getset_test} = 1; 101: } elsif($type eq $ACCESSOR_INJECTOR) { 102: # Object injection requires a mock object in the test 103: $plan{object_injection_test} = 1; 104: } 105: } 106: 107: # Boolean output type requires a predicate test 108: if($schema->{output}->{type} && $schema->{output}->{type} eq $OUTPUT_BOOLEAN) {
Mutants (Total: 1, Killed: 1, Survived: 0)
109: $plan{boolean_test} = 1; 110: } 111: 112: $method_plan{$method} = \%plan; 113: } 114: ●115 → 115 → 0 115: 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: 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: ); 141: 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: $self->{schemas}, $strategy 146: ); 147: my $fixture = App::Test::Generator::Planner::Fixture->new()->plan( 148: $self->{schemas}, $isolation 149: ); 150: my $mock = App::Test::Generator::Planner::Mock->new()->plan($self->{schemas}); 151: my $groups = App::Test::Generator::Planner::Grouping->new()->plan($self->{schemas}); 152: 153: return { 154: strategy => $strategy, 155: isolation => $isolation, 156: fixture => $fixture, 157: mock => $mock, 158: groups => $groups, 159: }; 160: } 161: 162: =head1 AUTHOR 163: 164: Nigel Horne 165: 166: =cut 167: 168: 1;