cucumber-core 4.0.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,474 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ require 'cucumber/core/test/result'
4
+ require 'cucumber/core/test/duration_matcher'
5
+
6
+ module Cucumber::Core::Test
7
+ describe Result do
8
+
9
+ let(:visitor) { double('visitor') }
10
+ let(:args) { double('args') }
11
+
12
+ describe Result::Passed do
13
+ subject(:result) { Result::Passed.new(duration) }
14
+ let(:duration) { Result::Duration.new(1 * 1000 * 1000) }
15
+
16
+ it "describes itself to a visitor" do
17
+ expect( visitor ).to receive(:passed).with(args)
18
+ expect( visitor ).to receive(:duration).with(duration, args)
19
+ result.describe_to(visitor, args)
20
+ end
21
+
22
+ it "converts to a string" do
23
+ expect( result.to_s ).to eq "✓"
24
+ end
25
+
26
+ it "has a duration" do
27
+ expect( result.duration ).to eq duration
28
+ end
29
+
30
+ it "requires the constructor argument" do
31
+ expect { Result::Passed.new }.to raise_error(ArgumentError)
32
+ end
33
+
34
+ it "does nothing when appending the backtrace" do
35
+ expect( result.with_appended_backtrace(double) ).to equal result
36
+ end
37
+
38
+ it "does nothing when filtering the backtrace" do
39
+ expect( result.with_filtered_backtrace(double) ).to equal result
40
+ end
41
+
42
+ specify { expect( result.to_sym ).to eq :passed }
43
+
44
+ specify { expect( result ).to be_passed }
45
+ specify { expect( result ).not_to be_failed }
46
+ specify { expect( result ).not_to be_undefined }
47
+ specify { expect( result ).not_to be_unknown }
48
+ specify { expect( result ).not_to be_skipped }
49
+ specify { expect( result ).not_to be_flaky }
50
+
51
+ specify { expect( result ).to be_ok }
52
+ specify { expect( result.ok? ).to be_truthy }
53
+ end
54
+
55
+ describe Result::Failed do
56
+ subject(:result) { Result::Failed.new(duration, exception) }
57
+ let(:duration) { Result::Duration.new(1 * 1000 * 1000) }
58
+ let(:exception) { StandardError.new("error message") }
59
+
60
+ it "describes itself to a visitor" do
61
+ expect( visitor ).to receive(:failed).with(args)
62
+ expect( visitor ).to receive(:duration).with(duration, args)
63
+ expect( visitor ).to receive(:exception).with(exception, args)
64
+ result.describe_to(visitor, args)
65
+ end
66
+
67
+ it "has a duration" do
68
+ expect( result.duration ).to eq duration
69
+ end
70
+
71
+ it "requires both constructor arguments" do
72
+ expect { Result::Failed.new }.to raise_error(ArgumentError)
73
+ expect { Result::Failed.new(duration) }.to raise_error(ArgumentError)
74
+ end
75
+
76
+ it "does nothing if step has no backtrace line" do
77
+ result.exception.set_backtrace("exception backtrace")
78
+ step = "does not respond_to?(:backtrace_line)"
79
+
80
+ expect( result.with_appended_backtrace(step).exception.backtrace ).to eq(["exception backtrace"])
81
+ end
82
+
83
+ it "appends the backtrace line of the step" do
84
+ result.exception.set_backtrace("exception backtrace")
85
+ step = double
86
+ expect( step ).to receive(:backtrace_line).and_return("step_line")
87
+
88
+ expect( result.with_appended_backtrace(step).exception.backtrace ).to eq(["exception backtrace", "step_line"])
89
+ end
90
+
91
+ it "apply filters to the exception" do
92
+ filter_class = double
93
+ filter = double
94
+ filtered_exception = double
95
+ expect( filter_class ).to receive(:new).with(result.exception).and_return(filter)
96
+ expect( filter ).to receive(:exception).and_return(filtered_exception)
97
+
98
+ expect( result.with_filtered_backtrace(filter_class).exception ).to equal filtered_exception
99
+ end
100
+
101
+ specify { expect( result.to_sym ).to eq :failed }
102
+
103
+ specify { expect( result ).not_to be_passed }
104
+ specify { expect( result ).to be_failed }
105
+ specify { expect( result ).not_to be_undefined }
106
+ specify { expect( result ).not_to be_unknown }
107
+ specify { expect( result ).not_to be_skipped }
108
+ specify { expect( result ).not_to be_flaky }
109
+
110
+ specify { expect( result ).to_not be_ok }
111
+ specify { expect( result.ok? ).to be_falsey }
112
+ end
113
+
114
+ describe Result::Unknown do
115
+ subject(:result) { Result::Unknown.new }
116
+
117
+ it "doesn't describe itself to a visitor" do
118
+ visitor = double('never receives anything')
119
+ result.describe_to(visitor, args)
120
+ end
121
+
122
+ it "defines a with_filtered_backtrace method" do
123
+ expect(result.with_filtered_backtrace(double("filter"))).to eql result
124
+ end
125
+
126
+ specify { expect( result.to_sym ).to eq :unknown }
127
+
128
+ specify { expect( result ).not_to be_passed }
129
+ specify { expect( result ).not_to be_failed }
130
+ specify { expect( result ).not_to be_undefined }
131
+ specify { expect( result ).to be_unknown }
132
+ specify { expect( result ).not_to be_skipped }
133
+ specify { expect( result ).not_to be_flaky }
134
+ end
135
+
136
+ describe Result::Raisable do
137
+ context "with or without backtrace" do
138
+ subject(:result) { Result::Raisable.new }
139
+
140
+ it "does nothing if step has no backtrace line" do
141
+ step = "does not respond_to?(:backtrace_line)"
142
+
143
+ expect( result.with_appended_backtrace(step).backtrace ).to eq(nil)
144
+ end
145
+ end
146
+
147
+ context "without backtrace" do
148
+ subject(:result) { Result::Raisable.new }
149
+
150
+ it "set the backtrace to the backtrace line of the step" do
151
+ step = double
152
+ expect( step ).to receive(:backtrace_line).and_return("step_line")
153
+
154
+ expect( result.with_appended_backtrace(step).backtrace ).to eq(["step_line"])
155
+ end
156
+
157
+ it "does nothing when filtering the backtrace" do
158
+ expect( result.with_filtered_backtrace(double) ).to equal result
159
+ end
160
+ end
161
+
162
+ context "with backtrace" do
163
+ subject(:result) { Result::Raisable.new("message", 0, "backtrace") }
164
+
165
+ it "appends the backtrace line of the step" do
166
+ step = double
167
+ expect( step ).to receive(:backtrace_line).and_return("step_line")
168
+
169
+ expect( result.with_appended_backtrace(step).backtrace ).to eq(["backtrace", "step_line"])
170
+ end
171
+
172
+ it "apply filters to the backtrace" do
173
+ filter_class = double
174
+ filter = double
175
+ filtered_result = double
176
+ expect( filter_class ).to receive(:new).with(result.exception).and_return(filter)
177
+ expect( filter ).to receive(:exception).and_return(filtered_result)
178
+
179
+ expect( result.with_filtered_backtrace(filter_class) ).to equal filtered_result
180
+ end
181
+ end
182
+ end
183
+
184
+ describe Result::Undefined do
185
+ subject(:result) { Result::Undefined.new }
186
+
187
+ it "describes itself to a visitor" do
188
+ expect( visitor ).to receive(:undefined).with(args)
189
+ expect( visitor ).to receive(:duration).with(an_unknown_duration, args)
190
+ result.describe_to(visitor, args)
191
+ end
192
+
193
+ specify { expect( result.to_sym ).to eq :undefined }
194
+
195
+ specify { expect( result ).not_to be_passed }
196
+ specify { expect( result ).not_to be_failed }
197
+ specify { expect( result ).to be_undefined }
198
+ specify { expect( result ).not_to be_unknown }
199
+ specify { expect( result ).not_to be_skipped }
200
+ specify { expect( result ).not_to be_flaky }
201
+
202
+ specify { expect( result ).to be_ok }
203
+ specify { expect( result.ok? ).to be_truthy }
204
+ be_strict = Result::StrictConfiguration.new([:undefined])
205
+ specify { expect( result.ok?(be_strict) ).to be_falsey }
206
+ end
207
+
208
+ describe Result::Skipped do
209
+ subject(:result) { Result::Skipped.new }
210
+
211
+ it "describes itself to a visitor" do
212
+ expect( visitor ).to receive(:skipped).with(args)
213
+ expect( visitor ).to receive(:duration).with(an_unknown_duration, args)
214
+ result.describe_to(visitor, args)
215
+ end
216
+
217
+ specify { expect( result.to_sym ).to eq :skipped }
218
+
219
+ specify { expect( result ).not_to be_passed }
220
+ specify { expect( result ).not_to be_failed }
221
+ specify { expect( result ).not_to be_undefined }
222
+ specify { expect( result ).not_to be_unknown }
223
+ specify { expect( result ).to be_skipped }
224
+ specify { expect( result ).not_to be_flaky }
225
+
226
+ specify { expect( result ).to be_ok }
227
+ specify { expect( result.ok? ).to be_truthy }
228
+ end
229
+
230
+ describe Result::Pending do
231
+ subject(:result) { Result::Pending.new }
232
+
233
+ it "describes itself to a visitor" do
234
+ expect( visitor ).to receive(:pending).with(result, args)
235
+ expect( visitor ).to receive(:duration).with(an_unknown_duration, args)
236
+ result.describe_to(visitor, args)
237
+ end
238
+
239
+ specify { expect( result.to_sym ).to eq :pending }
240
+
241
+ specify { expect( result ).not_to be_passed }
242
+ specify { expect( result ).not_to be_failed }
243
+ specify { expect( result ).not_to be_undefined }
244
+ specify { expect( result ).not_to be_unknown }
245
+ specify { expect( result ).not_to be_skipped }
246
+ specify { expect( result ).not_to be_flaky }
247
+ specify { expect( result ).to be_pending }
248
+
249
+ specify { expect( result ).to be_ok }
250
+ specify { expect( result.ok? ).to be_truthy }
251
+ be_strict = Result::StrictConfiguration.new([:pending])
252
+ specify { expect( result.ok?(be_strict) ).to be_falsey }
253
+ end
254
+
255
+ describe Result::Flaky do
256
+ specify { expect( Result::Flaky.ok?(false) ).to be_truthy }
257
+ specify { expect( Result::Flaky.ok?(true) ).to be_falsey }
258
+ end
259
+
260
+ describe Result::StrictConfiguration do
261
+ subject(:strict_configuration) { Result::StrictConfiguration.new}
262
+
263
+ describe '#set_strict' do
264
+ context 'no type argument' do
265
+ it 'sets all result types to the setting argument' do
266
+ strict_configuration.set_strict(true)
267
+ expect( strict_configuration.strict?(:undefined) ).to be_truthy
268
+ expect( strict_configuration.strict?(:pending) ).to be_truthy
269
+ expect( strict_configuration.strict?(:flaky) ).to be_truthy
270
+
271
+ strict_configuration.set_strict(false)
272
+ expect( strict_configuration.strict?(:undefined) ).to be_falsey
273
+ expect( strict_configuration.strict?(:pending) ).to be_falsey
274
+ expect( strict_configuration.strict?(:flaky) ).to be_falsey
275
+ end
276
+ end
277
+ context 'with type argument' do
278
+ it 'sets the specified result type to the setting argument' do
279
+ strict_configuration.set_strict(true, :undefined)
280
+ expect( strict_configuration.strict?(:undefined) ).to be_truthy
281
+ expect( strict_configuration.set?(:pending) ).to be_falsey
282
+ expect( strict_configuration.set?(:flaky) ).to be_falsey
283
+
284
+ strict_configuration.set_strict(false, :undefined)
285
+ expect( strict_configuration.strict?(:undefined) ).to be_falsey
286
+ expect( strict_configuration.set?(:pending) ).to be_falsey
287
+ expect( strict_configuration.set?(:flaky) ).to be_falsey
288
+ end
289
+ end
290
+ end
291
+
292
+ describe '#strict?' do
293
+ context 'no type argument' do
294
+ it 'returns true if any result type is set to strict' do
295
+ strict_configuration.set_strict(false, :pending)
296
+ expect( strict_configuration.strict? ).to be_falsey
297
+
298
+ strict_configuration.set_strict(true, :flaky)
299
+ expect( strict_configuration.strict? ).to be_truthy
300
+ end
301
+ end
302
+ context 'with type argument' do
303
+ it 'returns true if the specified result type is set to strict' do
304
+ strict_configuration.set_strict(false, :pending)
305
+ strict_configuration.set_strict(true, :flaky)
306
+
307
+ expect( strict_configuration.strict?(:undefined) ).to be_falsey
308
+ expect( strict_configuration.strict?(:pending) ).to be_falsey
309
+ expect( strict_configuration.strict?(:flaky) ).to be_truthy
310
+ end
311
+ end
312
+ end
313
+
314
+ describe '#merge!' do
315
+ let(:merged_configuration) { Result::StrictConfiguration.new }
316
+ it 'sets the not default values from the argument accordingly' do
317
+ strict_configuration.set_strict(false, :undefined)
318
+ strict_configuration.set_strict(false, :pending)
319
+ strict_configuration.set_strict(true, :flaky)
320
+ merged_configuration.set_strict(true, :pending)
321
+ merged_configuration.set_strict(false, :flaky)
322
+ strict_configuration.merge!(merged_configuration)
323
+
324
+ expect( strict_configuration.strict?(:undefined) ).to be_falsey
325
+ expect( strict_configuration.strict?(:pending) ).to be_truthy
326
+ expect( strict_configuration.strict?(:flaky) ).to be_falsey
327
+ end
328
+ end
329
+ end
330
+
331
+ describe Result::Summary do
332
+ let(:summary) { Result::Summary.new }
333
+ let(:failed) { Result::Failed.new(Result::Duration.new(10), exception) }
334
+ let(:passed) { Result::Passed.new(Result::Duration.new(11)) }
335
+ let(:skipped) { Result::Skipped.new }
336
+ let(:unknown) { Result::Unknown.new }
337
+ let(:pending) { Result::Pending.new }
338
+ let(:undefined) { Result::Undefined.new }
339
+ let(:exception) { StandardError.new }
340
+
341
+ it "counts failed results" do
342
+ failed.describe_to summary
343
+ expect( summary.total_failed ).to eq 1
344
+ expect( summary.total(:failed) ).to eq 1
345
+ expect( summary.total ).to eq 1
346
+ end
347
+
348
+ it "counts passed results" do
349
+ passed.describe_to summary
350
+ expect( summary.total_passed ).to eq 1
351
+ expect( summary.total(:passed) ).to eq 1
352
+ expect( summary.total ).to eq 1
353
+ end
354
+
355
+ it "counts skipped results" do
356
+ skipped.describe_to summary
357
+ expect( summary.total_skipped ).to eq 1
358
+ expect( summary.total(:skipped) ).to eq 1
359
+ expect( summary.total ).to eq 1
360
+ end
361
+
362
+ it "counts undefined results" do
363
+ undefined.describe_to summary
364
+ expect( summary.total_undefined ).to eq 1
365
+ expect( summary.total(:undefined) ).to eq 1
366
+ expect( summary.total ).to eq 1
367
+ end
368
+
369
+ it "counts abitrary raisable results" do
370
+ flickering = Class.new(Result::Raisable) do
371
+ def describe_to(visitor, *args)
372
+ visitor.flickering(*args)
373
+ end
374
+ end
375
+
376
+ flickering.new.describe_to summary
377
+ expect( summary.total_flickering ).to eq 1
378
+ expect( summary.total(:flickering) ).to eq 1
379
+ expect( summary.total ).to eq 1
380
+ end
381
+
382
+ it "returns zero for a status where no messges have been received" do
383
+ expect( summary.total_passed ).to eq 0
384
+ expect( summary.total(:passed) ).to eq 0
385
+ expect( summary.total_ponies ).to eq 0
386
+ expect( summary.total(:ponies) ).to eq 0
387
+ end
388
+
389
+ it "doesn't count unknown results" do
390
+ unknown.describe_to summary
391
+ expect( summary.total ).to eq 0
392
+ end
393
+
394
+ it "counts combinations" do
395
+ [passed, passed, failed, skipped, undefined].each { |r| r.describe_to summary }
396
+ expect( summary.total ).to eq 5
397
+ expect( summary.total_passed ).to eq 2
398
+ expect( summary.total_failed ).to eq 1
399
+ expect( summary.total_skipped ).to eq 1
400
+ expect( summary.total_undefined ).to eq 1
401
+ end
402
+
403
+ it "records durations" do
404
+ [passed, failed].each { |r| r.describe_to summary }
405
+ expect( summary.durations[0] ).to be_duration 11
406
+ expect( summary.durations[1] ).to be_duration 10
407
+ end
408
+
409
+ it "records exceptions" do
410
+ [passed, failed].each { |r| r.describe_to summary }
411
+ expect( summary.exceptions ).to eq [exception]
412
+ end
413
+
414
+ context "ok? result" do
415
+ it "passed result is ok" do
416
+ passed.describe_to summary
417
+ expect( summary.ok? ).to be true
418
+ end
419
+
420
+ it "skipped result is ok" do
421
+ skipped.describe_to summary
422
+ expect( summary.ok? ).to be true
423
+ end
424
+
425
+ it "failed result is not ok" do
426
+ failed.describe_to summary
427
+ expect( summary.ok? ).to be false
428
+ end
429
+
430
+ it "pending result is ok if not strict" do
431
+ pending.describe_to summary
432
+ expect( summary.ok? ).to be true
433
+ be_strict = Result::StrictConfiguration.new([:pending])
434
+ expect( summary.ok?(be_strict) ).to be false
435
+ end
436
+
437
+ it "undefined result is ok if not strict" do
438
+ undefined.describe_to summary
439
+ expect( summary.ok? ).to be true
440
+ be_strict = Result::StrictConfiguration.new([:undefined])
441
+ expect( summary.ok?(be_strict) ).to be false
442
+ end
443
+
444
+ it "flaky result is ok if not strict" do
445
+ summary.flaky
446
+ expect( summary.ok? ).to be true
447
+ be_strict = Result::StrictConfiguration.new([:flaky])
448
+ expect( summary.ok?(be_strict) ).to be false
449
+ end
450
+ end
451
+ end
452
+
453
+ describe Result::Duration do
454
+ subject(:duration) { Result::Duration.new(10) }
455
+
456
+ it "#nanoseconds can be accessed in #tap" do
457
+ expect( duration.tap { |duration| @duration = duration.nanoseconds } ).to eq duration
458
+ expect( @duration ).to eq 10
459
+ end
460
+ end
461
+
462
+ describe Result::UnknownDuration do
463
+ subject(:duration) { Result::UnknownDuration.new }
464
+
465
+ it "#tap does not execute the passed block" do
466
+ expect( duration.tap { raise "tap executed block" } ).to eq duration
467
+ end
468
+
469
+ it "accessing #nanoseconds outside #tap block raises exception" do
470
+ expect { duration.nanoseconds }.to raise_error(RuntimeError)
471
+ end
472
+ end
473
+ end
474
+ end