File Coverage

lib/Test/BDD/Cucumber/Harness/TAP.pm
Criterion Covered Total %
statement 55 68 80.8
branch 14 24 58.3
condition 5 13 38.4
subroutine 12 12 100.0
pod 6 6 100.0
total 92 123 74.8


line stmt bran cond sub pod time code
1             package Test::BDD::Cucumber::Harness::TAP;
2             $Test::BDD::Cucumber::Harness::TAP::VERSION = '0.84';
3             =head1 NAME
4              
5             Test::BDD::Cucumber::Harness::TAP - Generate results in TAP format
6              
7             =head1 VERSION
8              
9             version 0.84
10              
11             =head1 DESCRIPTION
12              
13             A L subclass whose output
14             is TAP (Test Anything Protocol), such as consumed by C
15             and C.
16              
17             =head1 OPTIONS
18              
19             =head2 fail_skip
20              
21             Boolean - makes tests with no matcher fail
22              
23             =cut
24              
25 3     3   1664 use strict;
  3         7  
  3         92  
26 3     3   15 use warnings;
  3         7  
  3         70  
27 3     3   16 use Moo;
  3         5  
  3         16  
28              
29 3     3   1169 use Types::Standard qw( Bool InstanceOf );
  3         8  
  3         28  
30 3     3   2175 use Test2::API qw/context/;
  3         6  
  3         2690  
31              
32              
33             extends 'Test::BDD::Cucumber::Harness';
34             has 'fail_skip' => ( is => 'rw', isa => Bool, default => 0 );
35              
36              
37             sub feature {
38 9     9 1 31 my ( $self, $feature ) = @_;
39              
40 9         38 my $ctx = context();
41             $ctx->note(join(' ', $feature->keyword_original,
42             ($feature->name || '') . "\n",
43 9   50     1331 map { $_->content } @{ $feature->satisfaction }));
  35         166  
  9         502  
44 9         5158 $ctx->release;
45             }
46              
47             sub scenario {
48 73     73 1 252 my ( $self, $scenario, $dataset ) = @_;
49 73         259 my $ctx = context();
50             $ctx->note(join(' ', $scenario->keyword_original,
51             ($scenario->name || '') . "\n",
52 73   50     8595 map { $_->content} @{ $scenario->description }));
  8         95  
  73         3925  
53 73         31572 $ctx->release;
54             }
55       73 1   sub scenario_done { }
56              
57       497 1   sub step { }
58              
59             sub step_done {
60 497     497 1 1012 my ( $self, $context, $result ) = @_;
61              
62 497         1103 my $status = $result->result;
63              
64 497         1073 my $step = $context->step;
65 497         1020 my $scenario = $context->scenario;
66 497         707 my $step_name;
67 497         1380 my $ctx = context();
68              
69             # when called from a 'before' or 'after' hook, we have context, but no step
70             $ctx->trace->{frame} = [
71             undef,
72 497 100       63256 $step ? $step->line->document->filename : $scenario->line->document->filename,
    100          
73             $step ? $step->line->number : $scenario->line->number,
74             undef ];
75 497 100       42388 if ( $context->is_hook ) {
76             $status ne 'undefined'
77             and $status ne 'pending'
78             and $status ne 'passing'
79 192 50 33     5428 or do { $ctx->release; return; };
  192   33     709  
  192         5292  
80 0         0 $step_name = ucfirst( $context->verb ) . ' Hook';
81             } else {
82 305         12096 $step_name
83             = ucfirst( $step->verb_original ) . ' ' . $context->text;
84             }
85              
86 305 50 33     4986 if ( $status eq 'undefined' || $status eq 'pending' ) {
    50          
87 0 0       0 if ( $self->fail_skip ) {
88 0 0       0 if ( $status eq 'undefined' ) {
89 0         0 $ctx->fail( "Matcher for: $step_name",
90             $self->_note_step_data($step));
91             } else {
92 0         0 $ctx->skip( "Test skipped due to failure in previous step",
93             $self->_note_step_data($step));
94             }
95             } else {
96 0         0 $ctx->send_event( 'Skip', todo => 'pending', todo_diag => 1,
97             reason => 'Step not implemented', pass => 0);
98 0         0 $ctx->note($self->_note_step_data($step));
99             }
100             } elsif ( $status eq 'passing' ) {
101 305         1241 $ctx->pass( $step_name );
102 305         70866 $ctx->note($self->_note_step_data($step));
103             } else {
104 0         0 $ctx->fail( $step_name );
105 0         0 $ctx->note($self->_note_step_data($step));
106 0 0       0 if ( !$context->is_hook ) {
107 0         0 my $step_location
108             = ' in step at '
109             . $step->line->document->filename
110             . ' line '
111             . $step->line->number . '.';
112 0         0 $ctx->diag($step_location);
113             }
114 0         0 $ctx->diag( $result->output );
115             }
116 305         119256 $ctx->release;
117             }
118              
119             sub _note_step_data {
120 305     305   837 my ( $self, $step ) = @_;
121 305 50       1008 return unless $step;
122 305         502 my @step_data = @{ $step->data_as_strings };
  305         7663  
123 305 100       3511 return '' unless @step_data;
124              
125 25 100       218 if ( ref( $step->data ) eq 'ARRAY' ) {
126 6         47 return join("\n", @step_data);
127             } else {
128 19         154 return join('', '"""', join("\n", @step_data), '"""');
129             }
130             }
131              
132 1     1 1 4 sub shutdown { my $self = shift; my $ctx = context(); $ctx->done_testing; $ctx->release; }
  1         4  
  1         107  
  1         585  
133              
134             =head1 AUTHOR
135              
136             Peter Sergeant C
137              
138             =head1 LICENSE
139              
140             Copyright 2019-2023, Erik Huelsmann
141             Copyright 2011-2019, Peter Sergeant; Licensed under the same terms as Perl
142              
143             =cut
144              
145             1;