summaryrefslogtreecommitdiff
path: root/ext/Test/Harness/t/aggregator.t
blob: b3aff2a21f9ac909b096af6614fe8326056148e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#!/usr/bin/perl -wT

use strict;
use lib 't/lib';

use Test::More tests => 79;

use TAP::Parser;
use TAP::Parser::IteratorFactory;
use TAP::Parser::Aggregator;

my $tap = <<'END_TAP';
1..5
ok 1 - input file opened
... this is junk
not ok first line of the input valid # todo some data
# this is a comment
ok 3 - read the rest of the file
not ok 4 - this is a real failure
ok 5 # skip we have no description
END_TAP

my $factory = TAP::Parser::IteratorFactory->new;
my $stream = $factory->make_iterator( [ split /\n/ => $tap ] );
isa_ok $stream, 'TAP::Parser::Iterator';

my $parser1 = TAP::Parser->new( { stream => $stream } );
isa_ok $parser1, 'TAP::Parser';

$parser1->run;

$tap = <<'END_TAP';
1..7
ok 1 - gentlemen, start your engines
not ok first line of the input valid # todo some data
# this is a comment
ok 3 - read the rest of the file
not ok 4 - this is a real failure
ok 5 
ok 6 - you shall not pass! # TODO should have failed
not ok 7 - Gandalf wins.  Game over.  # TODO 'bout time!
END_TAP

my $parser2 = TAP::Parser->new( { tap => $tap } );
isa_ok $parser2, 'TAP::Parser';
$parser2->run;

can_ok 'TAP::Parser::Aggregator', 'new';
my $agg = TAP::Parser::Aggregator->new;
isa_ok $agg, 'TAP::Parser::Aggregator';

can_ok $agg, 'add';
ok $agg->add( 'tap1', $parser1 ), '... and calling it should succeed';
ok $agg->add( 'tap2', $parser2 ), '... even if we add more than one parser';
eval { $agg->add( 'tap1', $parser1 ) };
like $@, qr/^You already have a parser for \Q(tap1)/,
  '... but trying to reuse a description should be fatal';

can_ok $agg, 'parsers';
is scalar $agg->parsers, 2,
  '... and it should report how many parsers it has';
is_deeply [ $agg->parsers ], [ $parser1, $parser2 ],
  '... or which parsers it has';
is_deeply $agg->parsers('tap2'), $parser2, '... or reporting a single parser';
is_deeply [ $agg->parsers(qw(tap2 tap1)) ], [ $parser2, $parser1 ],
  '... or a group';

# test aggregate results

can_ok $agg, 'passed';
is $agg->passed, 10,
  '... and we should have the correct number of passed tests';
is_deeply [ $agg->passed ], [qw(tap1 tap2)],
  '... and be able to get their descriptions';

can_ok $agg, 'failed';
is $agg->failed, 2,
  '... and we should have the correct number of failed tests';
is_deeply [ $agg->failed ], [qw(tap1 tap2)],
  '... and be able to get their descriptions';

can_ok $agg, 'todo';
is $agg->todo, 4, '... and we should have the correct number of todo tests';
is_deeply [ $agg->todo ], [qw(tap1 tap2)],
  '... and be able to get their descriptions';

can_ok $agg, 'skipped';
is $agg->skipped, 1,
  '... and we should have the correct number of skipped tests';
is_deeply [ $agg->skipped ], [qw(tap1)],
  '... and be able to get their descriptions';

can_ok $agg, 'parse_errors';
is $agg->parse_errors, 0, '... and the correct number of parse errors';
is_deeply [ $agg->parse_errors ], [],
  '... and be able to get their descriptions';

can_ok $agg, 'todo_passed';
is $agg->todo_passed, 1,
  '... and the correct number of unexpectedly succeeded tests';
is_deeply [ $agg->todo_passed ], [qw(tap2)],
  '... and be able to get their descriptions';

can_ok $agg, 'total';
is $agg->total, $agg->passed + $agg->failed,
  '... and we should have the correct number of total tests';

can_ok $agg, 'has_problems';
ok $agg->has_problems, '... and it should report true if there are problems';

can_ok $agg, 'has_errors';
ok $agg->has_errors, '... and it should report true if there are errors';

can_ok $agg, 'get_status';
is $agg->get_status, 'FAIL', '... and it should tell us the tests failed';

can_ok $agg, 'all_passed';
ok !$agg->all_passed, '... and it should tell us not all tests passed';

# coverage testing

# _get_parsers
# bad descriptions
# currently the $agg object has descriptions tap1 and tap2
# call _get_parsers with another description.
# $agg will call  its _croak method
my @die;

eval {
    local $SIG{__DIE__} = sub { push @die, @_ };

    $agg->_get_parsers('no_such_parser_for');
};

is @die, 1,
  'coverage tests for missing parsers... and we caught just one death message';
like pop(@die),
  qr/^A parser for \(no_such_parser_for\) could not be found at /,
  '... and it was the expected death message';

# _get_parsers in scalar context

my $gp = $agg->_get_parsers(qw(tap1 tap2))
  ;    # should return ref to array containing parsers for tap1 and tap2

is @$gp, 2,
  'coverage tests for _get_parser in scalar context... and we got the right number of parsers';
isa_ok( $_, 'TAP::Parser' ) foreach (@$gp);

# _get_parsers
# todo_failed - this is a deprecated method, so it  (and these tests)
# can be removed eventually.  However, it is showing up in the coverage
# as never tested.
my @warn;

eval {
    local $SIG{__WARN__} = sub { push @warn, @_ };

    $agg->todo_failed();
};

# check the warning, making sure to capture the fullstops correctly (not
# as "any char" matches)
is @warn, 1,
  'coverage tests for deprecated todo_failed... and just one warning caught';
like pop(@warn),
  qr/^"todo_failed" is deprecated[.]  Please use "todo_passed"[.]  See the docs[.] at/,
  '... and it was the expected warning';

# has_problems
# this has a large number of conditions 'OR'd together, so the tests get
# a little complicated here

# currently, we have covered the cases of failed() being true and none
# of the summary methods failing

# we need to set up test cases for
# 1. !failed && todo_passed
# 2. !failed && !todo_passed && parse_errors
# 3. !failed && !todo_passed && !parse_errors && exit
# 4. !failed && !todo_passed && !parse_errors && !exit && wait

# note there is nothing wrong per se with the has_problems logic, these
# are simply coverage tests

# 1. !failed && todo_passed

$agg = TAP::Parser::Aggregator->new();
isa_ok $agg, 'TAP::Parser::Aggregator';

$tap = <<'END_TAP';
1..1
ok 1 - you shall not pass! # TODO should have failed
END_TAP

my $parser3 = TAP::Parser->new( { tap => $tap } );
isa_ok $parser3, 'TAP::Parser';
$parser3->run;

$agg->add( 'tap3', $parser3 );

is $agg->passed, 1,
  'coverage tests for !failed && todo_passed... and we should have the correct number of passed tests';
is $agg->failed, 0,
  '... and we should have the correct number of failed tests';
is $agg->todo_passed, 1,
  '... and the correct number of unexpectedly succeeded tests';
ok $agg->has_problems,
  '... and it should report true that there are problems';
is $agg->get_status, 'PASS', '... and the status should be passing';
ok !$agg->has_errors, '.... but it should not report any errors';
ok $agg->all_passed, '... bonus tests should be passing tests, too';

# 2. !failed && !todo_passed && parse_errors

$agg = TAP::Parser::Aggregator->new();

$tap = <<'END_TAP';
1..-1
END_TAP

my $parser4 = TAP::Parser->new( { tap => $tap } );
isa_ok $parser4, 'TAP::Parser';
$parser4->run;

$agg->add( 'tap4', $parser4 );

is $agg->passed, 0,
  'coverage tests for !failed && !todo_passed && parse_errors... and we should have the correct number of passed tests';
is $agg->failed, 0,
  '... and we should have the correct number of failed tests';
is $agg->todo_passed, 0,
  '... and the correct number of unexpectedly succeeded tests';
is $agg->parse_errors, 1, '... and the correct number of parse errors';
ok $agg->has_problems,
  '... and it should report true that there are problems';

# 3. !failed && !todo_passed && !parse_errors && exit
# now this is a little harder to emulate cleanly through creating tap
# fragments and parsing, as exit and wait collect OS-status codes.
# so we'll get a little funky with $agg and push exit and wait descriptions
# in it - not very friendly to internal rep changes.

$agg = TAP::Parser::Aggregator->new();

$tap = <<'END_TAP';
1..1
ok 1 - you shall not pass!
END_TAP

my $parser5 = TAP::Parser->new( { tap => $tap } );
$parser5->run;

$agg->add( 'tap', $parser5 );

push @{ $agg->{descriptions_for_exit} }, 'one possible reason';
$agg->{exit}++;

is $agg->passed, 1,
  'coverage tests for !failed && !todo_passed && !parse_errors... and we should have the correct number of passed tests';
is $agg->failed, 0,
  '... and we should have the correct number of failed tests';
is $agg->todo_passed, 0,
  '... and the correct number of unexpectedly succeeded tests';
is $agg->parse_errors, 0, '... and the correct number of parse errors';

my @exits = $agg->exit;

is @exits, 1, '... and the correct number of exits';
is pop(@exits), 'one possible reason',
  '... and we collected the right exit reason';

ok $agg->has_problems,
  '... and it should report true that there are problems';

# 4. !failed && !todo_passed && !parse_errors && !exit && wait

$agg = TAP::Parser::Aggregator->new();

$agg->add( 'tap', $parser5 );

push @{ $agg->{descriptions_for_wait} }, 'another possible reason';
$agg->{wait}++;

is $agg->passed, 1,
  'coverage tests for !failed && !todo_passed && !parse_errors && !exit... and we should have the correct number of passed tests';
is $agg->failed, 0,
  '... and we should have the correct number of failed tests';
is $agg->todo_passed, 0,
  '... and the correct number of unexpectedly succeeded tests';
is $agg->parse_errors, 0, '... and the correct number of parse errors';
is $agg->exit,         0, '... and the correct number of exits';

my @waits = $agg->wait;

is @waits, 1, '... and the correct number of waits';
is pop(@waits), 'another possible reason',
  '... and we collected the right wait reason';

ok $agg->has_problems,
  '... and it should report true that there are problems';