cucumber-core 3.0.0 → 3.1.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.
- checksums.yaml +4 -4
- data/lib/cucumber/core/version.rb +1 -1
- metadata +19 -85
- data/.coveralls.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -48
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -39
- data/.rspec +0 -1
- data/.ruby-gemset +0 -1
- data/.travis.yml +0 -30
- data/.yardopts +0 -6
- data/Gemfile +0 -2
- data/Rakefile +0 -28
- data/cucumber-core.gemspec +0 -36
- data/spec/capture_warnings.rb +0 -74
- data/spec/coverage.rb +0 -11
- data/spec/cucumber/core/ast/background_spec.rb +0 -11
- data/spec/cucumber/core/ast/data_table_spec.rb +0 -81
- data/spec/cucumber/core/ast/doc_string_spec.rb +0 -114
- data/spec/cucumber/core/ast/empty_multiline_argument_spec.rb +0 -28
- data/spec/cucumber/core/ast/examples_table_spec.rb +0 -113
- data/spec/cucumber/core/ast/location_spec.rb +0 -199
- data/spec/cucumber/core/ast/outline_step_spec.rb +0 -93
- data/spec/cucumber/core/ast/step_spec.rb +0 -174
- data/spec/cucumber/core/compiler_spec.rb +0 -267
- data/spec/cucumber/core/event_bus_spec.rb +0 -163
- data/spec/cucumber/core/event_spec.rb +0 -40
- data/spec/cucumber/core/filter_spec.rb +0 -101
- data/spec/cucumber/core/gherkin/parser_spec.rb +0 -261
- data/spec/cucumber/core/gherkin/writer_spec.rb +0 -333
- data/spec/cucumber/core/report/summary_spec.rb +0 -175
- data/spec/cucumber/core/test/action_spec.rb +0 -154
- data/spec/cucumber/core/test/case_spec.rb +0 -316
- data/spec/cucumber/core/test/duration_matcher.rb +0 -20
- data/spec/cucumber/core/test/filters/locations_filter_spec.rb +0 -405
- data/spec/cucumber/core/test/result_spec.rb +0 -474
- data/spec/cucumber/core/test/runner_spec.rb +0 -310
- data/spec/cucumber/core/test/step_spec.rb +0 -98
- data/spec/cucumber/core/test/timer_spec.rb +0 -25
- data/spec/cucumber/core_spec.rb +0 -262
- data/spec/readme_spec.rb +0 -37
- data/spec/report_api_spy.rb +0 -25
@@ -1,20 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
# frozen_string_literal: true
|
3
|
-
require 'cucumber/core/test/result'
|
4
|
-
require 'rspec/expectations'
|
5
|
-
|
6
|
-
module Cucumber::Core::Test
|
7
|
-
RSpec::Matchers.define :be_duration do |expected|
|
8
|
-
match do |actual|
|
9
|
-
actual.tap { |duration| @nanoseconds = duration.nanoseconds }
|
10
|
-
@nanoseconds == expected
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
RSpec::Matchers.define :an_unknown_duration do
|
15
|
-
match do |actual|
|
16
|
-
actual.tap { raise "#tap block was executed, not an UnknownDuration" }
|
17
|
-
expect(actual).to respond_to(:nanoseconds)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,405 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
require 'cucumber/core/gherkin/writer'
|
4
|
-
require 'cucumber/core'
|
5
|
-
require 'cucumber/core/test/filters/locations_filter'
|
6
|
-
require 'timeout'
|
7
|
-
require 'cucumber/core/ast/location'
|
8
|
-
|
9
|
-
module Cucumber::Core
|
10
|
-
describe Test::LocationsFilter do
|
11
|
-
include Cucumber::Core::Gherkin::Writer
|
12
|
-
include Cucumber::Core
|
13
|
-
|
14
|
-
let(:receiver) { SpyReceiver.new }
|
15
|
-
|
16
|
-
let(:doc) do
|
17
|
-
gherkin('features/test.feature') do
|
18
|
-
feature do
|
19
|
-
scenario 'x' do
|
20
|
-
step 'a step'
|
21
|
-
end
|
22
|
-
|
23
|
-
scenario 'y' do
|
24
|
-
step 'a step'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
it "sorts by the given locations" do
|
31
|
-
locations = [
|
32
|
-
Ast::Location.new('features/test.feature', 6),
|
33
|
-
Ast::Location.new('features/test.feature', 3)
|
34
|
-
]
|
35
|
-
filter = Test::LocationsFilter.new(locations)
|
36
|
-
compile [doc], receiver, [filter]
|
37
|
-
expect(receiver.test_case_locations).to eq locations
|
38
|
-
end
|
39
|
-
|
40
|
-
it "works with wildcard locations" do
|
41
|
-
locations = [
|
42
|
-
Ast::Location.new('features/test.feature')
|
43
|
-
]
|
44
|
-
filter = Test::LocationsFilter.new(locations)
|
45
|
-
compile [doc], receiver, [filter]
|
46
|
-
expect(receiver.test_case_locations).to eq [
|
47
|
-
Ast::Location.new('features/test.feature', 3),
|
48
|
-
Ast::Location.new('features/test.feature', 6)
|
49
|
-
]
|
50
|
-
end
|
51
|
-
|
52
|
-
it "filters out scenarios that don't match" do
|
53
|
-
locations = [
|
54
|
-
Ast::Location.new('features/test.feature', 3)
|
55
|
-
]
|
56
|
-
filter = Test::LocationsFilter.new(locations)
|
57
|
-
compile [doc], receiver, [filter]
|
58
|
-
expect(receiver.test_case_locations).to eq locations
|
59
|
-
end
|
60
|
-
|
61
|
-
describe "matching location" do
|
62
|
-
let(:file) { 'features/path/to/the.feature' }
|
63
|
-
|
64
|
-
let(:test_cases) do
|
65
|
-
receiver = double.as_null_object
|
66
|
-
result = []
|
67
|
-
allow(receiver).to receive(:test_case) { |test_case| result << test_case }
|
68
|
-
compile [doc], receiver
|
69
|
-
result
|
70
|
-
end
|
71
|
-
|
72
|
-
context "for a scenario" do
|
73
|
-
let(:doc) do
|
74
|
-
Gherkin::Document.new(file, <<-END)
|
75
|
-
Feature:
|
76
|
-
|
77
|
-
Scenario: one
|
78
|
-
Given one a
|
79
|
-
|
80
|
-
# comment
|
81
|
-
@tags
|
82
|
-
Scenario: two
|
83
|
-
Given two a
|
84
|
-
And two b
|
85
|
-
|
86
|
-
Scenario: three
|
87
|
-
Given three b
|
88
|
-
|
89
|
-
Scenario: with docstring
|
90
|
-
Given a docstring
|
91
|
-
"""
|
92
|
-
this is a docstring
|
93
|
-
"""
|
94
|
-
|
95
|
-
Scenario: with a table
|
96
|
-
Given a table
|
97
|
-
| a | b |
|
98
|
-
| 1 | 2 |
|
99
|
-
| 3 | 4 |
|
100
|
-
|
101
|
-
END
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_case_named(name)
|
105
|
-
test_cases.find { |c| c.name == name }
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'matches the precise location of the scenario' do
|
109
|
-
location = test_case_named('two').location
|
110
|
-
filter = Test::LocationsFilter.new([location])
|
111
|
-
compile [doc], receiver, [filter]
|
112
|
-
expect(receiver.test_case_locations).to eq [test_case_named('two').location]
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'matches multiple locations' do
|
116
|
-
good_location = Ast::Location.new(file, 8)
|
117
|
-
bad_location = Ast::Location.new(file, 5)
|
118
|
-
filter = Test::LocationsFilter.new([good_location, bad_location])
|
119
|
-
compile [doc], receiver, [filter]
|
120
|
-
expect(receiver.test_case_locations).to eq [test_case_named('two').location]
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'matches a location on the last step of the scenario' do
|
124
|
-
location = Ast::Location.new(file, 10)
|
125
|
-
filter = Test::LocationsFilter.new([location])
|
126
|
-
compile [doc], receiver, [filter]
|
127
|
-
expect(receiver.test_case_locations).to eq [test_case_named('two').location]
|
128
|
-
end
|
129
|
-
|
130
|
-
it "matches a location on the scenario's comment" do
|
131
|
-
location = Ast::Location.new(file, 6)
|
132
|
-
filter = Test::LocationsFilter.new([location])
|
133
|
-
compile [doc], receiver, [filter]
|
134
|
-
expect(receiver.test_case_locations).to eq [test_case_named('two').location]
|
135
|
-
end
|
136
|
-
|
137
|
-
it "matches a location on the scenario's tags" do
|
138
|
-
location = Ast::Location.new(file, 7)
|
139
|
-
filter = Test::LocationsFilter.new([location])
|
140
|
-
compile [doc], receiver, [filter]
|
141
|
-
expect(receiver.test_case_locations).to eq [test_case_named('two').location]
|
142
|
-
end
|
143
|
-
|
144
|
-
it "doesn't match a location after the last step of the scenario" do
|
145
|
-
location = Ast::Location.new(file, 11)
|
146
|
-
filter = Test::LocationsFilter.new([location])
|
147
|
-
compile [doc], receiver, [filter]
|
148
|
-
expect(receiver.test_case_locations).to eq []
|
149
|
-
end
|
150
|
-
|
151
|
-
it "doesn't match a location before the scenario" do
|
152
|
-
location = Ast::Location.new(file, 5)
|
153
|
-
filter = Test::LocationsFilter.new([location])
|
154
|
-
compile [doc], receiver, [filter]
|
155
|
-
expect(receiver.test_case_locations).to eq []
|
156
|
-
end
|
157
|
-
|
158
|
-
context "with a docstring" do
|
159
|
-
let(:test_case) do
|
160
|
-
test_cases.find { |c| c.name == 'with docstring' }
|
161
|
-
end
|
162
|
-
|
163
|
-
it "matches a location at the start the docstring" do
|
164
|
-
location = Ast::Location.new(file, 17)
|
165
|
-
filter = Test::LocationsFilter.new([location])
|
166
|
-
compile [doc], receiver, [filter]
|
167
|
-
expect(receiver.test_case_locations).to eq [test_case.location]
|
168
|
-
end
|
169
|
-
|
170
|
-
it "matches a location in the middle of the docstring" do
|
171
|
-
location = Ast::Location.new(file, 18)
|
172
|
-
filter = Test::LocationsFilter.new([location])
|
173
|
-
compile [doc], receiver, [filter]
|
174
|
-
expect(receiver.test_case_locations).to eq [test_case.location]
|
175
|
-
end
|
176
|
-
|
177
|
-
it "matches a location at the end of the docstring" do
|
178
|
-
location = Ast::Location.new(file, 19)
|
179
|
-
filter = Test::LocationsFilter.new([location])
|
180
|
-
compile [doc], receiver, [filter]
|
181
|
-
expect(receiver.test_case_locations).to eq [test_case.location]
|
182
|
-
end
|
183
|
-
|
184
|
-
it "does not match a location after the docstring" do
|
185
|
-
location = Ast::Location.new(file, 20)
|
186
|
-
filter = Test::LocationsFilter.new([location])
|
187
|
-
compile [doc], receiver, [filter]
|
188
|
-
expect(receiver.test_case_locations).to eq []
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
context "with a table" do
|
193
|
-
let(:test_case) do
|
194
|
-
test_cases.find { |c| c.name == 'with a table' }
|
195
|
-
end
|
196
|
-
|
197
|
-
it "matches a location at the start of the table" do
|
198
|
-
location = Ast::Location.new(file, 23)
|
199
|
-
expect( test_case.match_locations?([location]) ).to be_truthy
|
200
|
-
end
|
201
|
-
|
202
|
-
it "matches a location in the middle of the table" do
|
203
|
-
location = Ast::Location.new(file, 24)
|
204
|
-
expect( test_case.match_locations?([location]) ).to be_truthy
|
205
|
-
end
|
206
|
-
|
207
|
-
it "matches a location at the end of the table" do
|
208
|
-
location = Ast::Location.new(file, 25)
|
209
|
-
expect( test_case.match_locations?([location]) ).to be_truthy
|
210
|
-
end
|
211
|
-
|
212
|
-
it "does not match a location after the table" do
|
213
|
-
location = Ast::Location.new(file, 26)
|
214
|
-
expect( test_case.match_locations?([location]) ).to be_falsey
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
context "with duplicate locations in the filter" do
|
219
|
-
it "matches each test case only once" do
|
220
|
-
location_tc_two = test_case_named('two').location
|
221
|
-
location_tc_one = test_case_named('one').location
|
222
|
-
location_last_step_tc_two = Ast::Location.new(file, 10)
|
223
|
-
filter = Test::LocationsFilter.new([location_tc_two, location_tc_one, location_last_step_tc_two])
|
224
|
-
compile [doc], receiver, [filter]
|
225
|
-
expect(receiver.test_case_locations).to eq [test_case_named('two').location, location_tc_one = test_case_named('one').location]
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
context "for a scenario outline" do
|
231
|
-
let(:doc) do
|
232
|
-
Gherkin::Document.new(file, <<-END)
|
233
|
-
Feature:
|
234
|
-
|
235
|
-
Scenario: one
|
236
|
-
Given one a
|
237
|
-
|
238
|
-
# comment on line 6
|
239
|
-
@tags-on-line-7
|
240
|
-
Scenario Outline: two
|
241
|
-
Given two a
|
242
|
-
And two <arg>
|
243
|
-
"""
|
244
|
-
docstring
|
245
|
-
"""
|
246
|
-
|
247
|
-
# comment on line 15
|
248
|
-
@tags-on-line-16
|
249
|
-
Examples: x1
|
250
|
-
| arg |
|
251
|
-
| b |
|
252
|
-
|
253
|
-
Examples: x2
|
254
|
-
| arg |
|
255
|
-
| c |
|
256
|
-
| d |
|
257
|
-
|
258
|
-
Scenario: three
|
259
|
-
Given three b
|
260
|
-
END
|
261
|
-
end
|
262
|
-
|
263
|
-
let(:test_case) do
|
264
|
-
test_cases.find { |c| c.name == "two, x1 (#1)" }
|
265
|
-
end
|
266
|
-
|
267
|
-
it "matches row location to the test case of the row" do
|
268
|
-
locations = [
|
269
|
-
Ast::Location.new(file, 19),
|
270
|
-
]
|
271
|
-
filter = Test::LocationsFilter.new(locations)
|
272
|
-
compile [doc], receiver, [filter]
|
273
|
-
expect(receiver.test_case_locations).to eq [test_case.location]
|
274
|
-
end
|
275
|
-
|
276
|
-
it "matches examples location with all test cases of the table" do
|
277
|
-
locations = [
|
278
|
-
Ast::Location.new(file, 21),
|
279
|
-
]
|
280
|
-
filter = Test::LocationsFilter.new(locations)
|
281
|
-
compile [doc], receiver, [filter]
|
282
|
-
expect(receiver.test_case_locations.map(&:line)).to eq [23, 24]
|
283
|
-
end
|
284
|
-
|
285
|
-
it "matches outline location with the all test cases of all the tables" do
|
286
|
-
locations = [
|
287
|
-
Ast::Location.new(file, 8),
|
288
|
-
]
|
289
|
-
filter = Test::LocationsFilter.new(locations)
|
290
|
-
compile [doc], receiver, [filter]
|
291
|
-
expect(receiver.test_case_locations.map(&:line)).to eq [19, 23, 24]
|
292
|
-
end
|
293
|
-
|
294
|
-
it "matches outline step location the all test cases of all the tables" do
|
295
|
-
locations = [
|
296
|
-
Ast::Location.new(file, 10)
|
297
|
-
]
|
298
|
-
filter = Test::LocationsFilter.new(locations)
|
299
|
-
compile [doc], receiver, [filter]
|
300
|
-
expect(receiver.test_case_locations.map(&:line)).to eq [19, 23, 24]
|
301
|
-
end
|
302
|
-
|
303
|
-
it 'matches a location on a step of the scenario outline' do
|
304
|
-
location = Ast::Location.new(file, 10)
|
305
|
-
filter = Test::LocationsFilter.new([location])
|
306
|
-
compile [doc], receiver, [filter]
|
307
|
-
expect(receiver.test_case_locations).to include test_case.location
|
308
|
-
end
|
309
|
-
|
310
|
-
it 'matches a location on the docstring of a step of the scenario outline' do
|
311
|
-
location = Ast::Location.new(file, 12)
|
312
|
-
filter = Test::LocationsFilter.new([location])
|
313
|
-
compile [doc], receiver, [filter]
|
314
|
-
expect(receiver.test_case_locations).to include test_case.location
|
315
|
-
end
|
316
|
-
|
317
|
-
it "matches a location on the scenario outline's comment" do
|
318
|
-
location = Ast::Location.new(file, 6)
|
319
|
-
filter = Test::LocationsFilter.new([location])
|
320
|
-
compile [doc], receiver, [filter]
|
321
|
-
expect(receiver.test_case_locations).to include test_case.location
|
322
|
-
end
|
323
|
-
|
324
|
-
it "matches a location on the scenario outline's tags" do
|
325
|
-
location = Ast::Location.new(file, 7)
|
326
|
-
filter = Test::LocationsFilter.new([location])
|
327
|
-
compile [doc], receiver, [filter]
|
328
|
-
expect(receiver.test_case_locations).to include test_case.location
|
329
|
-
end
|
330
|
-
|
331
|
-
it "doesn't match a location after the last row of the examples table" do
|
332
|
-
location = Ast::Location.new(file, 20)
|
333
|
-
filter = Test::LocationsFilter.new([location])
|
334
|
-
compile [doc], receiver, [filter]
|
335
|
-
expect(receiver.test_case_locations).to eq []
|
336
|
-
end
|
337
|
-
|
338
|
-
it "doesn't match a location before the scenario outline" do
|
339
|
-
location = Ast::Location.new(file, 5)
|
340
|
-
filter = Test::LocationsFilter.new([location])
|
341
|
-
compile [doc], receiver, [filter]
|
342
|
-
expect(receiver.test_case_locations).to eq []
|
343
|
-
end
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
context "under load", slow: true do
|
348
|
-
num_features = 50
|
349
|
-
num_scenarios_per_feature = 50
|
350
|
-
|
351
|
-
let(:docs) do
|
352
|
-
(1..num_features).map do |i|
|
353
|
-
gherkin("features/test_#{i}.feature") do
|
354
|
-
feature do
|
355
|
-
(1..num_scenarios_per_feature).each do |j|
|
356
|
-
scenario "scenario #{j}" do
|
357
|
-
step
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
num_locations = num_features
|
366
|
-
let(:locations) do
|
367
|
-
(1..num_locations).map do |i|
|
368
|
-
(1..num_scenarios_per_feature).map do |j|
|
369
|
-
line = 3 + (j - 1) * 3
|
370
|
-
Ast::Location.new("features/test_#{i}.feature", line)
|
371
|
-
end
|
372
|
-
end.flatten
|
373
|
-
end
|
374
|
-
|
375
|
-
max_duration_ms = 10000
|
376
|
-
max_duration_ms = max_duration_ms * 2.5 if defined?(JRUBY_VERSION)
|
377
|
-
it "filters #{num_features * num_scenarios_per_feature} test cases within #{max_duration_ms}ms" do
|
378
|
-
filter = Test::LocationsFilter.new(locations)
|
379
|
-
Timeout.timeout(max_duration_ms / 1000.0) do
|
380
|
-
compile docs, receiver, [filter]
|
381
|
-
end
|
382
|
-
expect(receiver.test_cases.length).to eq num_features * num_scenarios_per_feature
|
383
|
-
end
|
384
|
-
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
class SpyReceiver
|
389
|
-
def test_case(test_case)
|
390
|
-
test_cases << test_case
|
391
|
-
end
|
392
|
-
|
393
|
-
def done
|
394
|
-
end
|
395
|
-
|
396
|
-
def test_case_locations
|
397
|
-
test_cases.map(&:location)
|
398
|
-
end
|
399
|
-
|
400
|
-
def test_cases
|
401
|
-
@test_cases ||= []
|
402
|
-
end
|
403
|
-
|
404
|
-
end
|
405
|
-
end
|
@@ -1,474 +0,0 @@
|
|
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
|