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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +7 -1
- data/README.md +1 -2
- data/lib/cucumber/core/compiler.rb +23 -21
- data/lib/cucumber/core/event_bus.rb +1 -1
- data/lib/cucumber/core/gherkin/parser.rb +4 -5
- data/lib/cucumber/core/version.rb +1 -1
- data/spec/capture_warnings.rb +74 -0
- data/spec/coverage.rb +11 -0
- data/spec/cucumber/core/compiler_spec.rb +178 -0
- data/spec/cucumber/core/event_bus_spec.rb +163 -0
- data/spec/cucumber/core/event_spec.rb +40 -0
- data/spec/cucumber/core/filter_spec.rb +101 -0
- data/spec/cucumber/core/gherkin/parser_spec.rb +95 -0
- data/spec/cucumber/core/gherkin/writer_spec.rb +333 -0
- data/spec/cucumber/core/report/summary_spec.rb +167 -0
- data/spec/cucumber/core/test/action_spec.rb +154 -0
- data/spec/cucumber/core/test/case_spec.rb +126 -0
- data/spec/cucumber/core/test/data_table_spec.rb +81 -0
- data/spec/cucumber/core/test/doc_string_spec.rb +114 -0
- data/spec/cucumber/core/test/duration_matcher.rb +20 -0
- data/spec/cucumber/core/test/empty_multiline_argument_spec.rb +28 -0
- data/spec/cucumber/core/test/filters/locations_filter_spec.rb +271 -0
- data/spec/cucumber/core/test/location_spec.rb +126 -0
- data/spec/cucumber/core/test/result_spec.rb +474 -0
- data/spec/cucumber/core/test/runner_spec.rb +318 -0
- data/spec/cucumber/core/test/step_spec.rb +87 -0
- data/spec/cucumber/core/test/timer_spec.rb +25 -0
- data/spec/cucumber/core_spec.rb +262 -0
- data/spec/report_api_spy.rb +25 -0
- metadata +83 -14
@@ -0,0 +1,318 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'cucumber/core/test/runner'
|
3
|
+
require 'cucumber/core/test/case'
|
4
|
+
require 'cucumber/core/test/step'
|
5
|
+
require 'cucumber/core/test/duration_matcher'
|
6
|
+
|
7
|
+
module Cucumber::Core::Test
|
8
|
+
describe Runner do
|
9
|
+
|
10
|
+
let(:name) { double }
|
11
|
+
let(:location) { double }
|
12
|
+
let(:tags) { double }
|
13
|
+
let(:language) { double }
|
14
|
+
let(:test_case) { Case.new(name, test_steps, location, tags, language) }
|
15
|
+
let(:text) { double }
|
16
|
+
let(:runner) { Runner.new(event_bus) }
|
17
|
+
let(:event_bus) { double.as_null_object }
|
18
|
+
let(:passing) { Step.new(text, location, location).with_action {} }
|
19
|
+
let(:failing) { Step.new(text, location, location).with_action { raise exception } }
|
20
|
+
let(:pending) { Step.new(text, location, location).with_action { raise Result::Pending.new("TODO") } }
|
21
|
+
let(:skipping) { Step.new(text, location, location).with_action { raise Result::Skipped.new } }
|
22
|
+
let(:undefined) { Step.new(text, location, location) }
|
23
|
+
let(:exception) { StandardError.new('test error') }
|
24
|
+
|
25
|
+
before do
|
26
|
+
allow( event_bus ).to receive(:test_case_started)
|
27
|
+
allow( text ).to receive(:empty?)
|
28
|
+
end
|
29
|
+
|
30
|
+
context "reporting the duration of a test case" do
|
31
|
+
before do
|
32
|
+
allow( Timer::MonotonicTime ).to receive(:time_in_nanoseconds).and_return(525702744080000, 525702744080001)
|
33
|
+
end
|
34
|
+
|
35
|
+
context "for a passing test case" do
|
36
|
+
let(:test_steps) { [passing] }
|
37
|
+
|
38
|
+
it "records the nanoseconds duration of the execution on the result" do
|
39
|
+
expect(event_bus).to receive(:test_case_finished) do |reported_test_case, result|
|
40
|
+
expect( result.duration ).to be_duration 1
|
41
|
+
end
|
42
|
+
test_case.describe_to runner
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "for a failing test case" do
|
47
|
+
let(:test_steps) { [failing] }
|
48
|
+
|
49
|
+
it "records the duration" do
|
50
|
+
expect(event_bus).to receive(:test_case_finished) do |reported_test_case, result|
|
51
|
+
expect(result.duration).to be_duration 1
|
52
|
+
end
|
53
|
+
test_case.describe_to runner
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "reporting the exception that failed a test case" do
|
59
|
+
let(:test_steps) { [failing] }
|
60
|
+
it "sets the exception on the result" do
|
61
|
+
allow(event_bus).to receive(:before_test_case)
|
62
|
+
expect(event_bus).to receive(:test_case_finished) do |reported_test_case, result|
|
63
|
+
expect( result.exception ).to eq exception
|
64
|
+
end
|
65
|
+
test_case.describe_to runner
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with a single case" do
|
70
|
+
context "without steps" do
|
71
|
+
let(:test_steps) { [] }
|
72
|
+
|
73
|
+
it "emits a test_case_started event before running the test case" do
|
74
|
+
expect(event_bus).to receive(:test_case_started).with(test_case)
|
75
|
+
test_case.describe_to runner
|
76
|
+
end
|
77
|
+
|
78
|
+
it "emits the test_case_finished event after running the the test case" do
|
79
|
+
expect(event_bus).to receive(:test_case_finished) do |reported_test_case, result|
|
80
|
+
expect( reported_test_case ).to eq test_case
|
81
|
+
expect( result ).to be_undefined
|
82
|
+
end
|
83
|
+
test_case.describe_to runner
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with steps' do
|
88
|
+
context 'that all pass' do
|
89
|
+
let(:test_steps) { [ passing, passing ] }
|
90
|
+
|
91
|
+
it 'emits the test_case_finished event with a passing result' do
|
92
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
93
|
+
expect( result ).to be_passed
|
94
|
+
end
|
95
|
+
test_case.describe_to runner
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'an undefined step' do
|
100
|
+
let(:test_steps) { [ undefined ] }
|
101
|
+
|
102
|
+
it 'emits the test_case_finished event with an undefined result' do
|
103
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
104
|
+
expect( result ).to be_undefined
|
105
|
+
end
|
106
|
+
|
107
|
+
test_case.describe_to runner
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'sets the message on the result' do
|
111
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
112
|
+
expect( result.message ).to eq("Undefined step: \"step name\"")
|
113
|
+
end
|
114
|
+
allow( undefined ).to receive(:text).and_return('step name')
|
115
|
+
|
116
|
+
test_case.describe_to runner
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'appends the backtrace of the result' do
|
120
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
121
|
+
expect( result.backtrace ).to eq(["step line"])
|
122
|
+
end
|
123
|
+
expect( undefined ).to receive(:backtrace_line).and_return('step line')
|
124
|
+
|
125
|
+
test_case.describe_to runner
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'a pending step' do
|
130
|
+
let(:test_steps) { [ pending ] }
|
131
|
+
|
132
|
+
it 'emits the test_case_finished event with a pending result' do
|
133
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
134
|
+
expect( result ).to be_pending
|
135
|
+
end
|
136
|
+
test_case.describe_to runner
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'appends the backtrace of the result' do
|
140
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
141
|
+
expect( result.backtrace.last ).to eq("step line")
|
142
|
+
end
|
143
|
+
expect( pending ).to receive(:backtrace_line).and_return('step line')
|
144
|
+
|
145
|
+
test_case.describe_to runner
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "a skipping step" do
|
150
|
+
let(:test_steps) { [skipping] }
|
151
|
+
|
152
|
+
it "emits the test_case_finished event with a skipped result" do
|
153
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
154
|
+
expect( result ).to be_skipped
|
155
|
+
end
|
156
|
+
test_case.describe_to runner
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'appends the backtrace of the result' do
|
160
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
161
|
+
expect( result.backtrace.last ).to eq("step line")
|
162
|
+
end
|
163
|
+
expect( skipping ).to receive(:backtrace_line).and_return('step line')
|
164
|
+
|
165
|
+
test_case.describe_to runner
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'that fail' do
|
170
|
+
let(:test_steps) { [ failing ] }
|
171
|
+
|
172
|
+
it 'emits the test_case_finished event with a failing result' do
|
173
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
174
|
+
expect( result ).to be_failed
|
175
|
+
end
|
176
|
+
test_case.describe_to runner
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'appends the backtrace of the exception of the result' do
|
180
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
181
|
+
expect( result.exception.backtrace.last ).to eq("step line")
|
182
|
+
end
|
183
|
+
expect( failing ).to receive(:backtrace_line).and_return('step line')
|
184
|
+
|
185
|
+
test_case.describe_to runner
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'where the first step fails' do
|
190
|
+
let(:test_steps) { [ failing, passing ] }
|
191
|
+
|
192
|
+
it 'emits the test_step_finished event with a failed result' do
|
193
|
+
expect(event_bus).to receive(:test_step_finished).with(failing, anything) do |test_step, result|
|
194
|
+
expect( result ).to be_failed
|
195
|
+
end
|
196
|
+
test_case.describe_to runner
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'emits a test_step_finished event with a skipped result' do
|
200
|
+
expect(event_bus).to receive(:test_step_finished).with(passing, anything) do |test_step, result|
|
201
|
+
expect( result ).to be_skipped
|
202
|
+
end
|
203
|
+
test_case.describe_to runner
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'emits a test_case_finished event with a failed result' do
|
207
|
+
expect(event_bus).to receive(:test_case_finished) do |test_case, result|
|
208
|
+
expect( result ).to be_failed
|
209
|
+
expect( result.exception ).to eq exception
|
210
|
+
end
|
211
|
+
test_case.describe_to runner
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'skips, rather than executing the second step' do
|
215
|
+
expect( passing ).not_to receive(:execute)
|
216
|
+
expect( passing ).to receive(:skip).and_return(Result::Skipped.new)
|
217
|
+
test_case.describe_to runner
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'with multiple test cases' do
|
225
|
+
context 'when the first test case fails' do
|
226
|
+
let(:first_test_case) { Case.new(name, [failing], location, tags, language) }
|
227
|
+
let(:last_test_case) { Case.new(name, [passing], location, tags, language) }
|
228
|
+
let(:test_cases) { [first_test_case, last_test_case] }
|
229
|
+
|
230
|
+
it 'reports the results correctly for the following test case' do
|
231
|
+
expect(event_bus).to receive(:test_case_finished) { |reported_test_case, result|
|
232
|
+
expect(result).to be_failed if reported_test_case.equal?(first_test_case)
|
233
|
+
expect(result).to be_passed if reported_test_case.equal?(last_test_case)
|
234
|
+
}.twice
|
235
|
+
|
236
|
+
test_cases.each { |c| c.describe_to runner }
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "passing latest result to a mapping" do
|
242
|
+
it "passes a Failed result when the scenario is failing" do
|
243
|
+
result_spy = nil
|
244
|
+
hook_mapping = UnskippableAction.new do |last_result|
|
245
|
+
result_spy = last_result
|
246
|
+
end
|
247
|
+
after_hook = HookStep.new(text, location, hook_mapping)
|
248
|
+
failing_step = Step.new(text, location).with_action { fail }
|
249
|
+
test_case = Case.new(name, [failing_step, after_hook], location, tags, language)
|
250
|
+
test_case.describe_to runner
|
251
|
+
expect(result_spy).to be_failed
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
require 'cucumber/core/test/around_hook'
|
256
|
+
context "with around hooks" do
|
257
|
+
it "passes normally when around hooks don't fail" do
|
258
|
+
around_hook = AroundHook.new { |block| block.call }
|
259
|
+
passing_step = Step.new(text, location, location).with_action {}
|
260
|
+
test_case = Case.new(name, [passing_step], location, tags, language, [around_hook])
|
261
|
+
expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
|
262
|
+
expect(result).to be_passed
|
263
|
+
end
|
264
|
+
test_case.describe_to runner
|
265
|
+
end
|
266
|
+
|
267
|
+
it "gets a failed result if the Around hook fails before the test case is run" do
|
268
|
+
around_hook = AroundHook.new { |block| raise exception }
|
269
|
+
passing_step = Step.new(text, location, location).with_action {}
|
270
|
+
test_case = Case.new(name, [passing_step], location, tags, language, [around_hook])
|
271
|
+
expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
|
272
|
+
expect(result).to be_failed
|
273
|
+
expect(result.exception).to eq exception
|
274
|
+
end
|
275
|
+
test_case.describe_to runner
|
276
|
+
end
|
277
|
+
|
278
|
+
it "gets a failed result if the Around hook fails after the test case is run" do
|
279
|
+
around_hook = AroundHook.new { |block| block.call; raise exception }
|
280
|
+
passing_step = Step.new(text, location, location).with_action {}
|
281
|
+
test_case = Case.new(name, [passing_step], location, tags, language, [around_hook])
|
282
|
+
expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
|
283
|
+
expect(result).to be_failed
|
284
|
+
expect(result.exception).to eq exception
|
285
|
+
end
|
286
|
+
test_case.describe_to runner
|
287
|
+
end
|
288
|
+
|
289
|
+
it "fails when a step fails if the around hook works" do
|
290
|
+
around_hook = AroundHook.new { |block| block.call }
|
291
|
+
failing_step = Step.new(text, location, location).with_action { raise exception }
|
292
|
+
test_case = Case.new(name, [failing_step], location, tags, language, [around_hook])
|
293
|
+
expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
|
294
|
+
expect(result).to be_failed
|
295
|
+
expect(result.exception).to eq exception
|
296
|
+
end
|
297
|
+
test_case.describe_to runner
|
298
|
+
end
|
299
|
+
|
300
|
+
it "sends after_test_step for a step interrupted by (a timeout in) the around hook" do
|
301
|
+
around_hook = AroundHook.new { |block| block.call; raise exception }
|
302
|
+
passing_step = Step.new(text, location, location).with_action {}
|
303
|
+
test_case = Case.new(name, [], location, tags, language, [around_hook])
|
304
|
+
allow(runner).to receive(:running_test_step).and_return(passing_step)
|
305
|
+
expect(event_bus).to receive(:test_step_finished).with(passing_step, anything) do |reported_test_case, result|
|
306
|
+
expect(result).to be_failed
|
307
|
+
expect(result.exception).to eq exception
|
308
|
+
end
|
309
|
+
expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
|
310
|
+
expect(result).to be_failed
|
311
|
+
expect(result.exception).to eq exception
|
312
|
+
end
|
313
|
+
test_case.describe_to runner
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|
318
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'cucumber/core/test/step'
|
3
|
+
|
4
|
+
module Cucumber::Core::Test
|
5
|
+
describe Step do
|
6
|
+
let(:text) { 'step text' }
|
7
|
+
let(:location) { double }
|
8
|
+
|
9
|
+
describe "describing itself" do
|
10
|
+
it "describes itself to a visitor" do
|
11
|
+
visitor = double
|
12
|
+
args = double
|
13
|
+
test_step = Step.new(text, location)
|
14
|
+
expect( visitor ).to receive(:test_step).with(test_step, args)
|
15
|
+
test_step.describe_to(visitor, args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "backtrace line" do
|
20
|
+
let(:text) { 'this step passes' }
|
21
|
+
let(:location) { Location.new('path/file.feature', 10) }
|
22
|
+
let(:test_step) { Step.new(text, location) }
|
23
|
+
|
24
|
+
it "knows how to form the backtrace line" do
|
25
|
+
expect( test_step.backtrace_line ).to eq("path/file.feature:10:in `this step passes'")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "executing" do
|
30
|
+
it "passes arbitrary arguments to the action's block" do
|
31
|
+
args_spy = nil
|
32
|
+
expected_args = [double, double]
|
33
|
+
test_step = Step.new(text, location).with_action do |*actual_args|
|
34
|
+
args_spy = actual_args
|
35
|
+
end
|
36
|
+
test_step.execute(*expected_args)
|
37
|
+
expect(args_spy).to eq expected_args
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when a passing action exists" do
|
41
|
+
it "returns a passing result" do
|
42
|
+
test_step = Step.new(text, location).with_action {}
|
43
|
+
expect( test_step.execute ).to be_passed
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when a failing action exists" do
|
48
|
+
let(:exception) { StandardError.new('oops') }
|
49
|
+
|
50
|
+
it "returns a failing result" do
|
51
|
+
test_step = Step.new(text, location).with_action { raise exception }
|
52
|
+
result = test_step.execute
|
53
|
+
expect( result ).to be_failed
|
54
|
+
expect( result.exception ).to eq exception
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with no action" do
|
59
|
+
it "returns an Undefined result" do
|
60
|
+
test_step = Step.new(text, location)
|
61
|
+
result = test_step.execute
|
62
|
+
expect( result ).to be_undefined
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "exposes the text and location of as attributes" do
|
68
|
+
test_step = Step.new(text, location)
|
69
|
+
expect( test_step.text ).to eq text
|
70
|
+
expect( test_step.location ).to eq location
|
71
|
+
end
|
72
|
+
|
73
|
+
it "exposes the location of the action as attribute" do
|
74
|
+
location = double
|
75
|
+
action = double(location: location)
|
76
|
+
test_step = Step.new(text, location, action)
|
77
|
+
expect( test_step.action_location ).to eq location
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns the text when converted to a string" do
|
81
|
+
text = 'a passing step'
|
82
|
+
test_step = Step.new(text, location)
|
83
|
+
expect( test_step.to_s ).to eq 'a passing step'
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'cucumber/core/test/timer'
|
3
|
+
require 'cucumber/core/test/duration_matcher'
|
4
|
+
|
5
|
+
module Cucumber
|
6
|
+
module Core
|
7
|
+
module Test
|
8
|
+
describe Timer do
|
9
|
+
before do
|
10
|
+
allow(Timer::MonotonicTime).to receive(:time_in_nanoseconds)
|
11
|
+
.and_return(525702744080000, 525702744080001)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns a Result::Duration object" do
|
15
|
+
timer = Timer.new.start
|
16
|
+
expect( timer.duration ).to be_duration 1
|
17
|
+
end
|
18
|
+
|
19
|
+
it "would be slow to test" do
|
20
|
+
# so we won't
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'report_api_spy'
|
3
|
+
require 'cucumber/core'
|
4
|
+
require 'cucumber/core/filter'
|
5
|
+
require 'cucumber/core/gherkin/writer'
|
6
|
+
require 'cucumber/core/platform'
|
7
|
+
require 'cucumber/core/report/summary'
|
8
|
+
require 'cucumber/core/test/around_hook'
|
9
|
+
require 'cucumber/core/test/filters/activate_steps_for_self_test'
|
10
|
+
|
11
|
+
module Cucumber
|
12
|
+
describe Core do
|
13
|
+
include Core
|
14
|
+
include Core::Gherkin::Writer
|
15
|
+
|
16
|
+
describe "compiling features to a test suite" do
|
17
|
+
|
18
|
+
it "compiles two scenarios into two test cases" do
|
19
|
+
visitor = ReportAPISpy.new
|
20
|
+
|
21
|
+
compile([
|
22
|
+
gherkin do
|
23
|
+
feature do
|
24
|
+
background do
|
25
|
+
step 'text'
|
26
|
+
end
|
27
|
+
scenario do
|
28
|
+
step 'text'
|
29
|
+
end
|
30
|
+
scenario do
|
31
|
+
step 'text'
|
32
|
+
step 'text'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
], visitor)
|
37
|
+
|
38
|
+
expect( visitor.messages ).to eq [
|
39
|
+
:test_case,
|
40
|
+
:test_step,
|
41
|
+
:test_step,
|
42
|
+
:test_case,
|
43
|
+
:test_step,
|
44
|
+
:test_step,
|
45
|
+
:test_step,
|
46
|
+
:done,
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "filters out test cases based on a tag expression" do
|
51
|
+
visitor = double.as_null_object
|
52
|
+
expect( visitor ).to receive(:test_case) do |test_case|
|
53
|
+
expect( test_case.name ).to eq 'foo'
|
54
|
+
end.exactly(1).times
|
55
|
+
|
56
|
+
gherkin = gherkin do
|
57
|
+
feature do
|
58
|
+
scenario tags: '@b' do
|
59
|
+
step 'text'
|
60
|
+
end
|
61
|
+
|
62
|
+
scenario_outline 'foo' do
|
63
|
+
step '<arg>'
|
64
|
+
|
65
|
+
examples tags: '@a'do
|
66
|
+
row 'arg'
|
67
|
+
row 'x'
|
68
|
+
end
|
69
|
+
|
70
|
+
examples 'bar', tags: '@a @b' do
|
71
|
+
row 'arg'
|
72
|
+
row 'y'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
compile [gherkin], visitor, [Cucumber::Core::Test::TagFilter.new(['@a', '@b'])]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "executing a test suite" do
|
83
|
+
|
84
|
+
it "fires events" do
|
85
|
+
gherkin = gherkin do
|
86
|
+
feature 'Feature name' do
|
87
|
+
scenario 'The one that passes' do
|
88
|
+
step 'passing'
|
89
|
+
end
|
90
|
+
|
91
|
+
scenario 'The one that fails' do
|
92
|
+
step 'passing'
|
93
|
+
step 'failing'
|
94
|
+
step 'passing'
|
95
|
+
step 'undefined'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
observed_events = []
|
101
|
+
execute [gherkin], [Core::Test::Filters::ActivateStepsForSelfTest.new] do |event_bus|
|
102
|
+
event_bus.on(:test_case_started) do |event|
|
103
|
+
test_case = event.test_case
|
104
|
+
observed_events << [:test_case_started, test_case.name]
|
105
|
+
end
|
106
|
+
event_bus.on(:test_case_finished) do |event|
|
107
|
+
test_case, result = *event.attributes
|
108
|
+
observed_events << [:test_case_finished, test_case.name, result.to_sym]
|
109
|
+
end
|
110
|
+
event_bus.on(:test_step_started) do |event|
|
111
|
+
test_step = event.test_step
|
112
|
+
observed_events << [:test_step_started, test_step.text]
|
113
|
+
end
|
114
|
+
event_bus.on(:test_step_finished) do |event|
|
115
|
+
test_step, result = *event.attributes
|
116
|
+
observed_events << [:test_step_finished, test_step.text, result.to_sym]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
expect(observed_events).to eq [
|
121
|
+
[:test_case_started, 'The one that passes'],
|
122
|
+
[:test_step_started, 'passing'],
|
123
|
+
[:test_step_finished, 'passing', :passed],
|
124
|
+
[:test_case_finished, 'The one that passes', :passed],
|
125
|
+
[:test_case_started, 'The one that fails'],
|
126
|
+
[:test_step_started, 'passing'],
|
127
|
+
[:test_step_finished, 'passing', :passed],
|
128
|
+
[:test_step_started, 'failing'],
|
129
|
+
[:test_step_finished, 'failing', :failed],
|
130
|
+
[:test_step_started, 'passing'],
|
131
|
+
[:test_step_finished, 'passing', :skipped],
|
132
|
+
[:test_step_started, 'undefined'],
|
133
|
+
[:test_step_finished, 'undefined', :undefined],
|
134
|
+
[:test_case_finished, 'The one that fails', :failed],
|
135
|
+
]
|
136
|
+
end
|
137
|
+
|
138
|
+
context "without hooks" do
|
139
|
+
it "executes the test cases in the suite" do
|
140
|
+
gherkin = gherkin do
|
141
|
+
feature 'Feature name' do
|
142
|
+
scenario 'The one that passes' do
|
143
|
+
step 'passing'
|
144
|
+
end
|
145
|
+
|
146
|
+
scenario 'The one that fails' do
|
147
|
+
step 'passing'
|
148
|
+
step 'failing'
|
149
|
+
step 'passing'
|
150
|
+
step 'undefined'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
event_bus = Core::EventBus.new
|
156
|
+
report = Core::Report::Summary.new(event_bus)
|
157
|
+
execute [gherkin], [Core::Test::Filters::ActivateStepsForSelfTest.new], event_bus
|
158
|
+
|
159
|
+
expect( report.test_cases.total ).to eq 2
|
160
|
+
expect( report.test_cases.total_passed ).to eq 1
|
161
|
+
expect( report.test_cases.total_failed ).to eq 1
|
162
|
+
expect( report.test_steps.total ).to eq 5
|
163
|
+
expect( report.test_steps.total_failed ).to eq 1
|
164
|
+
expect( report.test_steps.total_passed ).to eq 2
|
165
|
+
expect( report.test_steps.total_skipped ).to eq 1
|
166
|
+
expect( report.test_steps.total_undefined ).to eq 1
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "with around hooks" do
|
171
|
+
class WithAroundHooks < Core::Filter.new(:logger)
|
172
|
+
def test_case(test_case)
|
173
|
+
base_step = Core::Test::Step.new('text', nil, nil, nil)
|
174
|
+
test_steps = [
|
175
|
+
base_step.with_action { logger << :step },
|
176
|
+
]
|
177
|
+
|
178
|
+
around_hook = Core::Test::AroundHook.new do |run_scenario|
|
179
|
+
logger << :before_all
|
180
|
+
run_scenario.call
|
181
|
+
logger << :middle
|
182
|
+
run_scenario.call
|
183
|
+
logger << :after_all
|
184
|
+
end
|
185
|
+
test_case.with_steps(test_steps).with_around_hooks([around_hook]).describe_to(receiver)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
it "executes the test cases in the suite" do
|
190
|
+
gherkin = gherkin do
|
191
|
+
feature do
|
192
|
+
scenario do
|
193
|
+
step 'text'
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
logger = []
|
198
|
+
|
199
|
+
event_bus = Core::EventBus.new
|
200
|
+
report = Core::Report::Summary.new(event_bus)
|
201
|
+
execute [gherkin], [WithAroundHooks.new(logger)], event_bus
|
202
|
+
|
203
|
+
expect( report.test_cases.total ).to eq 1
|
204
|
+
expect( report.test_cases.total_passed ).to eq 1
|
205
|
+
expect( report.test_cases.total_failed ).to eq 0
|
206
|
+
expect( logger ).to eq [
|
207
|
+
:before_all,
|
208
|
+
:step,
|
209
|
+
:middle,
|
210
|
+
:step,
|
211
|
+
:after_all
|
212
|
+
]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
require 'cucumber/core/test/filters'
|
217
|
+
it "filters test cases by tag" do
|
218
|
+
gherkin = gherkin do
|
219
|
+
feature do
|
220
|
+
scenario do
|
221
|
+
step 'text'
|
222
|
+
end
|
223
|
+
|
224
|
+
scenario tags: '@a @b' do
|
225
|
+
step 'text'
|
226
|
+
end
|
227
|
+
|
228
|
+
scenario tags: '@a' do
|
229
|
+
step 'text'
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
event_bus = Core::EventBus.new
|
235
|
+
report = Core::Report::Summary.new(event_bus)
|
236
|
+
execute [gherkin], [ Cucumber::Core::Test::TagFilter.new(['@a']) ], event_bus
|
237
|
+
|
238
|
+
expect( report.test_cases.total ).to eq 2
|
239
|
+
end
|
240
|
+
|
241
|
+
it "filters test cases by name" do
|
242
|
+
gherkin = gherkin do
|
243
|
+
feature 'first feature' do
|
244
|
+
scenario 'first scenario' do
|
245
|
+
step 'missing'
|
246
|
+
end
|
247
|
+
scenario 'second' do
|
248
|
+
step 'missing'
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
event_bus = Core::EventBus.new
|
254
|
+
report = Core::Report::Summary.new(event_bus)
|
255
|
+
execute [gherkin], [ Cucumber::Core::Test::NameFilter.new([/scenario/]) ], event_bus
|
256
|
+
|
257
|
+
expect( report.test_cases.total ).to eq 1
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|