TER1 (Statement): 100.00%
TER2 (Branch): 100.00%
TER3 (LCSAJ): 100.0% (3/3)
Approximate LCSAJ segments: 7
● 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::Mock; 2: 3: use strict; 4: use warnings; 5: use Carp qw(croak); 6: use Readonly; 7: 8: # -------------------------------------------------- 9: # Mock strategy labels written to the plan output. 10: # mock_system is used when a method calls external 11: # commands; capture_io when it performs IO operations. 12: # Note: if a method does both, mock_system takes 13: # precedence â see note in plan() below. 14: # -------------------------------------------------- 15: Readonly my $MOCK_SYSTEM => 'mock_system'; 16: Readonly my $MOCK_CAPTURE_IO => 'capture_io'; 17: 18: our $VERSION = '0.36'; 19: 20: =head1 VERSION 21: 22: Version 0.36 23: 24: =head1 DESCRIPTION 25: 26: Plans mock strategy for each method that has external side effects, 27: based on side effect analysis metadata in the schema. Methods that 28: call external commands are assigned a system mock; methods that 29: perform IO are assigned IO capture. Used by 30: L<App::Test::Generator::Emitter::Perl> to generate appropriate mock 31: setup code in the test output. 32: 33: =head2 new 34: 35: Construct a new Mock planner. 36: 37: my $planner = App::Test::Generator::Planner::Mock->new; 38: 39: =head3 Arguments 40: 41: None. 42: 43: =head3 Returns 44: 45: A blessed hashref. 46: 47: =head3 API specification 48: 49: =head4 input 50: 51: {} 52: 53: =head4 output 54: 55: { 56: type => OBJECT, 57: isa => 'App::Test::Generator::Planner::Mock', 58: } 59: 60: =cut 61: 62: sub new { bless {}, shift } 63: 64: =head2 plan 65: 66: Produce a mock plan for each method that requires external mocking, 67: based on side effect analysis metadata in the schema. 68: 69: my $planner = App::Test::Generator::Planner::Mock->new; 70: my $mock_plan = $planner->plan($schema); 71: 72: for my $method (keys %{$mock_plan}) { 73: printf "%s: %s\n", $method, $mock_plan->{$method}; 74: } 75: 76: =head3 Arguments 77: 78: =over 4 79: 80: =item * C<$schema> 81: 82: A hashref of method schemas, each optionally containing a 83: C<_analysis> key with a C<side_effects> sub-key as produced by 84: L<App::Test::Generator::Analyzer::SideEffect>. 85: 86: =back 87: 88: =head3 Returns 89: 90: A hashref mapping method names to mock strategy strings. Only methods 91: that require mocking appear in the output â pure methods are omitted. 92: 93: Currently supported strategy values are C<mock_system> and 94: C<capture_io>. If a method both calls external commands and performs 95: IO, C<mock_system> takes precedence. This is a known limitation and 96: may be revised in a future version to support multiple strategies per 97: method. 98: 99: =head3 API specification 100: 101: =head4 input 102: 103: { 104: self => { type => OBJECT, isa => 'App::Test::Generator::Planner::Mock' }, 105: schema => { type => HASHREF }, 106: } 107: 108: =head4 output 109: 110: { 111: type => HASHREF, 112: keys => { 113: '*' => { type => SCALAR }, 114: }, 115: } 116: 117: =cut 118: 119: sub plan { ●120 → 127 → 147●120 → 127 → 0 120: my ($self, $schema) = @_; 121: 122: # Validate that schema is a hashref before iterating 123: croak 'schema must be a hashref' unless ref($schema) eq 'HASH'; 124: 125: my %mock_plan; 126: 127: for my $method (keys %{$schema}) { 128: # Extract side effect analysis if present â 129: # default to empty hashref if not available 130: my $effects = $schema->{$method}{_analysis}{side_effects} || {}; 131: 132: # -------------------------------------------------- 133: # Assign mock strategy based on detected side effects. 134: # mock_system takes precedence over capture_io when 135: # both are present â this is a known limitation. 136: # TODO: consider supporting multiple strategies per 137: # method as an arrayref in a future version. 138: # -------------------------------------------------- 139: if($effects->{calls_external}) {Mutants (Total: 1, Killed: 1, Survived: 0)
140: $mock_plan{$method} = $MOCK_SYSTEM; 141: } elsif($effects->{performs_io}) { 142: $mock_plan{$method} = $MOCK_CAPTURE_IO; 143: } 144: # Pure methods require no mocking â omit from plan 145: } 146: ●147 → 147 → 0 147: return \%mock_plan; 148: } 149: 150: 1;