cucumber-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE +20 -0
  8. data/README.md +9 -0
  9. data/Rakefile +24 -0
  10. data/cucumber-core.gemspec +32 -0
  11. data/lib/cucumber/core.rb +37 -0
  12. data/lib/cucumber/core/ast.rb +13 -0
  13. data/lib/cucumber/core/ast/background.rb +33 -0
  14. data/lib/cucumber/core/ast/comment.rb +17 -0
  15. data/lib/cucumber/core/ast/data_table.rb +326 -0
  16. data/lib/cucumber/core/ast/describes_itself.rb +16 -0
  17. data/lib/cucumber/core/ast/doc_string.rb +83 -0
  18. data/lib/cucumber/core/ast/empty_background.rb +12 -0
  19. data/lib/cucumber/core/ast/examples_table.rb +95 -0
  20. data/lib/cucumber/core/ast/feature.rb +62 -0
  21. data/lib/cucumber/core/ast/location.rb +140 -0
  22. data/lib/cucumber/core/ast/multiline_argument.rb +33 -0
  23. data/lib/cucumber/core/ast/names.rb +19 -0
  24. data/lib/cucumber/core/ast/outline_step.rb +51 -0
  25. data/lib/cucumber/core/ast/scenario.rb +43 -0
  26. data/lib/cucumber/core/ast/scenario_outline.rb +44 -0
  27. data/lib/cucumber/core/ast/step.rb +38 -0
  28. data/lib/cucumber/core/ast/tag.rb +14 -0
  29. data/lib/cucumber/core/compiler.rb +136 -0
  30. data/lib/cucumber/core/gherkin/ast_builder.rb +315 -0
  31. data/lib/cucumber/core/gherkin/document.rb +20 -0
  32. data/lib/cucumber/core/gherkin/parser.rb +45 -0
  33. data/lib/cucumber/core/gherkin/writer.rb +220 -0
  34. data/lib/cucumber/core/gherkin/writer/helpers.rb +178 -0
  35. data/lib/cucumber/core/platform.rb +30 -0
  36. data/lib/cucumber/core/test/case.rb +143 -0
  37. data/lib/cucumber/core/test/filters.rb +48 -0
  38. data/lib/cucumber/core/test/filters/tag_filter.rb +110 -0
  39. data/lib/cucumber/core/test/hook_compiler.rb +109 -0
  40. data/lib/cucumber/core/test/mapper.rb +56 -0
  41. data/lib/cucumber/core/test/mapping.rb +67 -0
  42. data/lib/cucumber/core/test/result.rb +191 -0
  43. data/lib/cucumber/core/test/runner.rb +149 -0
  44. data/lib/cucumber/core/test/step.rb +69 -0
  45. data/lib/cucumber/core/test/timer.rb +31 -0
  46. data/lib/cucumber/core/version.rb +9 -0
  47. data/lib/cucumber/initializer.rb +18 -0
  48. data/spec/capture_warnings.rb +68 -0
  49. data/spec/coverage.rb +10 -0
  50. data/spec/cucumber/core/ast/data_table_spec.rb +139 -0
  51. data/spec/cucumber/core/ast/doc_string_spec.rb +77 -0
  52. data/spec/cucumber/core/ast/examples_table_spec.rb +87 -0
  53. data/spec/cucumber/core/ast/location_spec.rb +105 -0
  54. data/spec/cucumber/core/ast/outline_step_spec.rb +77 -0
  55. data/spec/cucumber/core/ast/step_spec.rb +44 -0
  56. data/spec/cucumber/core/compiler_spec.rb +249 -0
  57. data/spec/cucumber/core/gherkin/parser_spec.rb +182 -0
  58. data/spec/cucumber/core/gherkin/writer_spec.rb +332 -0
  59. data/spec/cucumber/core/test/case_spec.rb +416 -0
  60. data/spec/cucumber/core/test/hook_compiler_spec.rb +78 -0
  61. data/spec/cucumber/core/test/mapper_spec.rb +68 -0
  62. data/spec/cucumber/core/test/mapping_spec.rb +103 -0
  63. data/spec/cucumber/core/test/result_spec.rb +178 -0
  64. data/spec/cucumber/core/test/runner_spec.rb +265 -0
  65. data/spec/cucumber/core/test/step_spec.rb +58 -0
  66. data/spec/cucumber/core/test/timer_spec.rb +13 -0
  67. data/spec/cucumber/core_spec.rb +419 -0
  68. data/spec/cucumber/initializer_spec.rb +49 -0
  69. metadata +221 -0
@@ -0,0 +1,105 @@
1
+ require 'cucumber/core/ast/location'
2
+
3
+ module Cucumber::Core::Ast
4
+ describe Location do
5
+ let(:line) { 12 }
6
+ let(:file) { "foo.feature" }
7
+
8
+ describe "equality" do
9
+ it "is equal to another Location on the same line of the same file" do
10
+ one_location = Location.new(file, line)
11
+ another_location = Location.new(file, line)
12
+ expect( one_location ).to eq another_location
13
+ end
14
+
15
+ it "is not equal to a wild card of the same file" do
16
+ expect( Location.new(file, line) ).not_to eq Location.new(file)
17
+ end
18
+ end
19
+
20
+ describe "to_s" do
21
+ it "is file:line for a precise location" do
22
+ expect( Location.new("foo.feature", 12).to_s ).to eq "foo.feature:12"
23
+ end
24
+
25
+ it "is file for a wildcard location" do
26
+ expect( Location.new("foo.feature").to_s ).to eq "foo.feature"
27
+ end
28
+
29
+ it "is file:first_line..last_line for a ranged location" do
30
+ expect( Location.new("foo.feature", 13..19).to_s ).to eq "foo.feature:13..19"
31
+ end
32
+ end
33
+
34
+ describe "matches" do
35
+ let(:matching) { Location.new(file, line) }
36
+ let(:same_file_other_line) { Location.new(file, double) }
37
+ let(:not_matching) { Location.new(other_file, line) }
38
+ let(:other_file) { double }
39
+
40
+ context 'a precise location' do
41
+ let(:precise) { Location.new(file, line) }
42
+
43
+ it "matches a precise location of the same file and line" do
44
+ expect( matching ).to be_match(precise)
45
+ end
46
+
47
+ it "does not match a precise location on a differnt line in the same file" do
48
+ expect( matching ).not_to be_match(same_file_other_line)
49
+ end
50
+
51
+ end
52
+
53
+ context 'a wildcard' do
54
+ let(:wildcard) { Location.new(file) }
55
+
56
+ it "matches any location with the same filename" do
57
+ expect( wildcard ).to be_match(matching)
58
+ end
59
+
60
+ it "is matched by any location of the same file" do
61
+ expect( matching ).to be_match(wildcard)
62
+ end
63
+
64
+ it "does not match a location in a different file" do
65
+ expect( wildcard ).not_to be_match(not_matching)
66
+ end
67
+ end
68
+
69
+ context 'a range wildcard' do
70
+ let(:range) { Location.new("foo.feature", 13..17) }
71
+
72
+ it "matches the first line in the same file" do
73
+ other = Location.new("foo.feature", 13)
74
+ expect( range ).to be_match(other)
75
+ end
76
+
77
+ it "matches a line within the docstring in the same file" do
78
+ other = Location.new("foo.feature", 15)
79
+ expect( range ).to be_match(other)
80
+ end
81
+
82
+ it "is matched by a line within the docstring in the same file" do
83
+ other = Location.new("foo.feature", 15)
84
+ expect( other ).to be_match(range)
85
+ end
86
+
87
+ it "matches a wildcard in the same file" do
88
+ wildcard = Location.new("foo.feature")
89
+ expect( range ).to be_match(wildcard)
90
+ end
91
+
92
+ it "does not match a location outside of the range" do
93
+ other = Location.new("foo.feature", 18)
94
+ expect( range ).not_to be_match(other)
95
+ end
96
+
97
+ it "does not match a location in another file" do
98
+ other = Location.new("bar.feature", 13)
99
+ expect( range ).not_to be_match(other)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+
@@ -0,0 +1,77 @@
1
+ require 'cucumber/core/ast/outline_step'
2
+ require 'cucumber/core/ast/examples_table'
3
+ require 'cucumber/core/ast/data_table'
4
+ require 'cucumber/core/ast/doc_string'
5
+
6
+ module Cucumber
7
+ module Core
8
+ module Ast
9
+ describe OutlineStep do
10
+ let(:outline_step) { OutlineStep.new(language, location, keyword, name) }
11
+ let(:language) { double }
12
+ let(:location) { double }
13
+ let(:keyword) { double }
14
+ let(:name) { 'anything' }
15
+
16
+ describe 'location' do
17
+ it "has a location" do
18
+ expect( outline_step ).to respond_to(:location)
19
+ end
20
+
21
+ it 'knows the file and line' do
22
+ location.stub(:to_s) { 'file_name:8' }
23
+ expect( outline_step.file_colon_line ).to eq 'file_name:8'
24
+ end
25
+ end
26
+
27
+ describe "converting to a Step" do
28
+ context "a single argument in the name" do
29
+ let(:name) { 'a <color> cucumber' }
30
+
31
+ it "replaces the argument" do
32
+ row = ExamplesTable::Row.new({'color' => 'green'}, 1, location)
33
+ expect( outline_step.to_step(row).name ).to eq 'a green cucumber'
34
+ end
35
+
36
+ end
37
+
38
+ context "when the step has a DataTable" do
39
+ let(:outline_step) { OutlineStep.new(language, location, keyword, name, table) }
40
+ let(:name) { "anything" }
41
+ let(:table) { DataTable.new([['x', 'y'],['a', 'a <arg>']], Location.new('foo.feature', 23)) }
42
+
43
+ it "replaces the arguments in the DataTable" do
44
+ visitor = double
45
+ visitor.stub(:step).and_yield
46
+ expect( visitor ).to receive(:table) do |data_table| # TODO: rename this message to :data_table
47
+ expect( data_table.raw ).to eq [['x', 'y'], ['a', 'a replacement']]
48
+ end
49
+ row = ExamplesTable::Row.new({'arg' => 'replacement'}, 1, location)
50
+ step = outline_step.to_step(row)
51
+ step.describe_to(visitor)
52
+ end
53
+ end
54
+
55
+ context "when the step has a DocString" do
56
+ let(:location) { double }
57
+ let(:outline_step) { OutlineStep.new(language, location, keyword, name, doc_string) }
58
+ let(:doc_string) { DocString.new('a <arg> that needs replacing', '', location) }
59
+ let(:name) { 'anything' }
60
+
61
+ it "replaces the arguments in the DocString" do
62
+ visitor = double
63
+ visitor.stub(:step).and_yield
64
+ expect( visitor ).to receive(:doc_string) do |doc_string|
65
+ expect( doc_string.content ).to eq "a replacement that needs replacing"
66
+ end
67
+ row = ExamplesTable::Row.new({'arg' => 'replacement'}, 1, location)
68
+ step = outline_step.to_step(row)
69
+ step.describe_to(visitor)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
@@ -0,0 +1,44 @@
1
+ require 'cucumber/core/ast/step'
2
+
3
+ module Cucumber
4
+ module Core
5
+ module Ast
6
+ describe Step do
7
+ let(:step) do
8
+ language, location, keyword, name = double, double, double, double
9
+ Step.new(language, location, keyword, name)
10
+ end
11
+
12
+ describe "describing itself" do
13
+ let(:visitor) { double }
14
+
15
+ it "describes itself as a step" do
16
+ expect( visitor ).to receive(:step).with(step)
17
+ step.describe_to(visitor)
18
+ end
19
+
20
+ context "with no multiline argument" do
21
+ it "does not try to describe any children" do
22
+ visitor.stub(:step).with(step).and_yield
23
+ step.describe_to(visitor)
24
+ end
25
+ end
26
+
27
+ context "with a multiline argument" do
28
+ let(:step) { Step.new(double, double, double, double, multiline_arg) }
29
+ let(:multiline_arg) { double }
30
+
31
+ it "tells its multiline argument to describe itself" do
32
+ visitor.stub(:step).with(step).and_yield
33
+ expect( multiline_arg ).to receive(:describe_to).with(visitor)
34
+ step.describe_to(visitor)
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,249 @@
1
+ require 'cucumber/core'
2
+ require 'cucumber/core/compiler'
3
+ require 'cucumber/core/gherkin/writer'
4
+
5
+ module Cucumber::Core
6
+ describe Compiler do
7
+ include Gherkin::Writer
8
+ include Cucumber::Core
9
+
10
+ def self.stubs(*names)
11
+ names.each do |name|
12
+ let(name) { double(name.to_s) }
13
+ end
14
+ end
15
+
16
+ it "compiles a feature with a single scenario" do
17
+ gherkin_documents = [
18
+ gherkin do
19
+ feature do
20
+ scenario do
21
+ step 'passing'
22
+ end
23
+ end
24
+ end
25
+ ]
26
+ compile(gherkin_documents) do |visitor|
27
+ expect( visitor ).to receive(:test_case).once.ordered.and_yield
28
+ expect( visitor ).to receive(:test_step).once.ordered
29
+ expect( visitor ).to receive(:done).once.ordered
30
+ end
31
+ end
32
+
33
+ it "compiles a feature with a background" do
34
+ gherkin_documents = [
35
+ gherkin do
36
+ feature do
37
+ background do
38
+ step 'passing'
39
+ end
40
+
41
+ scenario do
42
+ step 'passing'
43
+ end
44
+ end
45
+ end
46
+ ]
47
+ compile(gherkin_documents) do |visitor|
48
+ expect( visitor ).to receive(:test_case).once.ordered.and_yield
49
+ expect( visitor ).to receive(:test_step).exactly(2).times.ordered
50
+ expect( visitor ).to receive(:done).once.ordered
51
+ end
52
+ end
53
+
54
+ it "compiles multiple features" do
55
+ gherkin_documents = [
56
+ gherkin do
57
+ feature do
58
+ background do
59
+ step 'passing'
60
+ end
61
+ scenario do
62
+ step 'passing'
63
+ end
64
+ end
65
+ end,
66
+ gherkin do
67
+ feature do
68
+ background do
69
+ step 'passing'
70
+ end
71
+ scenario do
72
+ step 'passing'
73
+ end
74
+ end
75
+ end
76
+ ]
77
+ compile(gherkin_documents) do |visitor|
78
+ expect( visitor ).to receive(:test_case).once.ordered
79
+ expect( visitor ).to receive(:test_step).twice.ordered
80
+ expect( visitor ).to receive(:test_case).once.ordered
81
+ expect( visitor ).to receive(:test_step).twice.ordered
82
+ expect( visitor ).to receive(:done).once
83
+ end
84
+ end
85
+
86
+ context "compiling scenario outlines" do
87
+ it "compiles a scenario outline to test cases" do
88
+ gherkin_documents = [
89
+ gherkin do
90
+ feature do
91
+ background do
92
+ step 'passing'
93
+ end
94
+
95
+ scenario_outline do
96
+ step 'passing <arg>'
97
+ step 'passing'
98
+
99
+ examples 'examples 1' do
100
+ row 'arg'
101
+ row '1'
102
+ row '2'
103
+ end
104
+
105
+ examples 'examples 2' do
106
+ row 'arg'
107
+ row 'a'
108
+ end
109
+ end
110
+ end
111
+ end
112
+ ]
113
+ compile(gherkin_documents) do |visitor|
114
+ expect( visitor ).to receive(:test_case).exactly(3).times.and_yield
115
+ expect( visitor ).to receive(:test_step).exactly(9).times
116
+ expect( visitor ).to receive(:done).once
117
+ end
118
+ end
119
+
120
+ it 'replaces arguments correctly when generating test steps' do
121
+ gherkin_documents = [
122
+ gherkin do
123
+ feature do
124
+ scenario_outline do
125
+ step 'passing <arg1> with <arg2>'
126
+ step 'as well as <arg3>'
127
+
128
+ examples do
129
+ row 'arg1', 'arg2', 'arg3'
130
+ row '1', '2', '3'
131
+ end
132
+ end
133
+ end
134
+ end
135
+ ]
136
+
137
+ compile(gherkin_documents) do |visitor|
138
+ expect( visitor ).to receive(:test_step) do |test_step|
139
+ visit_source(test_step) do |source_visitor|
140
+ expect( source_visitor ).to receive(:step) do |step|
141
+ expect(step.name).to eq 'passing 1 with 2'
142
+ end
143
+ end
144
+ end.once.ordered
145
+
146
+ expect( visitor ).to receive(:test_step) do |test_step|
147
+ visit_source(test_step) do |source_visitor|
148
+ expect( source_visitor ).to receive(:step) do |step|
149
+ expect(step.name).to eq 'as well as 3'
150
+ end
151
+ end
152
+ end.once.ordered
153
+
154
+ expect( visitor ).to receive(:done).once.ordered
155
+ end
156
+ end
157
+ end
158
+
159
+ describe Compiler::FeatureCompiler do
160
+ let(:receiver) { double('receiver') }
161
+ let(:compiler) { Compiler::FeatureCompiler.new(receiver) }
162
+
163
+ context "a scenario with a background" do
164
+ stubs(:feature,
165
+ :background,
166
+ :background_step,
167
+ :scenario,
168
+ :scenario_step)
169
+
170
+ it "sets the source correctly on the test steps" do
171
+ expect( receiver ).to receive(:on_background_step).with(
172
+ [feature, background, background_step]
173
+ )
174
+ expect( receiver ).to receive(:on_step).with(
175
+ [feature, scenario, scenario_step]
176
+ )
177
+ expect( receiver ).to receive(:on_test_case).with(
178
+ [feature, scenario]
179
+ )
180
+ compiler.feature(feature) do |f|
181
+ f.background(background) do |b|
182
+ b.step background_step
183
+ end
184
+ f.scenario(scenario) do |s|
185
+ s.step scenario_step
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ context "a scenario outline" do
192
+ stubs(:feature,
193
+ :background,
194
+ :background_step,
195
+ :scenario_outline,
196
+ :outline_step,
197
+ :examples_table_1,
198
+ :examples_table_1_row_1,
199
+ :outline_ast_step,
200
+ :examples_table_2,
201
+ :examples_table_2_row_1,
202
+ )
203
+
204
+ it "sets the source correctly on the test steps" do
205
+ outline_step.stub(to_step: outline_ast_step)
206
+ expect( receiver ).to receive(:on_step).with(
207
+ [feature, scenario_outline, examples_table_1, examples_table_1_row_1, outline_ast_step]
208
+ ).ordered
209
+ expect( receiver ).to receive(:on_test_case).with(
210
+ [feature, scenario_outline, examples_table_1, examples_table_1_row_1]
211
+ ).ordered
212
+ expect( receiver ).to receive(:on_step).with(
213
+ [feature, scenario_outline, examples_table_2, examples_table_2_row_1, outline_ast_step]
214
+ ).ordered
215
+ expect( receiver ).to receive(:on_test_case).with(
216
+ [feature, scenario_outline, examples_table_2, examples_table_2_row_1]
217
+ ).ordered
218
+ compiler.feature(feature) do |f|
219
+ f.scenario_outline(scenario_outline) do |o|
220
+ o.outline_step outline_step
221
+ o.examples_table(examples_table_1) do |t|
222
+ t.examples_table_row(examples_table_1_row_1)
223
+ end
224
+ o.examples_table(examples_table_2) do |t|
225
+ t.examples_table_row(examples_table_2_row_1)
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ def visit_source(node)
234
+ visitor = double.as_null_object
235
+ yield visitor
236
+ node.describe_source_to(visitor)
237
+ end
238
+
239
+ def compile(gherkin_documents)
240
+ visitor = double
241
+ visitor.stub(:test_suite).and_yield
242
+ visitor.stub(:test_case).and_yield
243
+ yield visitor
244
+ super(gherkin_documents, visitor)
245
+ end
246
+
247
+ end
248
+ end
249
+