cucumber 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +26 -1
- data/Manifest.txt +20 -1
- data/config/hoe.rb +5 -4
- data/examples/i18n/hu/Rakefile +6 -0
- data/examples/i18n/hu/features/addition.feature +16 -0
- data/examples/i18n/hu/features/division.feature +9 -0
- data/examples/i18n/hu/features/step_definitons/calculator_steps.rb +25 -0
- data/examples/i18n/hu/lib/calculator.rb +14 -0
- data/examples/i18n/lv/Rakefile +6 -0
- data/examples/i18n/lv/features/addition.feature +16 -0
- data/examples/i18n/lv/features/division.feature +9 -0
- data/examples/i18n/lv/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/lv/lib/calculator.rb +14 -0
- data/examples/self_test/features/background/failing_background.feature +1 -0
- data/examples/self_test/features/multiline_name.feature +27 -0
- data/examples/self_test/features/search_sample.feature +22 -0
- data/examples/self_test/features/step_definitions/sample_steps.rb +3 -2
- data/examples/tickets/Rakefile +3 -3
- data/examples/tickets/features/236.feature +9 -9
- data/examples/tickets/features/272/hooks.feature +26 -0
- data/examples/tickets/features/272/hooks_steps.rb +53 -0
- data/examples/tickets/features/301/filter_background_tagged_hooks.feature +6 -0
- data/examples/tickets/features/301/filter_background_tagged_hooks_steps.rb +12 -0
- data/examples/tickets/features/306/only_background.feature +4 -0
- data/features/background.feature +2 -1
- data/features/cucumber_cli.feature +88 -12
- data/features/cucumber_cli_outlines.feature +32 -0
- data/features/custom_formatter.feature +2 -2
- data/features/multiline_names.feature +43 -0
- data/features/report_called_undefined_steps.feature +1 -1
- data/features/usage.feature +13 -4
- data/lib/cucumber/ast/background.rb +10 -13
- data/lib/cucumber/ast/feature.rb +5 -0
- data/lib/cucumber/ast/feature_element.rb +23 -12
- data/lib/cucumber/ast/outline_table.rb +10 -0
- data/lib/cucumber/ast/py_string.rb +5 -1
- data/lib/cucumber/ast/scenario.rb +17 -6
- data/lib/cucumber/ast/scenario_outline.rb +1 -6
- data/lib/cucumber/ast/step.rb +6 -3
- data/lib/cucumber/ast/step_collection.rb +9 -1
- data/lib/cucumber/ast/table.rb +8 -0
- data/lib/cucumber/ast/visitor.rb +2 -2
- data/lib/cucumber/cli/configuration.rb +15 -14
- data/lib/cucumber/formatter/console.rb +1 -1
- data/lib/cucumber/formatter/html.rb +1 -1
- data/lib/cucumber/formatter/pretty.rb +7 -8
- data/lib/cucumber/languages.yml +30 -0
- data/lib/cucumber/parser/feature.rb +214 -14
- data/lib/cucumber/parser/feature.tt +44 -14
- data/lib/cucumber/parser/treetop_ext.rb +3 -3
- data/lib/cucumber/rails/world.rb +6 -0
- data/lib/cucumber/step_mother.rb +2 -1
- data/lib/cucumber/version.rb +1 -1
- data/lib/cucumber/world.rb +2 -2
- data/rails_generators/cucumber/templates/paths.rb +11 -13
- data/rails_generators/feature/feature_generator.rb +1 -1
- data/spec/cucumber/ast/feature_element_spec.rb +40 -0
- data/spec/cucumber/ast/py_string_spec.rb +4 -0
- data/spec/cucumber/ast/table_spec.rb +20 -4
- data/spec/cucumber/ast/visitor_spec.rb +27 -0
- data/spec/cucumber/cli/configuration_spec.rb +4 -13
- data/spec/cucumber/cli/main_spec.rb +55 -153
- data/spec/cucumber/parser/feature_parser_spec.rb +79 -0
- data/spec/cucumber/step_mother_spec.rb +12 -5
- metadata +22 -13
- data/spec/cucumber/formatters/profile_formatter_spec.rb +0 -198
data/features/background.feature
CHANGED
@@ -72,6 +72,7 @@ Feature: backgrounds
|
|
72
72
|
When I run cucumber -q features/background/failing_background.feature --require features
|
73
73
|
Then it should fail with
|
74
74
|
"""
|
75
|
+
@after_file
|
75
76
|
Feature: Failing background sample
|
76
77
|
|
77
78
|
Background:
|
@@ -79,7 +80,7 @@ Feature: backgrounds
|
|
79
80
|
FAIL (RuntimeError)
|
80
81
|
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
81
82
|
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
82
|
-
features/background/failing_background.feature:
|
83
|
+
features/background/failing_background.feature:5:in `Given failing without a table'
|
83
84
|
And '10' cukes
|
84
85
|
|
85
86
|
Scenario: failing background
|
@@ -191,6 +191,36 @@ Feature: Cucumber command line
|
|
191
191
|
When I stop procrastinating
|
192
192
|
And there is world peace
|
193
193
|
|
194
|
+
Feature: multiline
|
195
|
+
|
196
|
+
Background: I'm a multiline name
|
197
|
+
which goes on and on and on for three lines
|
198
|
+
yawn
|
199
|
+
Given passing without a table
|
200
|
+
|
201
|
+
Scenario: I'm a multiline name
|
202
|
+
which goes on and on and on for three lines
|
203
|
+
yawn
|
204
|
+
Given passing without a table
|
205
|
+
|
206
|
+
Scenario Outline: I'm a multiline name
|
207
|
+
which goes on and on and on for three lines
|
208
|
+
yawn
|
209
|
+
Given <state> without a table
|
210
|
+
|
211
|
+
Examples:
|
212
|
+
| state |
|
213
|
+
| passing |
|
214
|
+
|
215
|
+
Scenario Outline: name
|
216
|
+
Given <state> without a table
|
217
|
+
|
218
|
+
Examples: I'm a multiline name
|
219
|
+
which goes on and on and on for three lines
|
220
|
+
yawn
|
221
|
+
| state |
|
222
|
+
| passing |
|
223
|
+
|
194
224
|
Feature: Outline Sample
|
195
225
|
|
196
226
|
Scenario: I have no steps
|
@@ -229,6 +259,31 @@ Feature: Cucumber command line
|
|
229
259
|
hello
|
230
260
|
\"\"\"
|
231
261
|
|
262
|
+
Feature: search examples
|
263
|
+
|
264
|
+
Background: Hantu Pisang background match
|
265
|
+
Given passing without a table
|
266
|
+
|
267
|
+
Scenario: should match Hantu Pisang
|
268
|
+
Given passing without a table
|
269
|
+
|
270
|
+
Scenario: Ignore me
|
271
|
+
Given failing without a table
|
272
|
+
|
273
|
+
Scenario Outline: Ignore me
|
274
|
+
Given <state> without a table
|
275
|
+
|
276
|
+
Examples:
|
277
|
+
| state |
|
278
|
+
| failing |
|
279
|
+
|
280
|
+
Scenario Outline: Hantu Pisang match
|
281
|
+
Given <state> without a table
|
282
|
+
|
283
|
+
Examples:
|
284
|
+
| state |
|
285
|
+
| passing |
|
286
|
+
|
232
287
|
Feature: undefined multiline args
|
233
288
|
|
234
289
|
Scenario: pystring
|
@@ -242,8 +297,8 @@ Feature: Cucumber command line
|
|
242
297
|
| table |
|
243
298
|
| example |
|
244
299
|
|
245
|
-
|
246
|
-
|
300
|
+
21 scenarios
|
301
|
+
26 skipped steps
|
247
302
|
9 undefined steps
|
248
303
|
|
249
304
|
"""
|
@@ -274,24 +329,45 @@ Feature: Cucumber command line
|
|
274
329
|
|
275
330
|
"""
|
276
331
|
|
277
|
-
Scenario: Run
|
278
|
-
When I run cucumber --
|
332
|
+
Scenario: Run feature elements which matches a name using --name
|
333
|
+
When I run cucumber --name Pisang -q features/
|
279
334
|
Then it should pass with
|
280
335
|
"""
|
281
|
-
|
282
|
-
Feature: Sample
|
336
|
+
Feature: search examples
|
283
337
|
|
284
|
-
|
285
|
-
|
286
|
-
Given passing
|
287
|
-
| a | b |
|
288
|
-
| c | d |
|
338
|
+
Background: Hantu Pisang background match
|
339
|
+
Given passing without a table
|
289
340
|
|
290
|
-
|
341
|
+
Scenario: should match Hantu Pisang
|
342
|
+
Given passing without a table
|
343
|
+
|
344
|
+
Scenario Outline: Hantu Pisang match
|
345
|
+
Given <state> without a table
|
346
|
+
|
347
|
+
Examples:
|
348
|
+
| state |
|
349
|
+
| passing |
|
350
|
+
|
351
|
+
2 scenarios
|
352
|
+
4 passed steps
|
353
|
+
|
354
|
+
"""
|
355
|
+
|
356
|
+
Scenario: Run a single background which matches a name using --name
|
357
|
+
When I run cucumber --name 'Hantu Pisang background' -q features/
|
358
|
+
Then it should pass with
|
359
|
+
"""
|
360
|
+
Feature: search examples
|
361
|
+
|
362
|
+
Background: Hantu Pisang background match
|
363
|
+
Given passing without a table
|
364
|
+
|
365
|
+
0 scenarios
|
291
366
|
1 passed step
|
292
367
|
|
293
368
|
"""
|
294
369
|
|
370
|
+
|
295
371
|
Scenario: Run with a tag that exists on 2 scenarios
|
296
372
|
When I run cucumber -q features --tags three
|
297
373
|
Then it should pass with
|
@@ -2,6 +2,38 @@ Feature: Cucumber command line
|
|
2
2
|
In order to write better software
|
3
3
|
Developers should be able to execute requirements as tests
|
4
4
|
|
5
|
+
Scenario: Run scenario outline with filtering on outline name
|
6
|
+
When I run cucumber -q features --name "Test state"
|
7
|
+
Then it should fail with
|
8
|
+
"""
|
9
|
+
Feature: Outline Sample
|
10
|
+
|
11
|
+
Scenario Outline: Test state
|
12
|
+
Given <state> without a table
|
13
|
+
Given <other_state> without a table
|
14
|
+
|
15
|
+
Examples: Rainbow colours
|
16
|
+
| state | other_state |
|
17
|
+
| missing | passing |
|
18
|
+
| passing | passing |
|
19
|
+
| failing | passing |
|
20
|
+
FAIL (RuntimeError)
|
21
|
+
./features/step_definitions/sample_steps.rb:2:in `flunker'
|
22
|
+
./features/step_definitions/sample_steps.rb:16:in `/^failing without a table$/'
|
23
|
+
features/outline_sample.feature:6:in `Given <state> without a table'
|
24
|
+
|
25
|
+
Examples: Only passing
|
26
|
+
| state | other_state |
|
27
|
+
| passing | passing |
|
28
|
+
|
29
|
+
4 scenarios
|
30
|
+
1 failed step
|
31
|
+
2 skipped steps
|
32
|
+
1 undefined step
|
33
|
+
4 passed steps
|
34
|
+
|
35
|
+
"""
|
36
|
+
|
5
37
|
Scenario: Run scenario outline steps only
|
6
38
|
When I run cucumber -q features/outline_sample.feature:7
|
7
39
|
Then it should fail with
|
@@ -4,8 +4,8 @@ Feature: Custom Formatter
|
|
4
4
|
When I run cucumber --format Tag::Count features
|
5
5
|
Then it should fail with
|
6
6
|
"""
|
7
|
-
| four | lots | one | three | two |
|
8
|
-
| 1 | 1 | 1 | 2 | 1 |
|
7
|
+
| after_file | four | lots | one | three | two |
|
8
|
+
| 1 | 1 | 1 | 1 | 2 | 1 |
|
9
9
|
|
10
10
|
"""
|
11
11
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
Feature: Multiline description names
|
2
|
+
In order to accurately document feature elements
|
3
|
+
As a cucumberist
|
4
|
+
I want to have multiline names
|
5
|
+
|
6
|
+
Scenario: multiline scenario
|
7
|
+
When I run cucumber features/multiline_name.feature --no-snippets
|
8
|
+
Then it should pass with
|
9
|
+
"""
|
10
|
+
Feature: multiline
|
11
|
+
|
12
|
+
Background: I'm a multiline name # features/multiline_name.feature:3
|
13
|
+
which goes on and on and on for three lines
|
14
|
+
yawn
|
15
|
+
Given passing without a table # features/step_definitions/sample_steps.rb:12
|
16
|
+
|
17
|
+
Scenario: I'm a multiline name # features/multiline_name.feature:8
|
18
|
+
which goes on and on and on for three lines
|
19
|
+
yawn
|
20
|
+
Given passing without a table # features/step_definitions/sample_steps.rb:12
|
21
|
+
|
22
|
+
Scenario Outline: I'm a multiline name # features/multiline_name.feature:13
|
23
|
+
which goes on and on and on for three lines
|
24
|
+
yawn
|
25
|
+
Given <state> without a table # features/step_definitions/sample_steps.rb:12
|
26
|
+
|
27
|
+
Examples:
|
28
|
+
| state |
|
29
|
+
| passing |
|
30
|
+
|
31
|
+
Scenario Outline: name # features/multiline_name.feature:21
|
32
|
+
Given <state> without a table # features/step_definitions/sample_steps.rb:12
|
33
|
+
|
34
|
+
Examples: I'm a multiline name
|
35
|
+
which goes on and on and on for three lines
|
36
|
+
yawn
|
37
|
+
| state |
|
38
|
+
| passing |
|
39
|
+
|
40
|
+
3 scenarios
|
41
|
+
6 passed steps
|
42
|
+
|
43
|
+
"""
|
@@ -23,7 +23,7 @@ Feature: Cucumber command line
|
|
23
23
|
2 scenarios
|
24
24
|
2 undefined steps
|
25
25
|
|
26
|
-
You can implement step definitions for
|
26
|
+
You can implement step definitions for undefined steps with these snippets:
|
27
27
|
|
28
28
|
Given /^this does not exist$/ do
|
29
29
|
pending
|
data/features/usage.feature
CHANGED
@@ -9,18 +9,27 @@ Feature: Cucumber command line
|
|
9
9
|
"""
|
10
10
|
/^passing without a table$/ # features/step_definitions/sample_steps.rb:12
|
11
11
|
Given passing without a table # features/background/failing_background_after_success.feature:4
|
12
|
+
Given passing without a table # features/multiline_name.feature:6
|
13
|
+
Given passing without a table # features/multiline_name.feature:11
|
14
|
+
Given <state> without a table # features/multiline_name.feature:16
|
15
|
+
Given <state> without a table # features/multiline_name.feature:22
|
12
16
|
Given <state> without a table # features/outline_sample.feature:6
|
13
17
|
Given <other_state> without a table # features/outline_sample.feature:7
|
18
|
+
Given passing without a table # features/search_sample.feature:4
|
19
|
+
Given passing without a table # features/search_sample.feature:7
|
20
|
+
Given <state> without a table # features/search_sample.feature:19
|
14
21
|
/^failing without a table$/ # features/step_definitions/sample_steps.rb:15
|
15
|
-
Given failing without a table # features/background/failing_background.feature:
|
22
|
+
Given failing without a table # features/background/failing_background.feature:5
|
16
23
|
Given failing without a table # features/background/scenario_outline_failing_background.feature:4
|
24
|
+
Given failing without a table # features/search_sample.feature:10
|
25
|
+
Given <state> without a table # features/search_sample.feature:13
|
17
26
|
/^a step definition that calls an undefined step$/ # features/step_definitions/sample_steps.rb:19
|
18
27
|
Given a step definition that calls an undefined step # features/call_undefined_step_from_step_def.feature:4
|
19
28
|
/^call step "(.*)"$/ # features/step_definitions/sample_steps.rb:23
|
20
29
|
Given call step "a step definition that calls an undefined step" # features/call_undefined_step_from_step_def.feature:7
|
21
30
|
/^'(.+)' cukes$/ # features/step_definitions/sample_steps.rb:27
|
22
31
|
Given '10' cukes # features/background/background_with_name.feature:4
|
23
|
-
And '10' cukes # features/background/failing_background.feature:
|
32
|
+
And '10' cukes # features/background/failing_background.feature:6
|
24
33
|
Given '10' cukes # features/background/passing_background.feature:4
|
25
34
|
Given '10' cukes # features/background/scenario_outline_passing_background.feature:4
|
26
35
|
Given '2' cukes # features/tons_of_cukes.feature:4
|
@@ -74,8 +83,8 @@ Feature: Cucumber command line
|
|
74
83
|
Given '2' cukes # features/tons_of_cukes.feature:52
|
75
84
|
/^I should have '(.+)' cukes$/ # features/step_definitions/sample_steps.rb:31
|
76
85
|
Then I should have '10' cukes # features/background/background_with_name.feature:7
|
77
|
-
Then I should have '10' cukes # features/background/failing_background.feature:
|
78
|
-
Then I should have '10' cukes # features/background/failing_background.feature:
|
86
|
+
Then I should have '10' cukes # features/background/failing_background.feature:9
|
87
|
+
Then I should have '10' cukes # features/background/failing_background.feature:12
|
79
88
|
Then I should have '10' cukes # features/background/passing_background.feature:7
|
80
89
|
Then I should have '10' cukes # features/background/passing_background.feature:10
|
81
90
|
Then I should have '10' cukes # features/background/pending_background.feature:7
|
@@ -4,12 +4,13 @@ module Cucumber
|
|
4
4
|
module Ast
|
5
5
|
class Background
|
6
6
|
include FeatureElement
|
7
|
-
|
7
|
+
attr_reader :feature_elements
|
8
8
|
|
9
9
|
def initialize(comment, line, keyword, name, steps)
|
10
10
|
@comment, @line, @keyword, @name, @steps = comment, line, keyword, name, StepCollection.new(steps)
|
11
11
|
attach_steps(steps)
|
12
12
|
@step_invocations = @steps.step_invocations(true)
|
13
|
+
@feature_elements = []
|
13
14
|
end
|
14
15
|
|
15
16
|
def step_collection(step_invocations)
|
@@ -23,32 +24,28 @@ module Cucumber
|
|
23
24
|
|
24
25
|
def accept(visitor)
|
25
26
|
visitor.visit_comment(@comment)
|
26
|
-
visitor.visit_background_name(@keyword, @name, file_colon_line(@line), source_indent(
|
27
|
-
visitor.step_mother.before(
|
27
|
+
visitor.visit_background_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
|
28
|
+
visitor.step_mother.before(hook_context)
|
28
29
|
visitor.visit_steps(@step_invocations)
|
29
30
|
@failed = @step_invocations.detect{|step_invocation| step_invocation.exception}
|
30
|
-
visitor.step_mother.after(
|
31
|
+
visitor.step_mother.after(hook_context) if @failed
|
31
32
|
end
|
32
33
|
|
33
34
|
def accept_hook?(hook)
|
34
|
-
|
35
|
-
# the current implementation. All hooks will be executed. This is because of the line
|
36
|
-
# visitor.step_mother.before(self)
|
37
|
-
# in the #accept method above. Instead, we should really be passing the first scenario
|
38
|
-
# here. We currently don't have access to that, so a refactoring is in order to make that happen.
|
39
|
-
true
|
35
|
+
false
|
40
36
|
end
|
41
37
|
|
42
38
|
def failed?
|
43
39
|
@failed
|
44
40
|
end
|
45
41
|
|
46
|
-
def
|
47
|
-
@
|
42
|
+
def hook_context
|
43
|
+
@feature_elements.first || self
|
48
44
|
end
|
49
45
|
|
50
46
|
def to_sexp
|
51
47
|
sexp = [:background, @line, @keyword]
|
48
|
+
sexp += [@name] unless @name.empty?
|
52
49
|
comment = @comment.to_sexp
|
53
50
|
sexp += [comment] if comment
|
54
51
|
steps = @steps.to_sexp
|
@@ -57,4 +54,4 @@ module Cucumber
|
|
57
54
|
end
|
58
55
|
end
|
59
56
|
end
|
60
|
-
end
|
57
|
+
end
|
data/lib/cucumber/ast/feature.rb
CHANGED
@@ -8,6 +8,7 @@ module Cucumber
|
|
8
8
|
def initialize(background, comment, tags, name, feature_elements)
|
9
9
|
@background, @comment, @tags, @name, @feature_elements = background, comment, tags, name, feature_elements
|
10
10
|
|
11
|
+
background.feature = self if background
|
11
12
|
@feature_elements.each do |feature_element|
|
12
13
|
feature_element.feature = self
|
13
14
|
end
|
@@ -23,6 +24,10 @@ module Cucumber
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
27
|
+
def accept_hook?(hook)
|
28
|
+
@tags.accept_hook?(hook)
|
29
|
+
end
|
30
|
+
|
26
31
|
def next_feature_element(feature_element, &proc)
|
27
32
|
index = @feature_elements.index(feature_element)
|
28
33
|
next_one = @feature_elements[index+1]
|
@@ -1,5 +1,9 @@
|
|
1
|
+
require 'enumerator'
|
2
|
+
|
1
3
|
module Cucumber
|
2
4
|
module FeatureElement
|
5
|
+
attr_writer :feature
|
6
|
+
|
3
7
|
def attach_steps(steps)
|
4
8
|
steps.each {|step| step.feature_element = self}
|
5
9
|
end
|
@@ -9,13 +13,27 @@ module Cucumber
|
|
9
13
|
end
|
10
14
|
|
11
15
|
def text_length
|
12
|
-
|
16
|
+
name_line_lengths.max
|
17
|
+
end
|
18
|
+
|
19
|
+
def first_line_length
|
20
|
+
name_line_lengths[0]
|
13
21
|
end
|
14
22
|
|
15
|
-
def
|
16
|
-
|
23
|
+
def name_line_lengths
|
24
|
+
if @name.empty?
|
25
|
+
[@keyword.jlength]
|
26
|
+
else
|
27
|
+
@name.split("\n").enum_for(:each_with_index).map do |line, line_number|
|
28
|
+
line_number == 0 ? @keyword.jlength + line.jlength : line.jlength + Ast::Step::INDENT - 1 # We -1 as names which are not keyword lines are missing a space between keyword and name
|
29
|
+
end
|
30
|
+
end
|
17
31
|
end
|
18
32
|
|
33
|
+
def matches_scenario_names?(scenario_name_regexps)
|
34
|
+
scenario_name_regexps.detect{|name| name =~ @name}
|
35
|
+
end
|
36
|
+
|
19
37
|
def backtrace_line(name = "#{@keyword} #{@name}", line = @line)
|
20
38
|
@feature.backtrace_line(name, line) if @feature
|
21
39
|
end
|
@@ -29,14 +47,7 @@ module Cucumber
|
|
29
47
|
end
|
30
48
|
|
31
49
|
def accept_hook?(hook)
|
32
|
-
@tags.accept_hook?(hook)
|
33
|
-
end
|
34
|
-
|
35
|
-
# TODO: Remove when we use StepCollection everywhere
|
36
|
-
def previous_step(step)
|
37
|
-
i = @steps.index(step) || -1
|
38
|
-
@steps[i-1]
|
50
|
+
@tags.accept_hook?(hook) || @feature.accept_hook?(hook)
|
39
51
|
end
|
40
|
-
|
41
52
|
end
|
42
|
-
end
|
53
|
+
end
|