cucumber-core 4.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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