File Coverage

lib/Test/BDD/Cucumber/Harness/TAP.pm
Criterion Covered Total %
statement 60 76 78.9
branch 14 24 58.3
condition 5 13 38.4
subroutine 13 13 100.0
pod 7 7 100.0
total 99 133 74.4


line stmt bran cond sub pod time code
1 3     3   2241 use v5.14;
  3         13  
2 3     3   16 use warnings;
  3         5  
  3         242  
3              
4             package Test::BDD::Cucumber::Harness::TAP 0.87;
5              
6             =head1 NAME
7              
8             Test::BDD::Cucumber::Harness::TAP - Generate results in TAP format
9              
10             =head1 VERSION
11              
12             version 0.87
13              
14             =head1 DESCRIPTION
15              
16             A L subclass whose output
17             is TAP (Test Anything Protocol), such as consumed by C
18             and C.
19              
20             =head1 OPTIONS
21              
22             =head2 fail_skip
23              
24             Boolean - makes tests with no matcher fail
25              
26             =cut
27              
28 3     3   15 use Moo;
  3         7  
  3         33  
29              
30 3     3   1255 use Types::Standard qw( Bool InstanceOf Int );
  3         5  
  3         70  
31 3     3   6244 use Test2::API qw/context/;
  3         7  
  3         3485  
32              
33              
34             extends 'Test::BDD::Cucumber::Harness';
35             has 'fail_skip' => ( is => 'rw', isa => Bool, default => 0 );
36              
37             has '_reported_results' => ( is => 'rw', isa => Int, default => 0 );
38              
39             sub feature {
40 9     9 1 28 my ( $self, $feature ) = @_;
41              
42 9         62 my $ctx = context();
43             $ctx->note(join(' ', $feature->keyword_original,
44             ($feature->name || '') . "\n",
45 9   50     1639 map { $_->content } @{ $feature->satisfaction }));
  35         161  
  9         528  
46 9         4225 $ctx->release;
47             }
48              
49             sub scenario {
50 73     73 1 300 my ( $self, $scenario, $dataset ) = @_;
51 73         270 my $ctx = context();
52             $ctx->note(join(' ', $scenario->keyword_original,
53             ($scenario->name || '') . "\n",
54 73   50     10907 map { $_->content} @{ $scenario->description }));
  8         104  
  73         4020  
55 73         29972 $ctx->release;
56             }
57             sub scenario_skip {
58 52     52 1 146 my ( $self, $scenario, $dataset ) = @_;
59 52         188 my $ctx = context();
60 52         7526 my $name = $scenario->name;
61              
62 52         845 $ctx->skip("Scenario '$name' skipped due to tag filter");
63 52         28935 $ctx->release;
64             }
65       73 1   sub scenario_done { }
66              
67       497 1   sub step { }
68              
69             sub step_done {
70 497     497 1 1113 my ( $self, $context, $result ) = @_;
71              
72 497         1405 my $status = $result->result;
73              
74 497         1149 my $step = $context->step;
75 497         1350 my $scenario = $context->scenario;
76 497         804 my $step_name;
77 497         1882 my $ctx = context();
78              
79             # when called from a 'before' or 'after' hook, we have context, but no step
80             $ctx->trace->{frame} = [
81             undef,
82 497 100       77651 $step ? $step->line->document->filename : $scenario->line->document->filename,
    100          
83             $step ? $step->line->number : $scenario->line->number,
84             undef ];
85 497 100       50370 if ( $context->is_hook ) {
86             $status ne 'undefined'
87             and $status ne 'pending'
88             and $status ne 'passing'
89 192 50 33     6613 or do { $ctx->release; return; };
  192   33     915  
  192         7755  
90 0         0 $step_name = ucfirst( $context->verb ) . ' Hook';
91             } else {
92 305         14131 $step_name
93             = ucfirst( $step->verb_original ) . ' ' . $context->text;
94             }
95              
96 305 50 33     4704 if ( $status eq 'undefined' || $status eq 'pending' ) {
    50          
97 0 0       0 if ( $self->fail_skip ) {
98 0 0       0 if ( $status eq 'undefined' ) {
99 0         0 $ctx->fail( "Matcher for: $step_name",
100             $self->_note_step_data($step));
101 0         0 $self->_reported_results( $self->_reported_results + 1 );
102             } else {
103 0         0 $ctx->skip( "Test skipped due to failure in previous step",
104             $self->_note_step_data($step));
105 0         0 $self->_reported_results( $self->_reported_results + 1 );
106             }
107             } else {
108 0         0 $ctx->send_event( 'Skip', todo => 'pending', todo_diag => 1,
109             reason => 'Step not implemented', pass => 0);
110 0         0 $ctx->note($self->_note_step_data($step));
111             }
112             } elsif ( $status eq 'passing' ) {
113 305         10596 $ctx->pass( $step_name );
114 305         66910 $ctx->note($self->_note_step_data($step));
115 305         141560 $self->_reported_results( $self->_reported_results + 1 );
116             } else {
117 0         0 $ctx->fail( $step_name );
118 0         0 $ctx->note($self->_note_step_data($step));
119 0         0 $self->_reported_results( $self->_reported_results + 1 );
120 0 0       0 if ( !$context->is_hook ) {
121 0         0 my $step_location
122             = ' in step at '
123             . $step->line->document->filename
124             . ' line '
125             . $step->line->number . '.';
126 0         0 $ctx->diag($step_location);
127             }
128 0         0 $ctx->diag( $result->output );
129             }
130 305         12356 $ctx->release;
131             }
132              
133             sub _note_step_data {
134 305     305   867 my ( $self, $step ) = @_;
135 305 50       1096 return unless $step;
136 305         603 my @step_data = @{ $step->data_as_strings };
  305         10606  
137 305 100       4205 return '' unless @step_data;
138              
139 25 100       148 if ( ref( $step->data ) eq 'ARRAY' ) {
140 6         60 return join("\n", @step_data);
141             } else {
142 19         176 return join('', '"""', join("\n", @step_data), '"""');
143             }
144             }
145              
146             sub shutdown {
147 1     1 1 2 my $self = shift;
148 1         5 my $ctx = context();
149 1         158 $ctx->done_testing;
150 1         612 $ctx->release;
151             }
152              
153             =head1 AUTHOR
154              
155             Peter Sergeant C
156              
157             =head1 LICENSE
158              
159             Copyright 2019-2023, Erik Huelsmann
160             Copyright 2011-2019, Peter Sergeant; Licensed under the same terms as Perl
161              
162             =cut
163              
164             1;