cucumber-core 0.1.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.
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,68 @@
1
+ require 'cucumber/core/test/mapper'
2
+ require 'cucumber/core/test/case'
3
+ require 'cucumber/core/test/step'
4
+
5
+ module Cucumber
6
+ module Core
7
+ module Test
8
+ describe Mapper do
9
+
10
+ ExampleMappings = Struct.new(:app) do
11
+ def test_step(test_step, mapper)
12
+ mapper.map { app.do_something } if test_step.name == 'mapped'
13
+ end
14
+ end
15
+
16
+ let(:mapper) { Mapper.new(mappings, receiver) }
17
+ let(:receiver) { double('receiver') }
18
+ before { receiver.stub(:test_case).and_yield }
19
+ let(:mappings) { ExampleMappings.new(app) }
20
+ let(:app) { double('app') }
21
+
22
+ context "an unmapped step" do
23
+ let(:test_step) { Test::Step.new([double(name: 'unmapped')]) }
24
+ let(:test_case) { Test::Case.new([test_step], double) }
25
+
26
+ it "maps to a step that executes to an undefined result" do
27
+ expect( receiver ).to receive(:test_step) do |test_step|
28
+ expect( test_step.name ).to eq 'unmapped'
29
+ expect( test_step.execute ).to be_undefined
30
+ end.once.ordered
31
+ test_case.describe_to mapper
32
+ end
33
+ end
34
+
35
+ context "a mapped step" do
36
+ let(:test_step) { Test::Step.new([double(name: 'mapped')]) }
37
+ let(:test_case) { Test::Case.new([test_step], double) }
38
+
39
+ it "maps to a step that executes the block" do
40
+ expect( receiver ).to receive(:test_step) do |test_step|
41
+ expect( test_step.name ).to eq 'mapped'
42
+ expect( app ).to receive(:do_something)
43
+ test_step.execute
44
+ end.once.ordered
45
+ test_case.describe_to mapper
46
+ end
47
+ end
48
+
49
+ context "a combination" do
50
+ let(:mapped) { Test::Step.new([double(name: 'passing')]) }
51
+ let(:unmapped) { Test::Step.new([double(name: 'unmapped')]) }
52
+ let(:test_case) { Test::Case.new([mapped, unmapped], double) }
53
+
54
+ it "maps each of the test steps" do
55
+ expect( receiver ).to receive(:test_step) do |test_step|
56
+ expect( test_step.name ).to eq 'passing'
57
+ end.once.ordered
58
+ expect( receiver ).to receive(:test_step) do |test_step|
59
+ expect( test_step.name ).to eq 'unmapped'
60
+ end.once.ordered
61
+ test_case.describe_to mapper
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,103 @@
1
+ require 'cucumber/core/test/mapping'
2
+
3
+ module Cucumber
4
+ module Core
5
+ module Test
6
+
7
+ describe Mapping do
8
+
9
+ context "constructed without a block" do
10
+ it "raises an error" do
11
+ expect { Mapping.new }.to raise_error(ArgumentError)
12
+ end
13
+ end
14
+
15
+ context "executing" do
16
+ it "executes the block passed to the constructor" do
17
+ executed = false
18
+ mapping = Mapping.new { executed = true }
19
+ mapping.execute
20
+ expect( executed ).to be_true
21
+ end
22
+
23
+ it "returns a passed result if the block doesn't fail" do
24
+ mapping = Mapping.new {}
25
+ expect( mapping.execute ).to be_passed
26
+ end
27
+
28
+ it "returns a failed result when the block raises an error" do
29
+ exception = StandardError.new
30
+ mapping = Mapping.new { raise exception }
31
+ result = mapping.execute
32
+ expect( result ).to be_failed
33
+ expect( result.exception ).to eq exception
34
+ end
35
+
36
+ it "returns a pending result if a pending error is raised" do
37
+ exception = Result::Pending.new("TODO")
38
+ mapping = Mapping.new { raise exception }
39
+ result = mapping.execute
40
+ expect( result ).to be_pending
41
+ expect( result.message ).to eq "TODO"
42
+ end
43
+
44
+ context "recording the duration" do
45
+ before do
46
+ time = double
47
+ Time.stub(now: time)
48
+ time.stub(:nsec).and_return(946752000, 946752001)
49
+ time.stub(:to_i).and_return(1377009235, 1377009235)
50
+ end
51
+
52
+ it "records the nanoseconds duration of the execution on the result" do
53
+ mapping = Mapping.new { }
54
+ duration = mapping.execute.duration
55
+ expect( duration ).to eq 1
56
+ end
57
+
58
+ it "records the duration of a failed execution" do
59
+ mapping = Mapping.new { raise StandardError }
60
+ duration = mapping.execute.duration
61
+ expect( duration ).to eq 1
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ context "skipping" do
68
+ it "does not execute the block" do
69
+ executed = false
70
+ mapping = Mapping.new { executed = true }
71
+ mapping.skip
72
+ expect( executed ).to be_false
73
+ end
74
+
75
+ it "returns a skipped result" do
76
+ mapping = Mapping.new {}
77
+ expect( mapping.skip ).to be_skipped
78
+ end
79
+ end
80
+ end
81
+
82
+ describe UndefinedMapping do
83
+ let(:mapping) { UndefinedMapping.new }
84
+ let(:test_step) { double }
85
+
86
+ context "executing" do
87
+ it "returns an undefined result" do
88
+ expect( mapping.execute ).to be_undefined
89
+ end
90
+ end
91
+
92
+ context "skipping" do
93
+ it "returns an undefined result" do
94
+ expect( mapping.skip ).to be_undefined
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+ end
102
+ end
103
+
@@ -0,0 +1,178 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'cucumber/core/test/result'
3
+
4
+ module Cucumber::Core::Test
5
+ describe Result do
6
+
7
+ let(:visitor) { double('visitor') }
8
+ let(:args) { double('args') }
9
+
10
+ describe Result::Passed do
11
+ subject(:result) { Result::Passed.new(duration) }
12
+ let(:duration) { 1 * 1000 * 1000 }
13
+
14
+ it "describes itself to a visitor" do
15
+ expect( visitor ).to receive(:passed).with(args)
16
+ expect( visitor ).to receive(:duration).with(duration, args)
17
+ result.describe_to(visitor, args)
18
+ end
19
+
20
+ it "converts to a string" do
21
+ expect( result.to_s ).to eq "✓"
22
+ end
23
+
24
+ it "has a duration" do
25
+ expect( result.duration ).to eq duration
26
+ end
27
+
28
+ it "requires the constructor argument" do
29
+ expect { Result::Passed.new }.to raise_error(ArgumentError)
30
+ end
31
+
32
+ it { expect( result ).to be_passed }
33
+ it { expect( result ).not_to be_failed }
34
+ it { expect( result ).not_to be_undefined }
35
+ it { expect( result ).not_to be_unknown }
36
+ it { expect( result ).not_to be_skipped }
37
+ end
38
+
39
+ describe Result::Failed do
40
+ subject(:result) { Result::Failed.new(duration, exception) }
41
+ let(:duration) { 1 * 1000 * 1000 }
42
+ let(:exception) { StandardError.new("error message") }
43
+
44
+ it "describes itself to a visitor" do
45
+ expect( visitor ).to receive(:failed).with(args)
46
+ expect( visitor ).to receive(:duration).with(duration, args)
47
+ expect( visitor ).to receive(:exception).with(exception, args)
48
+ result.describe_to(visitor, args)
49
+ end
50
+
51
+ it "has a duration" do
52
+ expect( result.duration ).to eq duration
53
+ end
54
+
55
+ it "requires both constructor arguments" do
56
+ expect { Result::Failed.new }.to raise_error(ArgumentError)
57
+ expect { Result::Failed.new(duration) }.to raise_error(ArgumentError)
58
+ end
59
+
60
+ it { expect( result ).not_to be_passed }
61
+ it { expect( result ).to be_failed }
62
+ it { expect( result ).not_to be_undefined }
63
+ it { expect( result ).not_to be_unknown }
64
+ it { expect( result ).not_to be_skipped }
65
+ end
66
+
67
+ describe Result::Unknown do
68
+ subject(:result) { Result::Unknown.new }
69
+
70
+ it "doesn't describe itself to a visitor" do
71
+ visitor = double('never receives anything')
72
+ result.describe_to(visitor, args)
73
+ end
74
+
75
+ it "has no duration" do
76
+ expect { result.duration }.to raise_error NoMethodError
77
+ end
78
+
79
+ it { expect( result ).not_to be_passed }
80
+ it { expect( result ).not_to be_failed }
81
+ it { expect( result ).not_to be_undefined }
82
+ it { expect( result ).to be_unknown }
83
+ it { expect( result ).not_to be_skipped }
84
+ end
85
+
86
+ describe Result::Undefined do
87
+ subject(:result) { Result::Undefined.new }
88
+
89
+ it "describes itself to a visitor" do
90
+ expect( visitor ).to receive(:undefined).with(args)
91
+ result.describe_to(visitor, args)
92
+ end
93
+
94
+ it { expect( result ).not_to be_passed }
95
+ it { expect( result ).not_to be_failed }
96
+ it { expect( result ).to be_undefined }
97
+ it { expect( result ).not_to be_unknown }
98
+ it { expect( result ).not_to be_skipped }
99
+ end
100
+
101
+ describe Result::Skipped do
102
+ subject(:result) { Result::Skipped.new }
103
+
104
+ it "describes itself to a visitor" do
105
+ expect( visitor ).to receive(:skipped).with(args)
106
+ result.describe_to(visitor, args)
107
+ end
108
+
109
+ it "has no duration" do
110
+ expect { result.duration }.to raise_error NoMethodError
111
+ end
112
+
113
+ it { expect( result ).not_to be_passed }
114
+ it { expect( result ).not_to be_failed }
115
+ it { expect( result ).not_to be_undefined }
116
+ it { expect( result ).not_to be_unknown }
117
+ it { expect( result ).to be_skipped }
118
+ end
119
+
120
+ describe Result::Summary do
121
+ let(:summary) { Result::Summary.new }
122
+ let(:failed) { Result::Failed.new(10, exception) }
123
+ let(:passed) { Result::Passed.new(11) }
124
+ let(:skipped) { Result::Skipped.new }
125
+ let(:unknown) { Result::Unknown.new }
126
+ let(:undefined) { Result::Undefined.new }
127
+ let(:exception) { StandardError.new }
128
+
129
+ it "counts failed results" do
130
+ failed.describe_to summary
131
+ expect( summary.total_failed ).to eq 1
132
+ expect( summary.total ).to eq 1
133
+ end
134
+
135
+ it "counts passed results" do
136
+ passed.describe_to summary
137
+ expect( summary.total_passed ).to eq 1
138
+ expect( summary.total ).to eq 1
139
+ end
140
+
141
+ it "counts skipped results" do
142
+ skipped.describe_to summary
143
+ expect( summary.total_skipped ).to eq 1
144
+ expect( summary.total ).to eq 1
145
+ end
146
+
147
+ it "counts undefined results" do
148
+ undefined.describe_to summary
149
+ expect( summary.total_undefined ).to eq 1
150
+ expect( summary.total ).to eq 1
151
+ end
152
+
153
+ it "doesn't count unknown results" do
154
+ unknown.describe_to summary
155
+ expect( summary.total ).to eq 0
156
+ end
157
+
158
+ it "counts combinations" do
159
+ [passed, passed, failed, skipped, undefined].each { |r| r.describe_to summary }
160
+ expect( summary.total ).to eq 5
161
+ expect( summary.total_passed ).to eq 2
162
+ expect( summary.total_failed ).to eq 1
163
+ expect( summary.total_skipped ).to eq 1
164
+ expect( summary.total_undefined ).to eq 1
165
+ end
166
+
167
+ it "records durations" do
168
+ [passed, failed].each { |r| r.describe_to summary }
169
+ expect( summary.durations ).to eq [11, 10]
170
+ end
171
+
172
+ it "records exceptions" do
173
+ [passed, failed].each { |r| r.describe_to summary }
174
+ expect( summary.exceptions ).to eq [exception]
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,265 @@
1
+ require 'cucumber/core/test/runner'
2
+ require 'cucumber/core/test/case'
3
+ require 'cucumber/core/test/step'
4
+
5
+ module Cucumber::Core::Test
6
+ describe Runner do
7
+
8
+ let(:test_case) { Case.new(test_steps, source) }
9
+ let(:source) { double }
10
+ let(:runner) { Runner.new(report) }
11
+ let(:report) { double.as_null_object }
12
+ let(:passing) { Step.new([double]).map {} }
13
+ let(:failing) { Step.new([double]).map { raise exception } }
14
+ let(:pending) { Step.new([double]).map { raise Result::Pending.new("TODO") } }
15
+ let(:undefined) { Step.new([double]) }
16
+ let(:exception) { StandardError.new('test error') }
17
+
18
+ context "reporting the duration of a test case" do
19
+ before do
20
+ time = double
21
+ Time.stub(now: time)
22
+ time.stub(:nsec).and_return(946752000, 946752001)
23
+ time.stub(:to_i).and_return(1377009235, 1377009235)
24
+ end
25
+
26
+ context "for a passing test case" do
27
+ let(:test_steps) { [passing] }
28
+
29
+ it "records the nanoseconds duration of the execution on the result" do
30
+ expect( report ).to receive(:after_test_case) do |reported_test_case, result|
31
+ expect( result.duration ).to eq 1
32
+ end
33
+ test_case.describe_to runner
34
+ end
35
+ end
36
+
37
+ context "for a failing test case" do
38
+ let(:test_steps) { [failing] }
39
+
40
+ it "records the duration" do
41
+ expect( report ).to receive(:after_test_case) do |reported_test_case, result|
42
+ expect( result.duration ).to eq 1
43
+ end
44
+ test_case.describe_to runner
45
+ end
46
+ end
47
+ end
48
+
49
+ context "reporting the exception that failed a test case" do
50
+ let(:test_steps) { [failing] }
51
+ it "sets the exception on the result" do
52
+ expect( report ).to receive(:after_test_case) do |reported_test_case, result|
53
+ expect( result.exception ).to eq exception
54
+ end
55
+ test_case.describe_to runner
56
+ end
57
+ end
58
+
59
+ context "with a single case" do
60
+ context "without steps" do
61
+ let(:test_steps) { [] }
62
+
63
+ it "calls the report before running the case" do
64
+ expect( report ).to receive(:before_test_case).with(test_case)
65
+ test_case.describe_to runner
66
+ end
67
+
68
+ it "calls the report after running the case" do
69
+ expect( report ).to receive(:after_test_case) do |reported_test_case, result|
70
+ expect( reported_test_case ).to eq test_case
71
+ expect( result ).to be_unknown
72
+ end
73
+ test_case.describe_to runner
74
+ end
75
+ end
76
+
77
+ context 'with steps' do
78
+ context 'that all pass' do
79
+ let(:test_steps) { [ passing, passing ] }
80
+
81
+ it 'reports a passing test case' do
82
+ expect( report ).to receive(:after_test_case) do |test_case, result|
83
+ expect( result ).to be_passed
84
+ end
85
+ test_case.describe_to runner
86
+ end
87
+ end
88
+
89
+ context 'an undefined step' do
90
+ let(:test_steps) { [ undefined ] }
91
+
92
+ it 'reports an undefined test case' do
93
+ expect( report ).to receive(:after_test_case) do |test_case, result|
94
+ expect( result ).to be_undefined
95
+ end
96
+ test_case.describe_to runner
97
+ end
98
+ end
99
+
100
+ context 'a pending step' do
101
+ let(:test_steps) { [ pending ] }
102
+
103
+ it 'reports a pending test case' do
104
+ expect( report ).to receive(:after_test_case) do |test_case, result|
105
+ expect( result ).to be_pending
106
+ end
107
+ test_case.describe_to runner
108
+ end
109
+ end
110
+
111
+ context 'that fail' do
112
+ let(:test_steps) { [ failing ] }
113
+
114
+ it 'reports a failing test case' do
115
+ expect( report ).to receive(:after_test_case) do |test_case, result|
116
+ expect( result ).to be_failed
117
+ end
118
+ test_case.describe_to runner
119
+ end
120
+ end
121
+
122
+ context 'where the first step fails' do
123
+ let(:test_steps) { [ failing, passing ] }
124
+
125
+ it 'reports the first step as failed' do
126
+ expect( report ).to receive(:after_test_step).with(failing, anything) do |test_step, result|
127
+ expect( result ).to be_failed
128
+ end
129
+ test_case.describe_to runner
130
+ end
131
+
132
+ it 'reports the second step as skipped' do
133
+ expect( report ).to receive(:after_test_step).with(passing, anything) do |test_step, result|
134
+ expect( result ).to be_skipped
135
+ end
136
+ test_case.describe_to runner
137
+ end
138
+
139
+ it 'reports the test case as failed' do
140
+ expect( report ).to receive(:after_test_case) do |test_case, result|
141
+ expect( result ).to be_failed
142
+ expect( result.exception ).to eq exception
143
+ end
144
+ test_case.describe_to runner
145
+ end
146
+
147
+ it 'skips, rather than executing the second step' do
148
+ expect( passing ).not_to receive(:execute)
149
+ expect( passing ).to receive(:skip)
150
+ test_case.describe_to runner
151
+ end
152
+ end
153
+
154
+ end
155
+ end
156
+
157
+ context 'with multiple test cases' do
158
+ context 'when the first test case fails' do
159
+ let(:first_test_case) { Case.new([failing], source) }
160
+ let(:last_test_case) { Case.new([passing], source) }
161
+ let(:test_cases) { [first_test_case, last_test_case] }
162
+
163
+ it 'reports the results correctly for the following test case' do
164
+ expect( report ).to receive(:after_test_case).with(last_test_case, anything) do |reported_test_case, result|
165
+ expect( result ).to be_passed
166
+ end
167
+
168
+ test_cases.each { |c| c.describe_to runner }
169
+ end
170
+ end
171
+ end
172
+
173
+ end
174
+
175
+ describe 'with the dry run strategy' do
176
+
177
+ let(:report) { double(:report).as_null_object }
178
+ let(:source) { double(:source) }
179
+ let(:runner) { Runner.new(report, :run_mode => :dry_run) }
180
+ let(:passing) { Step.new([double]).map {} }
181
+ let(:undefined) { Step.new([double]) }
182
+ let(:test_case) { Case.new(test_steps, source) }
183
+
184
+ context 'with a passing step' do
185
+ let(:test_steps) { [passing] }
186
+
187
+ it 'reports the test case as skipped' do
188
+ report.should_receive(:after_test_case) do |test_case, result|
189
+ result.should be_skipped
190
+ end
191
+ test_case.describe_to runner
192
+ end
193
+
194
+ it 'reports the test step has been skipped' do
195
+ report.should_receive(:after_test_step) do |test_step, result|
196
+ result.should be_skipped
197
+ end
198
+ test_case.describe_to runner
199
+ end
200
+ end
201
+
202
+ context 'with a undefined step' do
203
+ let(:test_steps) { [undefined] }
204
+
205
+ it 'reports the test case as undefined' do
206
+ report.should_receive(:after_test_case) do |test_case, result|
207
+ result.should be_undefined
208
+ end
209
+ test_case.describe_to runner
210
+ end
211
+
212
+
213
+ it 'reports the test step as undefined' do
214
+ report.should_receive(:after_test_step) do |test_step, result|
215
+ result.should be_undefined
216
+ end
217
+ test_case.describe_to runner
218
+ end
219
+ end
220
+
221
+ context 'with passing and undefined steps' do
222
+ let(:test_steps) { [passing, undefined] }
223
+
224
+ it 'reports the test case as undefined' do
225
+ report.should_receive(:after_test_case) do |test_case, result|
226
+ result.should be_undefined
227
+ end
228
+ test_case.describe_to runner
229
+ end
230
+
231
+ it 'reports the passing step as skipped' do
232
+ report.should_receive(:after_test_step).with(passing, anything) do |test_case, result|
233
+ result.should be_skipped
234
+ end
235
+ test_case.describe_to runner
236
+ end
237
+
238
+ it 'reports the undefined step as undefined' do
239
+ report.should_receive(:after_test_step).with(undefined, anything) do |test_case, result|
240
+ result.should be_undefined
241
+ end
242
+ test_case.describe_to runner
243
+ end
244
+ end
245
+
246
+ context 'with multiple test cases' do
247
+ context 'when the first test case is undefined' do
248
+ let(:first_test_case) { Case.new([undefined], source) }
249
+ let(:last_test_case) { Case.new([passing], source) }
250
+ let(:test_cases) { [first_test_case, last_test_case] }
251
+
252
+ it 'reports the results correctly for the following test case' do
253
+ report.
254
+ should_receive(:after_test_case).
255
+ with(last_test_case, anything) do |reported_test_case, result|
256
+ result.should be_skipped
257
+ end
258
+
259
+ test_cases.each { |c| c.describe_to runner }
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ end