cucumber 0.7.3 → 0.8.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.
- data/History.txt +20 -1
- data/Rakefile +4 -4
- data/VERSION.yml +2 -2
- data/cucumber.gemspec +35 -23
- data/examples/json/features/background.feature +7 -0
- data/examples/json/features/one_passing_one_failing.feature +11 -0
- data/examples/json/features/pystring.feature +8 -0
- data/examples/json/features/step_definitions/steps.rb +27 -0
- data/examples/json/features/tables.feature +13 -0
- data/examples/json/tmp/out.json +1 -0
- data/examples/self_test/features/step_definitions/sample_steps.rb +1 -0
- data/examples/tickets/features/around_timeout.feature +6 -0
- data/examples/tickets/features/step_definitons/around_timeout_steps.rb +9 -0
- data/examples/{javascript → v8}/Rakefile +3 -1
- data/examples/{javascript → v8}/features/fibonacci.feature +4 -7
- data/examples/{javascript → v8}/features/step_definitions/fib_steps.js +7 -3
- data/examples/{javascript → v8}/features/support/env.js +3 -0
- data/examples/{javascript/features → v8}/lib/fibonacci.js +0 -0
- data/features/announce.feature +1 -1
- data/features/cucumber_cli_diff_disabled.feature +1 -24
- data/features/custom_formatter.feature +9 -3
- data/features/json_formatter.feature +281 -0
- data/features/step_definitions/cucumber_steps.rb +6 -1
- data/gem_tasks/rspec.rake +1 -1
- data/lib/cucumber/ast/feature.rb +1 -1
- data/lib/cucumber/cli/configuration.rb +8 -12
- data/lib/cucumber/cli/main.rb +0 -8
- data/lib/cucumber/cli/options.rb +22 -21
- data/lib/cucumber/formatter/json.rb +154 -0
- data/lib/cucumber/formatter/json_pretty.rb +14 -0
- data/lib/cucumber/js_support/js_dsl.js +14 -26
- data/lib/cucumber/js_support/js_language.rb +31 -16
- data/lib/cucumber/rb_support/rb_language.rb +22 -3
- data/spec/cucumber/ast/scenario_spec.rb +1 -1
- data/spec/cucumber/cli/configuration_spec.rb +8 -16
- data/spec/cucumber/cli/main_spec.rb +5 -5
- data/spec/cucumber/formatter/html_spec.rb +1 -1
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +4 -4
- data/spec/cucumber/step_mother_spec.rb +1 -1
- data/spec/cucumber/world/pending_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +65 -21
- data/lib/cucumber/rspec/diffing.rb +0 -17
@@ -14,7 +14,8 @@ Feature: Custom Formatter
|
|
14
14
|
Given a standard Cucumber project directory structure
|
15
15
|
And a file named "features/f.feature" with:
|
16
16
|
"""
|
17
|
-
Feature:
|
17
|
+
Feature: I'll use my own
|
18
|
+
because I'm worth it
|
18
19
|
Scenario: just print me
|
19
20
|
Given this step works
|
20
21
|
"""
|
@@ -32,8 +33,12 @@ Feature: Custom Formatter
|
|
32
33
|
@io = io
|
33
34
|
end
|
34
35
|
|
36
|
+
def before_feature(feature)
|
37
|
+
@io.puts feature.short_name.upcase
|
38
|
+
end
|
39
|
+
|
35
40
|
def scenario_name(keyword, name, file_colon_line, source_indent)
|
36
|
-
@io.puts "
|
41
|
+
@io.puts " #{name.upcase}"
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
@@ -42,7 +47,8 @@ Feature: Custom Formatter
|
|
42
47
|
Then STDERR should be empty
|
43
48
|
Then it should pass with
|
44
49
|
"""
|
45
|
-
|
50
|
+
I'LL USE MY OWN
|
51
|
+
JUST PRINT ME
|
46
52
|
|
47
53
|
"""
|
48
54
|
|
@@ -0,0 +1,281 @@
|
|
1
|
+
Feature: JSON output formatter
|
2
|
+
In order to get results as data
|
3
|
+
As a developer
|
4
|
+
Cucumber should be able to output JSON
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I am in json
|
8
|
+
|
9
|
+
Scenario: one feature, one passing scenario, one failing scenario
|
10
|
+
And the tmp directory is empty
|
11
|
+
When I run cucumber --format json --out tmp/out.json features/one_passing_one_failing.feature
|
12
|
+
Then STDERR should be empty
|
13
|
+
And it should fail with
|
14
|
+
"""
|
15
|
+
"""
|
16
|
+
And "examples/json/tmp/out.json" should match "^\{\"features\":\["
|
17
|
+
|
18
|
+
Scenario: one feature, one passing scenario, one failing scenario
|
19
|
+
When I run cucumber --format json_pretty features/one_passing_one_failing.feature
|
20
|
+
Then STDERR should be empty
|
21
|
+
And it should fail with JSON
|
22
|
+
"""
|
23
|
+
{
|
24
|
+
"features": [
|
25
|
+
{
|
26
|
+
"file": "features/one_passing_one_failing.feature",
|
27
|
+
"name": "One passing scenario, one failing scenario",
|
28
|
+
"tags": [
|
29
|
+
"@a"
|
30
|
+
],
|
31
|
+
"elements": [
|
32
|
+
{
|
33
|
+
"tags": [
|
34
|
+
"@b"
|
35
|
+
],
|
36
|
+
"keyword": "Scenario",
|
37
|
+
"name": "Passing",
|
38
|
+
"file_colon_line": "features/one_passing_one_failing.feature:5",
|
39
|
+
"steps": [
|
40
|
+
{
|
41
|
+
"status": "passed",
|
42
|
+
"name": "Given a passing step",
|
43
|
+
"file_colon_line": "features/step_definitions/steps.rb:1"
|
44
|
+
}
|
45
|
+
]
|
46
|
+
},
|
47
|
+
{
|
48
|
+
"tags": [
|
49
|
+
"@c"
|
50
|
+
],
|
51
|
+
"keyword": "Scenario",
|
52
|
+
"name": "Failing",
|
53
|
+
"file_colon_line": "features/one_passing_one_failing.feature:9",
|
54
|
+
"steps": [
|
55
|
+
{
|
56
|
+
"exception": {
|
57
|
+
"class": "RuntimeError",
|
58
|
+
"message": "",
|
59
|
+
"backtrace": [
|
60
|
+
"./features/step_definitions/steps.rb:6:in `/a failing step/'",
|
61
|
+
"features/one_passing_one_failing.feature:10:in `Given a failing step'"
|
62
|
+
]
|
63
|
+
},
|
64
|
+
"status": "failed",
|
65
|
+
"name": "Given a failing step",
|
66
|
+
"file_colon_line": "features/step_definitions/steps.rb:5"
|
67
|
+
}
|
68
|
+
]
|
69
|
+
}
|
70
|
+
]
|
71
|
+
}
|
72
|
+
]
|
73
|
+
}
|
74
|
+
"""
|
75
|
+
|
76
|
+
Scenario: Tables
|
77
|
+
When I run cucumber --format json_pretty features/tables.feature
|
78
|
+
Then STDERR should be empty
|
79
|
+
And it should fail with JSON
|
80
|
+
"""
|
81
|
+
{
|
82
|
+
"features": [
|
83
|
+
{
|
84
|
+
"file": "features/tables.feature",
|
85
|
+
"name": "A scenario outline",
|
86
|
+
"tags": [
|
87
|
+
|
88
|
+
],
|
89
|
+
"elements": [
|
90
|
+
{
|
91
|
+
"tags": [
|
92
|
+
|
93
|
+
],
|
94
|
+
"keyword": "Scenario Outline",
|
95
|
+
"name": "",
|
96
|
+
"file_colon_line": "features/tables.feature:3",
|
97
|
+
"steps": [
|
98
|
+
{
|
99
|
+
"status": "skipped",
|
100
|
+
"name": "Given I add <a> and <b>",
|
101
|
+
"file_colon_line": "features/step_definitions/steps.rb:13"
|
102
|
+
},
|
103
|
+
{
|
104
|
+
"status": "skipped",
|
105
|
+
"name": "When I pass a table argument",
|
106
|
+
"file_colon_line": "features/step_definitions/steps.rb:25",
|
107
|
+
"table": [
|
108
|
+
{"cells":
|
109
|
+
[{"text":"foo", "status": null},
|
110
|
+
{"text":"bar", "status": null}]},
|
111
|
+
{"cells":
|
112
|
+
[{"text": "bar", "status": null},
|
113
|
+
{"text": "baz", "status": null}]}
|
114
|
+
]
|
115
|
+
},
|
116
|
+
{
|
117
|
+
"status": "skipped",
|
118
|
+
"name": "Then I the result should be <c>",
|
119
|
+
"file_colon_line": "features/step_definitions/steps.rb:17"
|
120
|
+
}
|
121
|
+
],
|
122
|
+
"examples": {
|
123
|
+
"name": "Examples ",
|
124
|
+
"table": [
|
125
|
+
{
|
126
|
+
"cells": [
|
127
|
+
{
|
128
|
+
"text": "a",
|
129
|
+
"status": "skipped_param"
|
130
|
+
},
|
131
|
+
{
|
132
|
+
"text": "b",
|
133
|
+
"status": "skipped_param"
|
134
|
+
},
|
135
|
+
{
|
136
|
+
"text": "c",
|
137
|
+
"status": "skipped_param"
|
138
|
+
}
|
139
|
+
]
|
140
|
+
},
|
141
|
+
{
|
142
|
+
"cells": [
|
143
|
+
{
|
144
|
+
"text": "1",
|
145
|
+
"status": "passed"
|
146
|
+
},
|
147
|
+
{
|
148
|
+
"text": "2",
|
149
|
+
"status": "passed"
|
150
|
+
},
|
151
|
+
{
|
152
|
+
"text": "3",
|
153
|
+
"status": "passed"
|
154
|
+
}
|
155
|
+
]
|
156
|
+
},
|
157
|
+
{
|
158
|
+
"cells": [
|
159
|
+
{
|
160
|
+
"text": "2",
|
161
|
+
"status": "passed"
|
162
|
+
},
|
163
|
+
{
|
164
|
+
"text": "3",
|
165
|
+
"status": "passed"
|
166
|
+
},
|
167
|
+
{
|
168
|
+
"text": "4",
|
169
|
+
"status": "failed"
|
170
|
+
}
|
171
|
+
],
|
172
|
+
"exception": {
|
173
|
+
"class": "RSpec::Expectations::ExpectationNotMetError",
|
174
|
+
"message": "expected: 4,\n got: 5 (using ==)\nDiff:\n@@ -1,2 +1,2 @@\n-4\n+5\n",
|
175
|
+
"backtrace": [
|
176
|
+
"./features/step_definitions/steps.rb:18:in `/^I the result should be (\\d+)$/'",
|
177
|
+
"features/tables.feature:8:in `Then I the result should be <c>'"
|
178
|
+
]
|
179
|
+
}
|
180
|
+
}
|
181
|
+
]
|
182
|
+
}
|
183
|
+
}
|
184
|
+
]
|
185
|
+
}
|
186
|
+
]
|
187
|
+
}
|
188
|
+
"""
|
189
|
+
|
190
|
+
Scenario: pystring
|
191
|
+
When I run cucumber --format json_pretty features/pystring.feature
|
192
|
+
Then STDERR should be empty
|
193
|
+
And it should pass with JSON
|
194
|
+
"""
|
195
|
+
{
|
196
|
+
"features": [
|
197
|
+
{
|
198
|
+
"file": "features/pystring.feature",
|
199
|
+
"name": "A py string feature",
|
200
|
+
"tags": [
|
201
|
+
|
202
|
+
],
|
203
|
+
"elements": [
|
204
|
+
{
|
205
|
+
"tags": [
|
206
|
+
|
207
|
+
],
|
208
|
+
"keyword": "Scenario",
|
209
|
+
"name": "",
|
210
|
+
"file_colon_line": "features/pystring.feature:3",
|
211
|
+
"steps": [
|
212
|
+
{
|
213
|
+
"status": "passed",
|
214
|
+
"name": "Then I should see",
|
215
|
+
"file_colon_line": "features/step_definitions/steps.rb:21",
|
216
|
+
"py_string": "a string"
|
217
|
+
}
|
218
|
+
]
|
219
|
+
}
|
220
|
+
]
|
221
|
+
}
|
222
|
+
]
|
223
|
+
}
|
224
|
+
"""
|
225
|
+
|
226
|
+
Scenario: background
|
227
|
+
When I run cucumber --format json_pretty features/background.feature
|
228
|
+
Then STDERR should be empty
|
229
|
+
And it should fail with JSON
|
230
|
+
"""
|
231
|
+
{
|
232
|
+
"features": [
|
233
|
+
{
|
234
|
+
"file": "features/background.feature",
|
235
|
+
"name": "Feature with background",
|
236
|
+
"tags": [
|
237
|
+
|
238
|
+
],
|
239
|
+
"background": {
|
240
|
+
"steps": [
|
241
|
+
{
|
242
|
+
"status": "passed",
|
243
|
+
"name": "Given a passing step",
|
244
|
+
"file_colon_line": "features/step_definitions/steps.rb:1"
|
245
|
+
}
|
246
|
+
]
|
247
|
+
},
|
248
|
+
"elements": [
|
249
|
+
{
|
250
|
+
"tags": [
|
251
|
+
|
252
|
+
],
|
253
|
+
"keyword": "Scenario",
|
254
|
+
"name": "",
|
255
|
+
"file_colon_line": "features/background.feature:6",
|
256
|
+
"steps": [
|
257
|
+
{
|
258
|
+
"status": "passed",
|
259
|
+
"name": "Given a passing step",
|
260
|
+
"file_colon_line": "features/step_definitions/steps.rb:1"
|
261
|
+
},
|
262
|
+
{
|
263
|
+
"exception": {
|
264
|
+
"class": "RuntimeError",
|
265
|
+
"message": "",
|
266
|
+
"backtrace": [
|
267
|
+
"./features/step_definitions/steps.rb:6:in `/a failing step/'",
|
268
|
+
"features/background.feature:7:in `Given a failing step'"
|
269
|
+
]
|
270
|
+
},
|
271
|
+
"status": "failed",
|
272
|
+
"name": "Given a failing step",
|
273
|
+
"file_colon_line": "features/step_definitions/steps.rb:5"
|
274
|
+
}
|
275
|
+
]
|
276
|
+
}
|
277
|
+
]
|
278
|
+
}
|
279
|
+
]
|
280
|
+
}
|
281
|
+
"""
|
@@ -84,6 +84,11 @@ Then /^the output should be$/ do |text|
|
|
84
84
|
last_stdout.should == text
|
85
85
|
end
|
86
86
|
|
87
|
+
Then /^it should (fail|pass) with JSON$/ do |success, text|
|
88
|
+
JSON.parse(last_stdout).should == JSON.parse(text)
|
89
|
+
Then("it should #{success}")
|
90
|
+
end
|
91
|
+
|
87
92
|
Then /^"([^"]*)" should contain$/ do |file, text|
|
88
93
|
strip_duration(IO.read(file)).should == text
|
89
94
|
end
|
@@ -95,7 +100,7 @@ Then /^"([^"]*)" with junit duration "([^"]*)" should contain$/ do |actual_file,
|
|
95
100
|
actual.should == text
|
96
101
|
end
|
97
102
|
|
98
|
-
Then /^"([^"]*)" should match "(
|
103
|
+
Then /^"([^"]*)" should match "(.+?)"$/ do |file, text|
|
99
104
|
File.open(file, Cucumber.file_mode('r')).read.should =~ Regexp.new(text)
|
100
105
|
end
|
101
106
|
|
data/gem_tasks/rspec.rake
CHANGED
data/lib/cucumber/ast/feature.rb
CHANGED
@@ -11,7 +11,7 @@ module Cucumber
|
|
11
11
|
|
12
12
|
class Configuration
|
13
13
|
include Constantize
|
14
|
-
|
14
|
+
|
15
15
|
attr_reader :options, :out_stream
|
16
16
|
|
17
17
|
def initialize(out_stream = STDOUT, error_stream = STDERR)
|
@@ -48,10 +48,6 @@ module Cucumber
|
|
48
48
|
@options[:guess]
|
49
49
|
end
|
50
50
|
|
51
|
-
def diff_enabled?
|
52
|
-
@options[:diff_enabled]
|
53
|
-
end
|
54
|
-
|
55
51
|
def drb?
|
56
52
|
@options[:drb]
|
57
53
|
end
|
@@ -85,11 +81,11 @@ module Cucumber
|
|
85
81
|
files.reject! {|f| f =~ /^http/}
|
86
82
|
files.sort
|
87
83
|
end
|
88
|
-
|
84
|
+
|
89
85
|
def step_defs_to_load
|
90
86
|
all_files_to_load.reject {|f| f =~ %r{/support/} }
|
91
87
|
end
|
92
|
-
|
88
|
+
|
93
89
|
def support_to_load
|
94
90
|
support_files = all_files_to_load.select {|f| f =~ %r{/support/} }
|
95
91
|
env_files = support_files.select {|f| f =~ %r{/support/env\..*} }
|
@@ -106,14 +102,14 @@ module Cucumber
|
|
106
102
|
elsif path[0..0] == '@' and # @listfile.txt
|
107
103
|
File.file?(path[1..-1]) # listfile.txt is a file
|
108
104
|
IO.read(path[1..-1]).split
|
109
|
-
else
|
105
|
+
else
|
110
106
|
path
|
111
107
|
end
|
112
108
|
end.flatten.uniq
|
113
109
|
remove_excluded_files_from(potential_feature_files)
|
114
|
-
potential_feature_files
|
110
|
+
potential_feature_files
|
115
111
|
end
|
116
|
-
|
112
|
+
|
117
113
|
def feature_dirs
|
118
114
|
paths.map { |f| File.directory?(f) ? f : File.dirname(f) }.uniq
|
119
115
|
end
|
@@ -127,7 +123,7 @@ module Cucumber
|
|
127
123
|
end
|
128
124
|
|
129
125
|
private
|
130
|
-
|
126
|
+
|
131
127
|
def formatters(step_mother)
|
132
128
|
# TODO: We should remove the autoformat functionality. That
|
133
129
|
# can be done with the gherkin CLI.
|
@@ -181,7 +177,7 @@ module Cucumber
|
|
181
177
|
def require_dirs
|
182
178
|
feature_dirs + Dir['vendor/{gems,plugins}/*/cucumber']
|
183
179
|
end
|
184
|
-
|
180
|
+
|
185
181
|
end
|
186
182
|
|
187
183
|
end
|
data/lib/cucumber/cli/main.rb
CHANGED
@@ -55,8 +55,6 @@ module Cucumber
|
|
55
55
|
features = step_mother.load_plain_text_features(configuration.feature_files)
|
56
56
|
step_mother.load_code_files(configuration.step_defs_to_load)
|
57
57
|
|
58
|
-
enable_diffing
|
59
|
-
|
60
58
|
tag_excess = tag_excess(features)
|
61
59
|
configuration.options[:tag_excess] = tag_excess # Hack to make it available in console.rb - later: stick on Run instance.
|
62
60
|
|
@@ -99,12 +97,6 @@ module Cucumber
|
|
99
97
|
|
100
98
|
private
|
101
99
|
|
102
|
-
def enable_diffing
|
103
|
-
if configuration.diff_enabled?
|
104
|
-
require 'cucumber/rspec/diffing'
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
100
|
def trap_interrupt
|
109
101
|
trap('INT') do
|
110
102
|
exit!(1) if Cucumber.wants_to_quit
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -6,25 +6,28 @@ module Cucumber
|
|
6
6
|
module Cli
|
7
7
|
|
8
8
|
class Options
|
9
|
+
INDENT = ' ' * 53
|
9
10
|
BUILTIN_FORMATS = {
|
10
|
-
'html'
|
11
|
-
'pretty'
|
12
|
-
'pdf'
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
'progress'
|
17
|
-
'rerun'
|
18
|
-
'usage'
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
'stepdefs'
|
24
|
-
|
25
|
-
'junit'
|
26
|
-
'
|
27
|
-
'
|
11
|
+
'html' => ['Cucumber::Formatter::Html', 'Generates a nice looking HTML report.'],
|
12
|
+
'pretty' => ['Cucumber::Formatter::Pretty', 'Prints the feature as is - in colours.'],
|
13
|
+
'pdf' => ['Cucumber::Formatter::Pdf', "Generates a PDF report. You need to have the\n" +
|
14
|
+
"#{INDENT}prawn gem installed. Will pick up logo from\n" +
|
15
|
+
"#{INDENT}features/support/logo.png or\n" +
|
16
|
+
"#{INDENT}features/support/logo.jpg if present."],
|
17
|
+
'progress' => ['Cucumber::Formatter::Progress', 'Prints one character per scenario.'],
|
18
|
+
'rerun' => ['Cucumber::Formatter::Rerun', 'Prints failing files with line numbers.'],
|
19
|
+
'usage' => ['Cucumber::Formatter::Usage', "Prints where step definitions are used.\n" +
|
20
|
+
"#{INDENT}The slowest step definitions (with duration) are\n" +
|
21
|
+
"#{INDENT}listed first. If --dry-run is used the duration\n" +
|
22
|
+
"#{INDENT}is not shown, and step definitions are sorted by\n" +
|
23
|
+
"#{INDENT}filename instead."],
|
24
|
+
'stepdefs' => ['Cucumber::Formatter::Stepdefs', "Prints All step definitions with their locations. Same as\n" +
|
25
|
+
"#{INDENT}the usage formatter, except that steps are not printed."],
|
26
|
+
'junit' => ['Cucumber::Formatter::Junit', 'Generates a report similar to Ant+JUnit.'],
|
27
|
+
'json' => ['Cucumber::Formatter::Json', 'Prints the feature as JSON'],
|
28
|
+
'json_pretty' => ['Cucumber::Formatter::JsonPretty', 'Prints the feature as pretty JSON'],
|
29
|
+
'tag_cloud' => ['Cucumber::Formatter::TagCloud', 'Prints a tag cloud of tag usage.'],
|
30
|
+
'debug' => ['Cucumber::Formatter::Debug', 'For developing formatters - prints the calls made to the listeners.']
|
28
31
|
}
|
29
32
|
max = BUILTIN_FORMATS.keys.map{|s| s.length}.max
|
30
33
|
FORMAT_HELP = (BUILTIN_FORMATS.keys.sort.map do |key|
|
@@ -118,6 +121,7 @@ module Cucumber
|
|
118
121
|
"This option can be specified multiple times.") do |v|
|
119
122
|
@options[:require] << v
|
120
123
|
if(Cucumber::JRUBY && File.directory?(v))
|
124
|
+
require 'java'
|
121
125
|
$CLASSPATH << v
|
122
126
|
end
|
123
127
|
end
|
@@ -243,9 +247,6 @@ module Cucumber
|
|
243
247
|
opts.on("-x", "--expand", "Expand Scenario Outline Tables in output.") do
|
244
248
|
@options[:expand] = true
|
245
249
|
end
|
246
|
-
opts.on("--no-diff", "Disable diff output on failing expectations.") do
|
247
|
-
@options[:diff_enabled] = false
|
248
|
-
end
|
249
250
|
opts.on(DRB_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do
|
250
251
|
@options[:drb] = true
|
251
252
|
end
|