cucumber 2.0.0.rc.4 → 2.0.0.rc.5
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/History.md +74 -52
- data/examples/i18n/ht/Rakefile +6 -0
- data/examples/i18n/ht/features/adisyon.feature +17 -0
- data/examples/i18n/ht/features/divizyon.feature +10 -0
- data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +25 -0
- data/examples/i18n/ht/lib/kalkilatris.rb +14 -0
- data/features/docs/cli/dry_run.feature +43 -0
- data/features/docs/cli/strict_mode.feature +24 -1
- data/features/docs/defining_steps/nested_steps.feature +49 -0
- data/features/docs/exception_in_after_step_hook.feature +1 -1
- data/features/docs/exception_in_around_hook.feature +80 -0
- data/features/docs/formatters/json_formatter.feature +65 -1
- data/features/docs/formatters/junit_formatter.feature +40 -0
- data/features/docs/{wire_protocol_erb.feature → wire_protocol/erb_configuration.feature} +2 -2
- data/features/docs/wire_protocol/handle_unexpected_response.feature +30 -0
- data/features/docs/wire_protocol/invoke_message.feature +216 -0
- data/features/docs/wire_protocol/readme.md +26 -0
- data/features/docs/wire_protocol/snippets_message.feature +51 -0
- data/features/docs/wire_protocol/step_matches_message.feature +81 -0
- data/features/docs/{wire_protocol_table_diffing.feature → wire_protocol/table_diffing.feature} +1 -0
- data/features/docs/{wire_protocol_tags.feature → wire_protocol/tags.feature} +1 -0
- data/features/docs/{wire_protocol_timeouts.feature → wire_protocol/timeouts.feature} +1 -0
- data/features/docs/work_in_progress.feature +1 -1
- data/features/docs/writing_support_code/around_hooks.feature +31 -0
- data/features/docs/writing_support_code/before_hook.feature +7 -3
- data/features/docs/writing_support_code/tagged_hooks.feature +44 -6
- data/features/lib/step_definitions/wire_steps.rb +18 -1
- data/features/lib/support/fake_wire_server.rb +10 -7
- data/lib/cucumber.rb +1 -3
- data/lib/cucumber/cli/options.rb +7 -0
- data/lib/cucumber/encoding.rb +5 -0
- data/lib/cucumber/errors.rb +8 -0
- data/lib/cucumber/filters/prepare_world.rb +13 -5
- data/lib/cucumber/formatter/console.rb +1 -1
- data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +9 -6
- data/lib/cucumber/formatter/junit.rb +95 -0
- data/lib/cucumber/formatter/legacy_api/adapter.rb +39 -3
- data/lib/cucumber/platform.rb +1 -1
- data/lib/cucumber/project_initializer.rb +43 -0
- data/lib/cucumber/rb_support/rb_step_definition.rb +11 -2
- data/lib/cucumber/rb_support/rb_world.rb +2 -2
- data/lib/cucumber/rb_support/snippet.rb +1 -1
- data/lib/cucumber/rspec/doubles.rb +1 -1
- data/lib/cucumber/running_test_case.rb +115 -0
- data/lib/cucumber/runtime.rb +5 -1
- data/lib/cucumber/runtime/for_programming_languages.rb +2 -2
- data/lib/cucumber/runtime/support_code.rb +18 -8
- data/spec/cucumber/formatter/junit_spec.rb +212 -156
- data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +89 -1
- data/spec/cucumber/formatter/pretty_spec.rb +13 -0
- data/spec/cucumber/project_initializer_spec.rb +87 -0
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +21 -3
- data/spec/cucumber/rb_support/snippet_spec.rb +6 -6
- data/spec/cucumber/running_test_case_spec.rb +83 -0
- data/spec/spec_helper.rb +1 -4
- metadata +35 -18
- data/bin/cuke +0 -60
- data/features/docs/report_called_undefined_steps.feature +0 -57
- data/features/docs/wire_protocol.feature +0 -337
- data/lib/cucumber/ast/facade.rb +0 -117
data/lib/cucumber/runtime.rb
CHANGED
@@ -102,6 +102,10 @@ module Cucumber
|
|
102
102
|
@support_code.fire_hook(:begin_scenario, scenario)
|
103
103
|
end
|
104
104
|
|
105
|
+
def end_scenario(scenario)
|
106
|
+
@support_code.fire_hook(:end_scenario)
|
107
|
+
end
|
108
|
+
|
105
109
|
def unknown_programming_language?
|
106
110
|
@support_code.unknown_programming_language?
|
107
111
|
end
|
@@ -201,7 +205,7 @@ module Cucumber
|
|
201
205
|
summary_report.test_cases.total_passed > 0
|
202
206
|
else
|
203
207
|
summary_report.test_cases.total_failed > 0 || summary_report.test_steps.total_failed > 0 ||
|
204
|
-
(@configuration.strict? && (summary_report.test_steps.total_undefined > 0 || summary_report.test_steps.
|
208
|
+
(@configuration.strict? && (summary_report.test_steps.total_undefined > 0 || summary_report.test_steps.total_pending > 0))
|
205
209
|
end
|
206
210
|
end
|
207
211
|
public :failure?
|
@@ -23,8 +23,8 @@ module Cucumber
|
|
23
23
|
:step_match
|
24
24
|
|
25
25
|
def_delegators :@support_code,
|
26
|
-
:
|
27
|
-
:
|
26
|
+
:invoke_dynamic_steps,
|
27
|
+
:invoke_dynamic_step,
|
28
28
|
:load_programming_language
|
29
29
|
|
30
30
|
# Returns a Cucumber::MultilineArgument::DataTable for +text_or_table+, which can either
|
@@ -23,7 +23,7 @@ module Cucumber
|
|
23
23
|
|
24
24
|
def step(step)
|
25
25
|
location = Core::Ast::Location.of_caller
|
26
|
-
@support_code.
|
26
|
+
@support_code.invoke_dynamic_step(step.name, multiline_arg(step, location))
|
27
27
|
end
|
28
28
|
|
29
29
|
def eof
|
@@ -58,14 +58,24 @@ module Cucumber
|
|
58
58
|
# Given I have 8 cukes in my belly
|
59
59
|
# Then I should not be thirsty
|
60
60
|
# })
|
61
|
-
def
|
61
|
+
def invoke_dynamic_steps(steps_text, i18n, file_colon_line)
|
62
62
|
file, line = file_colon_line.split(':')
|
63
63
|
parser = Gherkin::Parser::Parser.new(StepInvoker.new(self), true, 'steps', false, i18n.iso_code)
|
64
64
|
parser.parse(steps_text, file, line.to_i)
|
65
65
|
end
|
66
66
|
|
67
|
-
|
68
|
-
|
67
|
+
# @api private
|
68
|
+
# This allows users to attempt to find, match and execute steps
|
69
|
+
# from code as the features are running, as opposed to regular
|
70
|
+
# steps which are compiled into test steps before execution.
|
71
|
+
#
|
72
|
+
# These are commonly called nested steps.
|
73
|
+
def invoke_dynamic_step(step_name, multiline_argument, location=nil)
|
74
|
+
begin
|
75
|
+
step_match(step_name).invoke(multiline_argument)
|
76
|
+
rescue Undefined => exception
|
77
|
+
raise UndefinedDynamicStep, step_name
|
78
|
+
end
|
69
79
|
end
|
70
80
|
|
71
81
|
# Loads and registers programming language implementation.
|
@@ -137,7 +147,7 @@ module Cucumber
|
|
137
147
|
|
138
148
|
def find_after_step_hooks(test_case)
|
139
149
|
ruby = load_programming_language('rb')
|
140
|
-
scenario =
|
150
|
+
scenario = RunningTestCase.new(test_case)
|
141
151
|
|
142
152
|
action_blocks = ruby.hooks_for(:after_step, scenario).map do |hook|
|
143
153
|
->(*args) { hook.invoke('AfterStep', args) }
|
@@ -147,7 +157,7 @@ module Cucumber
|
|
147
157
|
|
148
158
|
def apply_before_hooks(test_case)
|
149
159
|
ruby = load_programming_language('rb')
|
150
|
-
scenario =
|
160
|
+
scenario = RunningTestCase.new(test_case)
|
151
161
|
|
152
162
|
action_blocks = ruby.hooks_for(:before, scenario).map do |hook|
|
153
163
|
->(result) { hook.invoke('Before', scenario.with_result(result)) }
|
@@ -157,7 +167,7 @@ module Cucumber
|
|
157
167
|
|
158
168
|
def apply_after_hooks(test_case)
|
159
169
|
ruby = load_programming_language('rb')
|
160
|
-
scenario =
|
170
|
+
scenario = RunningTestCase.new(test_case)
|
161
171
|
|
162
172
|
action_blocks = ruby.hooks_for(:after, scenario).map do |hook|
|
163
173
|
->(result) { hook.invoke('After', scenario.with_result(result)) }
|
@@ -167,7 +177,7 @@ module Cucumber
|
|
167
177
|
|
168
178
|
def find_around_hooks(test_case)
|
169
179
|
ruby = load_programming_language('rb')
|
170
|
-
scenario =
|
180
|
+
scenario = RunningTestCase.new(test_case)
|
171
181
|
|
172
182
|
ruby.hooks_for(:around, scenario).map do |hook|
|
173
183
|
Hooks.around_hook(test_case.source) do |run_scenario|
|
@@ -4,192 +4,248 @@ require 'cucumber/formatter/spec_helper'
|
|
4
4
|
require 'cucumber/formatter/junit'
|
5
5
|
require 'nokogiri'
|
6
6
|
|
7
|
-
module Cucumber
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
7
|
+
module Cucumber
|
8
|
+
module Formatter
|
9
|
+
describe Junit do
|
10
|
+
extend SpecHelperDsl
|
11
|
+
include SpecHelper
|
12
|
+
|
13
|
+
class TestDoubleJunitFormatter < Junit
|
14
|
+
attr_reader :written_files
|
15
|
+
|
16
|
+
def write_file(feature_filename, data)
|
17
|
+
@written_files ||= {}
|
18
|
+
@written_files[feature_filename] = data
|
19
|
+
end
|
18
20
|
end
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
context "With no options" do
|
23
|
+
before(:each) do
|
24
|
+
allow(File).to receive(:directory?) { true }
|
25
|
+
@formatter = TestDoubleJunitFormatter.new(runtime, '', {})
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
after(:each) do
|
29
|
+
$stdout = STDOUT
|
30
|
+
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
32
|
+
describe "is able to strip control chars from cdata" do
|
33
|
+
before(:each) do
|
34
|
+
run_defined_feature
|
35
|
+
@doc = Nokogiri.XML(@formatter.written_files.values.first)
|
36
|
+
end
|
37
|
+
define_feature "
|
38
|
+
Feature: One passing scenario, one failing scenario
|
39
|
+
|
40
|
+
Scenario: Passing
|
41
|
+
Given a passing ctrl scenario
|
42
|
+
"
|
43
|
+
class Junit
|
44
|
+
def before_step(step)
|
45
|
+
if step.name.match("a passing ctrl scenario")
|
46
|
+
Interceptor::Pipe.unwrap! :stdout
|
47
|
+
@fake_io = $stdout = StringIO.new
|
48
|
+
$stdout.sync = true
|
49
|
+
@interceptedout = Interceptor::Pipe.wrap(:stdout)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def after_step(step)
|
54
|
+
if step.name.match("a passing ctrl scenario")
|
55
|
+
@interceptedout.write("boo\b\cx\e\a\f boo ")
|
56
|
+
$stdout = STDOUT
|
57
|
+
@fake_io.close
|
58
|
+
end
|
59
|
+
end
|
48
60
|
end
|
61
|
+
|
62
|
+
it { expect(@doc.xpath('//testsuite/system-out').first.content).to match(/\s+boo boo\s+/) }
|
49
63
|
end
|
50
64
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
65
|
+
describe "a feature with no name" do
|
66
|
+
define_feature <<-FEATURE
|
67
|
+
Feature:
|
68
|
+
Scenario: Passing
|
69
|
+
Given a passing scenario
|
70
|
+
FEATURE
|
71
|
+
|
72
|
+
it "raises an exception" do
|
73
|
+
expect(-> {
|
74
|
+
run_defined_feature
|
75
|
+
}).to raise_error(Junit::UnNamedFeatureError)
|
56
76
|
end
|
57
77
|
end
|
58
|
-
end
|
59
78
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
Feature:
|
66
|
-
Scenario: Passing
|
67
|
-
Given a passing scenario
|
68
|
-
FEATURE
|
69
|
-
|
70
|
-
it "raises an exception" do
|
71
|
-
expect(-> {
|
72
|
-
run_defined_feature
|
73
|
-
}).to raise_error(Junit::UnNamedFeatureError)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe "given a single feature" do
|
78
|
-
before(:each) do
|
79
|
-
run_defined_feature
|
80
|
-
@doc = Nokogiri.XML(@formatter.written_files.values.first)
|
81
|
-
end
|
79
|
+
describe "given a single feature" do
|
80
|
+
before(:each) do
|
81
|
+
run_defined_feature
|
82
|
+
@doc = Nokogiri.XML(@formatter.written_files.values.first)
|
83
|
+
end
|
82
84
|
|
83
|
-
|
84
|
-
|
85
|
-
|
85
|
+
describe "with a single scenario" do
|
86
|
+
define_feature <<-FEATURE
|
87
|
+
Feature: One passing scenario, one failing scenario
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
89
|
+
Scenario: Passing
|
90
|
+
Given a passing scenario
|
91
|
+
FEATURE
|
90
92
|
|
91
|
-
|
93
|
+
it { expect(@doc.to_s).to match /One passing scenario, one failing scenario/ }
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
-
|
95
|
+
it 'has a root system-out node' do
|
96
|
+
expect(@doc.xpath('//testsuite/system-out').size).to eq 1
|
97
|
+
end
|
96
98
|
|
97
|
-
|
98
|
-
|
99
|
-
|
99
|
+
it 'has a root system-err node' do
|
100
|
+
expect(@doc.xpath('//testsuite/system-err').size).to eq 1
|
101
|
+
end
|
100
102
|
|
101
|
-
|
102
|
-
|
103
|
-
|
103
|
+
it 'has a system-out node under <testcase/>' do
|
104
|
+
expect(@doc.xpath('//testcase/system-out').size).to eq 1
|
105
|
+
end
|
104
106
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
107
|
+
it 'has a system-err node under <testcase/>' do
|
108
|
+
expect(@doc.xpath('//testcase/system-err').size).to eq 1
|
109
|
+
end
|
110
|
+
end
|
109
111
|
|
110
|
-
|
111
|
-
|
112
|
-
|
112
|
+
describe "with a scenario in a subdirectory" do
|
113
|
+
define_feature %{
|
114
|
+
Feature: One passing scenario, one failing scenario
|
113
115
|
|
114
|
-
|
115
|
-
|
116
|
-
|
116
|
+
Scenario: Passing
|
117
|
+
Given a passing scenario
|
118
|
+
}, File.join('features', 'some', 'path', 'spec.feature')
|
117
119
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
120
|
+
it 'writes the filename including the subdirectory' do
|
121
|
+
expect(@formatter.written_files.keys.first).to eq File.join('', 'TEST-features-some-path-spec.xml')
|
122
|
+
end
|
123
|
+
end
|
122
124
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
125
|
+
describe "with a scenario outline table" do
|
126
|
+
define_steps do
|
127
|
+
Given(/.*/) { }
|
128
|
+
end
|
129
|
+
|
130
|
+
define_feature <<-FEATURE
|
131
|
+
Feature: Eat things when hungry
|
132
|
+
|
133
|
+
Scenario Outline: Eat things
|
134
|
+
Given <Things>
|
135
|
+
And stuff:
|
136
|
+
| foo |
|
137
|
+
| bar |
|
138
|
+
|
139
|
+
Examples: Good
|
140
|
+
| Things |
|
141
|
+
| Cucumber |
|
142
|
+
| Whisky |
|
143
|
+
Examples: Evil
|
144
|
+
| Things |
|
145
|
+
| Big Mac |
|
146
|
+
FEATURE
|
147
|
+
|
148
|
+
it { expect(@doc.to_s).to match /Eat things when hungry/ }
|
149
|
+
it { expect(@doc.to_s).to match /Cucumber/ }
|
150
|
+
it { expect(@doc.to_s).to match /Whisky/ }
|
151
|
+
it { expect(@doc.to_s).to match /Big Mac/ }
|
152
|
+
it { expect(@doc.to_s).not_to match /Things/ }
|
153
|
+
it { expect(@doc.to_s).not_to match /Good|Evil/ }
|
154
|
+
it { expect(@doc.to_s).not_to match /type="skipped"/}
|
155
|
+
end
|
127
156
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
Scenario Outline: Eat things
|
132
|
-
Given <Things>
|
133
|
-
And stuff:
|
134
|
-
| foo |
|
135
|
-
| bar |
|
136
|
-
|
137
|
-
Examples: Good
|
138
|
-
| Things |
|
139
|
-
| Cucumber |
|
140
|
-
| Whisky |
|
141
|
-
Examples: Evil
|
142
|
-
| Things |
|
143
|
-
| Big Mac |
|
144
|
-
FEATURE
|
145
|
-
|
146
|
-
it { expect(@doc.to_s).to match /Eat things when hungry/ }
|
147
|
-
it { expect(@doc.to_s).to match /Cucumber/ }
|
148
|
-
it { expect(@doc.to_s).to match /Whisky/ }
|
149
|
-
it { expect(@doc.to_s).to match /Big Mac/ }
|
150
|
-
it { expect(@doc.to_s).not_to match /Things/ }
|
151
|
-
it { expect(@doc.to_s).not_to match /Good|Evil/ }
|
152
|
-
it { expect(@doc.to_s).not_to match /type="skipped"/}
|
153
|
-
end
|
157
|
+
describe "scenario with skipped test in junit report" do
|
158
|
+
define_feature <<-FEATURE
|
159
|
+
Feature: junit report with skipped test
|
154
160
|
|
155
|
-
|
156
|
-
|
157
|
-
Feature: junit report with skipped test
|
161
|
+
Scenario Outline: skip a test and junit report of the same
|
162
|
+
Given a <skip> scenario
|
158
163
|
|
159
|
-
|
160
|
-
|
164
|
+
Examples:
|
165
|
+
| skip |
|
166
|
+
| undefined |
|
167
|
+
| still undefined |
|
168
|
+
FEATURE
|
161
169
|
|
162
|
-
|
163
|
-
|
164
|
-
| undefined |
|
165
|
-
| still undefined |
|
166
|
-
FEATURE
|
170
|
+
it { expect(@doc.to_s).to match /skipped="2"/}
|
171
|
+
end
|
167
172
|
|
168
|
-
|
173
|
+
describe "with a regular data table scenario" do
|
174
|
+
define_steps do
|
175
|
+
Given(/the following items on a shortlist/) { |table| }
|
176
|
+
When(/I go.*/) { }
|
177
|
+
Then(/I should have visited at least/) { |table| }
|
178
|
+
end
|
179
|
+
|
180
|
+
define_feature <<-FEATURE
|
181
|
+
Feature: Shortlist
|
182
|
+
|
183
|
+
Scenario: Procure items
|
184
|
+
Given the following items on a shortlist:
|
185
|
+
| item |
|
186
|
+
| milk |
|
187
|
+
| cookies |
|
188
|
+
When I get some..
|
189
|
+
Then I'll eat 'em
|
190
|
+
|
191
|
+
FEATURE
|
192
|
+
# these type of tables shouldn't crash (or generate test cases)
|
193
|
+
it { expect(@doc.to_s).not_to match /milk/ }
|
194
|
+
it { expect(@doc.to_s).not_to match /cookies/ }
|
195
|
+
end
|
196
|
+
end
|
169
197
|
end
|
198
|
+
|
199
|
+
context "In --expand mode" do
|
200
|
+
let(:runtime) { Runtime.new({:expand => true}) }
|
201
|
+
before(:each) do
|
202
|
+
allow(File).to receive(:directory?) { true }
|
203
|
+
@formatter = TestDoubleJunitFormatter.new(runtime, '', {:expand => true})
|
204
|
+
end
|
170
205
|
|
171
|
-
|
172
|
-
|
173
|
-
Given(/the following items on a shortlist/) { |table| }
|
174
|
-
When(/I go.*/) { }
|
175
|
-
Then(/I should have visited at least/) { |table| }
|
206
|
+
after(:each) do
|
207
|
+
$stdout = STDOUT
|
176
208
|
end
|
177
209
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
210
|
+
describe "given a single feature" do
|
211
|
+
before(:each) do
|
212
|
+
run_defined_feature
|
213
|
+
@doc = Nokogiri.XML(@formatter.written_files.values.first)
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "with a scenario outline table" do
|
217
|
+
define_steps do
|
218
|
+
Given(/.*/) { }
|
219
|
+
end
|
220
|
+
|
221
|
+
define_feature <<-FEATURE
|
222
|
+
Feature: Eat things when hungry
|
223
|
+
|
224
|
+
Scenario Outline: Eat things
|
225
|
+
Given <Things>
|
226
|
+
And stuff:
|
227
|
+
| foo |
|
228
|
+
| bar |
|
229
|
+
|
230
|
+
Examples: Good
|
231
|
+
| Things |
|
232
|
+
| Cucumber |
|
233
|
+
| Whisky |
|
234
|
+
Examples: Evil
|
235
|
+
| Things |
|
236
|
+
| Big Mac |
|
237
|
+
FEATURE
|
238
|
+
|
239
|
+
it { expect(@doc.to_s).to match /Eat things when hungry/ }
|
240
|
+
it { expect(@doc.to_s).to match /Cucumber/ }
|
241
|
+
it { expect(@doc.to_s).to match /Whisky/ }
|
242
|
+
it { expect(@doc.to_s).to match /Big Mac/ }
|
243
|
+
it { expect(@doc.to_s).not_to match /Things/ }
|
244
|
+
it { expect(@doc.to_s).not_to match /Good|Evil/ }
|
245
|
+
it { expect(@doc.to_s).not_to match /type="skipped"/}
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
193
249
|
end
|
194
250
|
end
|
195
251
|
end
|