gherkin 0.0.3-universal-java-1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/.gitignore +8 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +47 -0
  4. data/Rakefile +48 -0
  5. data/VERSION.yml +4 -0
  6. data/bin/gherkin +10 -0
  7. data/cucumber.yml +3 -0
  8. data/ext/gherkin_lexer/.gitignore +6 -0
  9. data/ext/gherkin_lexer/extconf.rb +6 -0
  10. data/features/feature_parser.feature +206 -0
  11. data/features/native_lexer.feature +19 -0
  12. data/features/parser_with_native_lexer.feature +205 -0
  13. data/features/pretty_printer.feature +11 -0
  14. data/features/step_definitions/gherkin_steps.rb +34 -0
  15. data/features/step_definitions/pretty_printer_steps.rb +51 -0
  16. data/features/steps_parser.feature +46 -0
  17. data/features/support/env.rb +33 -0
  18. data/gherkin.gemspec +177 -0
  19. data/java/.gitignore +2 -0
  20. data/java/Gherkin.iml +24 -0
  21. data/java/build.xml +13 -0
  22. data/java/src/gherkin/FixJava.java +34 -0
  23. data/java/src/gherkin/Lexer.java +5 -0
  24. data/java/src/gherkin/LexingError.java +7 -0
  25. data/java/src/gherkin/Listener.java +27 -0
  26. data/java/src/gherkin/ParseError.java +22 -0
  27. data/java/src/gherkin/Parser.java +185 -0
  28. data/java/src/gherkin/lexer/.gitignore +1 -0
  29. data/java/src/gherkin/parser/StateMachineReader.java +62 -0
  30. data/lib/.gitignore +2 -0
  31. data/lib/gherkin.rb +2 -0
  32. data/lib/gherkin/c_lexer.rb +10 -0
  33. data/lib/gherkin/i18n.yml +535 -0
  34. data/lib/gherkin/i18n_lexer.rb +29 -0
  35. data/lib/gherkin/java_lexer.rb +10 -0
  36. data/lib/gherkin/lexer.rb +42 -0
  37. data/lib/gherkin/parser.rb +19 -0
  38. data/lib/gherkin/parser/meta.txt +4 -0
  39. data/lib/gherkin/parser/root.txt +9 -0
  40. data/lib/gherkin/parser/steps.txt +3 -0
  41. data/lib/gherkin/rb_lexer.rb +9 -0
  42. data/lib/gherkin/rb_lexer/.gitignore +1 -0
  43. data/lib/gherkin/rb_lexer/README.rdoc +8 -0
  44. data/lib/gherkin/rb_parser.rb +117 -0
  45. data/lib/gherkin/tools/pretty_printer.rb +77 -0
  46. data/ragel/i18n/.gitignore +1 -0
  47. data/ragel/lexer.c.rl.erb +385 -0
  48. data/ragel/lexer.java.rl.erb +198 -0
  49. data/ragel/lexer.rb.rl.erb +172 -0
  50. data/ragel/lexer_common.rl.erb +46 -0
  51. data/spec/gherkin/c_lexer_spec.rb +21 -0
  52. data/spec/gherkin/fixtures/complex.feature +43 -0
  53. data/spec/gherkin/fixtures/i18n_fr.feature +13 -0
  54. data/spec/gherkin/fixtures/i18n_no.feature +6 -0
  55. data/spec/gherkin/fixtures/i18n_zh-CN.feature +8 -0
  56. data/spec/gherkin/fixtures/simple.feature +3 -0
  57. data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
  58. data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
  59. data/spec/gherkin/i18n_spec.rb +57 -0
  60. data/spec/gherkin/java_lexer_spec.rb +20 -0
  61. data/spec/gherkin/parser_spec.rb +28 -0
  62. data/spec/gherkin/rb_lexer_spec.rb +18 -0
  63. data/spec/gherkin/sexp_recorder.rb +29 -0
  64. data/spec/gherkin/shared/lexer_spec.rb +420 -0
  65. data/spec/gherkin/shared/py_string_spec.rb +112 -0
  66. data/spec/gherkin/shared/table_spec.rb +97 -0
  67. data/spec/gherkin/shared/tags_spec.rb +50 -0
  68. data/spec/spec_helper.rb +53 -0
  69. data/tasks/bench.rake +176 -0
  70. data/tasks/bench/feature_builder.rb +49 -0
  71. data/tasks/bench/generated/.gitignore +1 -0
  72. data/tasks/bench/null_listener.rb +4 -0
  73. data/tasks/cucumber.rake +20 -0
  74. data/tasks/ext.rake +49 -0
  75. data/tasks/ragel.rake +94 -0
  76. data/tasks/rdoc.rake +12 -0
  77. data/tasks/rspec.rake +15 -0
  78. metadata +204 -0
@@ -0,0 +1,8 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ *.dot
7
+ *.png
8
+ *.so
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Mike Sassak, Gregory Hnatiuk, Aslak Hellesøy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,47 @@
1
+ = Gherkin
2
+
3
+ Fast Gherkin lexer based on Ragel.
4
+
5
+ Gherkin is the language that has evolved out of the Cucumber project. Cucumber currently uses
6
+ Treetop, which is too slow for larger projects.
7
+
8
+ This project will *not* include code to build an AST. Instead, this lexer will have an API
9
+ that makes it possible to plug in a builder that can build an AST.
10
+
11
+ == Testing
12
+
13
+ rake ragel
14
+ rake spec cucumber
15
+
16
+ == Cleaning generated code
17
+
18
+ rake clobber
19
+
20
+ == Notes
21
+
22
+ Ragel supports Ruby, but it's much slower than C. The ruby target will be used for development.
23
+ The final version will use C for MRI and Java for JRuby.
24
+
25
+ == Ragel links
26
+
27
+ * http://www.complang.org/ragel/
28
+ * http://dev.sipdoc.net/attachments/2/ragel_talk.pdf
29
+ * http://lambda-the-ultimate.org/node/1125
30
+ * http://www.zedshaw.com/essays/ragel_state_charts.html
31
+ * http://www.devchix.com/2008/01/13/a-hello-world-for-ruby-on-ragel-60/
32
+
33
+ == Note on Patches/Pull Requests
34
+
35
+ * Fork the project.
36
+ * Run rake ragel:rb to generate all the I18N lexers
37
+ * Make your feature addition or bug fix.
38
+ * Add tests for it. This is important so I don't break it in a
39
+ future version unintentionally.
40
+ * Commit, do not mess with rakefile, version, or history.
41
+ (if you want to have your own version, that is fine but
42
+ bump version in a commit by itself I can ignore when I pull)
43
+ * Send me a pull request. Bonus points for topic branches.
44
+
45
+ == Copyright
46
+
47
+ Copyright (c) 2009 Mike Sassak, Gregory Hnatiuk, Aslak Hellesøy. See LICENSE for details.
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ require 'rbconfig'
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'rake/clean'
6
+
7
+ JRUBY = defined?(JRUBY_VERSION)
8
+ WINDOWS = Config::CONFIG['host_os'] =~ /mswin|mingw/
9
+
10
+ begin
11
+ require 'jeweler'
12
+ Jeweler::Tasks.new do |gem|
13
+ gem.name = "gherkin"
14
+ gem.summary = %Q{Fast Gherkin lexer}
15
+ gem.description = %Q{A fast Gherkin lexer in Ragel}
16
+ gem.email = "cukes@googlegroups.com"
17
+ gem.homepage = "http://github.com/aslakhellesoy/gherkin"
18
+ gem.authors = ["Mike Sassak", "Gregory Hnatiuk", "Aslak Hellesøy"]
19
+ gem.executables = ["gherkin"]
20
+ gem.add_development_dependency "rspec", "1.2.9"
21
+ gem.add_development_dependency "cucumber"
22
+
23
+ # Jeweler only includes files in git by default. Add the generated ones.
24
+ gem.files += FileList['lib/gherkin/rb_lexer/*.rb']
25
+
26
+ if(JRUBY)
27
+ gem.platform = Gem::Platform::CURRENT
28
+ gem.files += FileList['lib/gherkin.jar']
29
+ gem.extensions = []
30
+ elsif(WINDOWS)
31
+ gem.platform = Gem::Platform::CURRENT
32
+ gem.files += FileList['lib/gherkin_lexer.dll']
33
+ gem.extensions = []
34
+ else
35
+ gem.files += FileList['ext/gherkin_lexer/*.{c,h}']
36
+ gem.extensions = 'ext/gherkin_lexer/extconf.rb'
37
+ end
38
+
39
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
40
+ end
41
+ Jeweler::GemcutterTasks.new
42
+ rescue LoadError
43
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
44
+ end
45
+
46
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
47
+
48
+ task :default => [:spec, :cucumber]
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 0
3
+ :patch: 3
4
+ :major: 0
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require 'gherkin'
5
+ require 'gherkin/tools/pretty_printer'
6
+
7
+ listener = Gherkin::Tools::PrettyPrinter.new(STDOUT)
8
+ parser = Gherkin::Parser.new(listener, true) # We could skip the parser here, if we don't want to verify well-formedness
9
+ lexer = Gherkin::Lexer['en'].new(parser)
10
+ lexer.scan(IO.read(ARGV[0]))
@@ -0,0 +1,3 @@
1
+ default: --format pretty --tags ~@pending,~@wip --strict features
2
+ wip: --format pretty --tags @wip --wip features
3
+ pending: --format pretty --tags @pending,~@native_lexer
@@ -0,0 +1,6 @@
1
+ Makefile
2
+ *.bundle
3
+ *.log
4
+ en.c
5
+ *.o
6
+ *dSYM/
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("gherkin_lexer")
4
+ have_library("c", "main")
5
+
6
+ create_makefile("gherkin_lexer")
@@ -0,0 +1,206 @@
1
+ # language: en
2
+ Feature: Gherkin Feature lexer
3
+ In order to make it easy to control the Gherkin syntax
4
+ As a Gherkin developer bent on Gherkin world-domination
5
+ I want a feature lexer that uses a feature parser to
6
+ make all the syntax decisions for me
7
+
8
+ Background:
9
+ Given a "en", "ruby" "root" parser
10
+
11
+ Scenario: Correctly formed feature
12
+ Given the following text is parsed:
13
+ """
14
+ # Apologies to Bill Watterson
15
+ @cardboard_box @wip
16
+ Feature: Transmogrification
17
+ As a young boy with a hyperactive imagination
18
+ I want a cardboard box
19
+ In order to transform the ennui of suburban life into something
20
+ befitting my imagination
21
+
22
+ Background:
23
+ Given I have a transmogrifier
24
+ And I am a member of G.R.O.S.S
25
+
26
+ Scenario: Whoozit to whatzit transmogrification
27
+ Given I have a whoozit
28
+ When I put it in the transmogrifier
29
+ And I press the "transmogrify" button
30
+ Then I should have a whatzit
31
+
32
+ Scenario Outline: Imaginary Beings
33
+ Given I have a <boring being>
34
+ When I transmogrify it with the incantation:
35
+ \"\"\"
36
+ ALAKAZAM!
37
+ \"\"\"
38
+ Then I should have an <exciting being>
39
+
40
+ Examples:
41
+ | boring being | exciting being |
42
+ | Sparrow | Alicanto |
43
+ | Goldfish | Baldanders |
44
+ | Cow | Hsiao |
45
+
46
+ Scenario: Sense of humor detection
47
+ Given the following excerpt:
48
+ \"\"\"
49
+ WOMAN: Who are the Britons?
50
+ ARTHUR: Well, we all are. we're all Britons and I am your king.
51
+ WOMAN: I didn't know we had a king. I thought we were an autonomous
52
+ collective.
53
+ DENNIS: You're fooling yourself. We're living in a dictatorship.
54
+ A self-perpetuating autocracy in which the working classes--
55
+ WOMAN: Oh there you go, bringing class into it again.
56
+ DENNIS: That's what it's all about if only people would--
57
+ ARTHUR: Please, please good people. I am in haste. Who lives
58
+ in that castle?
59
+ \"\"\"
60
+ When I read it
61
+ Then I should be amused
62
+ """
63
+ Then there should be no parse errors
64
+
65
+ Scenario: Keyword before feature
66
+ Given the following text is parsed:
67
+ """
68
+ Scenario: Bullying my way to the head of the line
69
+ Given I am a big bully of a scenario
70
+ Then I should be caught by the syntax police(y)
71
+
72
+ Feature: Too timid to stand up for myself
73
+ """
74
+ Then there should be parse errors on lines 1 through 3
75
+
76
+ Scenario: Tag ends background and scenario
77
+ Given the following text is parsed:
78
+ """
79
+ Feature: test feature
80
+ Background:
81
+ Given a something
82
+ @tag
83
+ And something else
84
+
85
+ @foo
86
+ Scenario: my scenario
87
+ @tag
88
+ Given this is a step
89
+ @oh_hai
90
+ And this is a horrible idea
91
+ Then it shouldn't work
92
+ """
93
+ Then there should be parse errors on lines 5, 10 and 12
94
+
95
+ Scenario: Tables
96
+ Given the following text is parsed:
97
+ """
98
+ Feature: Antiques Roadshow
99
+ Scenario Outline: Table
100
+ Given a <foo>
101
+ Then a <bar>
102
+
103
+ Examples:
104
+ | foo | bar |
105
+ | 42 | towel |
106
+ @hello
107
+ | 1 | prime |
108
+
109
+ Scenario: Table arguments
110
+ Given this step needs this table:
111
+ | foo | bar |
112
+ | one | two |
113
+ @tag
114
+ | aaa | bbb |
115
+ """
116
+ Then there should be parse errors on lines 10 and 17
117
+
118
+ Scenario: Multiline keyword descriptions
119
+ Given the following text is parsed:
120
+ """
121
+ Feature: Documentation is fun
122
+ Scenario Outline: With lots of docs
123
+ We need lots of embedded documentation for some reason
124
+ \"\"\" # Not interpreted as a pystring, just plain text
125
+ Oh hai
126
+ \"\"\"
127
+
128
+ La la la
129
+
130
+ Examples:
131
+ | one | two |
132
+ | foo | bar |
133
+
134
+ \"\"\"
135
+ Oh Hello
136
+ \"\"\"
137
+
138
+ # Body of the scenario outline starts below
139
+ Given <something>
140
+ And something <else>
141
+
142
+ # The real examples table
143
+ Examples:
144
+ | something | else |
145
+ | orange | apple |
146
+ """
147
+ Then there should be no parse errors
148
+
149
+ Scenario: Scenario Outline with multiple Example groups
150
+ Given the following text is parsed:
151
+ """
152
+ Feature: Outline Sample
153
+
154
+ Scenario: I have no steps
155
+
156
+ Scenario Outline: Test state
157
+ Given <state> without a table
158
+ Given <other_state> without a table
159
+
160
+ Examples: Rainbow colours
161
+ | state | other_state |
162
+ | missing | passing|
163
+ | passing| passing |
164
+ | failing | passing |
165
+
166
+ Examples: Only passing
167
+ | state | other_state |
168
+ | passing | passing |
169
+ """
170
+ Then there should be no parse errors
171
+
172
+ Scenario: Multiple Scenario Outlines with multiline outline steps
173
+ Given the following text is parsed:
174
+ """
175
+ Feature: Test
176
+ Scenario Outline: with step tables
177
+ Given I have the following fruits in my pantry
178
+ | name | quantity |
179
+ | cucumbers | 10 |
180
+ | strawberrys | 5 |
181
+ | apricots | 7 |
182
+
183
+ When I eat <number> <fruits> from the pantry
184
+ Then I should have <left> <fruits> in the pantry
185
+
186
+ Examples:
187
+ | number | fruits | left |
188
+ | 2 | cucumbers | 8 |
189
+ | 4 | strawberrys| 1 |
190
+ | 2 | apricots | 5 |
191
+
192
+ Scenario Outline: placeholder in a multiline string
193
+ Given my shopping list
194
+ \"\"\"
195
+ Must buy some <fruits>
196
+ \"\"\"
197
+ Then my shopping list should equal
198
+ \"\"\"
199
+ Must buy some cucumbers
200
+ \"\"\"
201
+
202
+ Examples:
203
+ | fruits |
204
+ | cucumbers |
205
+ """
206
+ Then there should be no parse errors
@@ -0,0 +1,19 @@
1
+ Feature: Native (C/Java) Lexer
2
+
3
+ Background:
4
+ Given a "en", "native" "root" parser
5
+
6
+ Scenario: Parsing an empty feature
7
+ Given the following text is parsed:
8
+ """
9
+ Feature: blah
10
+ """
11
+ Then there should be no parse errors
12
+
13
+ Scenario: Parsing a comment
14
+ Given the following text is parsed:
15
+ """
16
+ # A comment
17
+ Feature: Hello
18
+ """
19
+ Then there should be no parse errors
@@ -0,0 +1,205 @@
1
+ Feature: Gherkin Feature lexer/parser
2
+ In order to make it easy to control the Gherkin syntax
3
+ As a Gherkin developer bent on Gherkin world-domination
4
+ I want a feature lexer that uses a feature parser to
5
+ make all the syntax decisions for me
6
+
7
+ Background:
8
+ Given a "en", "native" "root" parser
9
+
10
+ Scenario: Correctly formed feature
11
+ When the following text is parsed:
12
+ """
13
+ # Apologies to Bill Watterson
14
+ @cardboard_box @wip
15
+ Feature: Transmogrification
16
+ As a young boy with a hyperactive imagination
17
+ I want a cardboard box
18
+ In order to transform the ennui of suburban life into something
19
+ befitting my imagination
20
+
21
+ Background:
22
+ Given I have a transmogrifier
23
+ And I am a member of G.R.O.S.S
24
+
25
+ Scenario: Whoozit to whatzit transmogrification
26
+ Given I have a whoozit
27
+ When I put it in the transmogrifier
28
+ And I press the "transmogrify" button
29
+ Then I should have a whatzit
30
+
31
+ Scenario Outline: Imaginary Beings
32
+ Given I have a <boring being>
33
+ When I transmogrify it with the incantation:
34
+ \"\"\"
35
+ ALAKAZAM!
36
+ \"\"\"
37
+ Then I should have an <exciting being>
38
+
39
+ Examples:
40
+ | boring being | exciting being |
41
+ | Sparrow | Alicanto |
42
+ | Goldfish | Baldanders |
43
+ | Cow | Hsiao |
44
+
45
+ Scenario: Sense of humor detection
46
+ Given the following excerpt:
47
+ \"\"\"
48
+ WOMAN: Who are the Britons?
49
+ ARTHUR: Well, we all are. we're all Britons and I am your king.
50
+ WOMAN: I didn't know we had a king. I thought we were an autonomous
51
+ collective.
52
+ DENNIS: You're fooling yourself. We're living in a dictatorship.
53
+ A self-perpetuating autocracy in which the working classes--
54
+ WOMAN: Oh there you go, bringing class into it again.
55
+ DENNIS: That's what it's all about if only people would--
56
+ ARTHUR: Please, please good people. I am in haste. Who lives
57
+ in that castle?
58
+ \"\"\"
59
+ When I read it
60
+ Then I should be amused
61
+ """
62
+ Then there should be no parse errors
63
+
64
+ Scenario: Keyword before feature
65
+ When the following text is parsed:
66
+ """
67
+ Scenario: Bullying my way to the head of the line
68
+ Given I am a big bully of a scenario
69
+ Then I should be caught by the syntax police(y)
70
+
71
+ Feature: Too timid to stand up for myself
72
+ """
73
+ Then there should be parse errors on lines 1 through 3
74
+
75
+ Scenario: Tag ends background and scenario
76
+ When the following text is parsed:
77
+ """
78
+ Feature: test feature
79
+ Background:
80
+ Given a something
81
+ @tag
82
+ And something else
83
+
84
+ @foo
85
+ Scenario: my scenario
86
+ @tag
87
+ Given this is a step
88
+ @oh_hai
89
+ And this is a horrible idea
90
+ Then it shouldn't work
91
+ """
92
+ Then there should be parse errors on lines 5, 10 and 12
93
+
94
+ Scenario: Tables
95
+ When the following text is parsed:
96
+ """
97
+ Feature: Antiques Roadshow
98
+ Scenario Outline: Table
99
+ Given a <foo>
100
+ Then a <bar>
101
+
102
+ Examples:
103
+ | foo | bar |
104
+ | 42 | towel |
105
+ @hello
106
+ | 1 | prime |
107
+
108
+ Scenario: Table arguments
109
+ Given this step needs this table:
110
+ | foo | bar |
111
+ | one | two |
112
+ @tag
113
+ | aaa | bbb |
114
+ """
115
+ Then there should be parse errors on lines 10 and 17
116
+
117
+ Scenario: Multiline keyword descriptions
118
+ When the following text is parsed:
119
+ """
120
+ Feature: Documentation is fun
121
+ Scenario Outline: With lots of docs
122
+ We need lots of embedded documentation for some reason
123
+ \"\"\" # Not interpreted as a pystring, just plain text
124
+ Oh hai
125
+ \"\"\"
126
+
127
+ La la la
128
+
129
+ Examples:
130
+ | one | two |
131
+ | foo | bar |
132
+
133
+ \"\"\"
134
+ Oh Hello
135
+ \"\"\"
136
+
137
+ # Body of the scenario outline starts below
138
+ Given <something>
139
+ And something <else>
140
+
141
+ # The real examples table
142
+ Examples:
143
+ | something | else |
144
+ | orange | apple |
145
+ """
146
+ Then there should be no parse errors
147
+
148
+ Scenario: Scenario Outline with multiple Example groups
149
+ When the following text is parsed:
150
+ """
151
+ Feature: Outline Sample
152
+
153
+ Scenario: I have no steps
154
+
155
+ Scenario Outline: Test state
156
+ Given <state> without a table
157
+ Given <other_state> without a table
158
+
159
+ Examples: Rainbow colours
160
+ | state | other_state |
161
+ | missing | passing|
162
+ | passing| passing |
163
+ | failing | passing |
164
+
165
+ Examples: Only passing
166
+ | state | other_state |
167
+ | passing | passing |
168
+ """
169
+ Then there should be no parse errors
170
+
171
+ Scenario: Multiple Scenario Outlines with multiline outline steps
172
+ When the following text is parsed:
173
+ """
174
+ Feature: Test
175
+ Scenario Outline: with step tables
176
+ Given I have the following fruits in my pantry
177
+ | name | quantity |
178
+ | cucumbers | 10 |
179
+ | strawberrys | 5 |
180
+ | apricots | 7 |
181
+
182
+ When I eat <number> <fruits> from the pantry
183
+ Then I should have <left> <fruits> in the pantry
184
+
185
+ Examples:
186
+ | number | fruits | left |
187
+ | 2 | cucumbers | 8 |
188
+ | 4 | strawberrys| 1 |
189
+ | 2 | apricots | 5 |
190
+
191
+ Scenario Outline: placeholder in a multiline string
192
+ Given my shopping list
193
+ \"\"\"
194
+ Must buy some <fruits>
195
+ \"\"\"
196
+ Then my shopping list should equal
197
+ \"\"\"
198
+ Must buy some cucumbers
199
+ \"\"\"
200
+
201
+ Examples:
202
+ | fruits |
203
+ | cucumbers |
204
+ """
205
+ Then there should be no parse errors