spinach 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +1 -0
  2. data/.yardopts +6 -0
  3. data/Gemfile +1 -0
  4. data/Guardfile +7 -0
  5. data/Rakefile +1 -0
  6. data/Readme.md +147 -10
  7. data/features/{generate_features.feature → automatic_feature_generation.feature} +0 -0
  8. data/features/steps/automatic_feature_generation.rb +5 -2
  9. data/features/steps/exit_status.rb +8 -3
  10. data/features/steps/feature_name_guessing.rb +4 -1
  11. data/features/steps/reporting/display_run_summary.rb +7 -4
  12. data/features/steps/reporting/error_reporting.rb +7 -2
  13. data/features/steps/reporting/show_step_source_location.rb +9 -5
  14. data/features/steps/reporting/undefined_feature_reporting.rb +4 -1
  15. data/features/steps/rspec_compatibility.rb +6 -2
  16. data/features/support/spinach_runner.rb +2 -9
  17. data/lib/spinach/capybara.rb +3 -4
  18. data/lib/spinach/cli.rb +0 -1
  19. data/lib/spinach/config.rb +0 -8
  20. data/lib/spinach/dsl.rb +4 -13
  21. data/lib/spinach/exceptions.rb +1 -1
  22. data/lib/spinach/feature_steps.rb +1 -9
  23. data/lib/spinach/generators/feature_generator.rb +3 -2
  24. data/lib/spinach/generators.rb +1 -1
  25. data/lib/spinach/hookable.rb +81 -0
  26. data/lib/spinach/hooks.rb +132 -0
  27. data/lib/spinach/reporter/stdout/error_reporting.rb +163 -0
  28. data/lib/spinach/reporter/stdout.rb +3 -151
  29. data/lib/spinach/reporter.rb +39 -25
  30. data/lib/spinach/runner/{feature.rb → feature_runner.rb} +5 -15
  31. data/lib/spinach/runner/scenario_runner.rb +65 -0
  32. data/lib/spinach/runner.rb +5 -11
  33. data/lib/spinach/version.rb +1 -1
  34. data/lib/spinach.rb +20 -8
  35. data/spinach.gemspec +2 -3
  36. data/test/spinach/capybara_test.rb +4 -3
  37. data/test/spinach/cli_test.rb +0 -1
  38. data/test/spinach/feature_steps_test.rb +6 -23
  39. data/test/spinach/generators/feature_generator_test.rb +2 -2
  40. data/test/spinach/generators_test.rb +2 -2
  41. data/test/spinach/hookable_test.rb +59 -0
  42. data/test/spinach/hooks_test.rb +28 -0
  43. data/test/spinach/reporter/stdout/error_reporting_test.rb +265 -0
  44. data/test/spinach/reporter/stdout_test.rb +1 -238
  45. data/test/spinach/reporter_test.rb +58 -103
  46. data/test/spinach/runner/{feature_test.rb → feature_runner_test.rb} +21 -23
  47. data/test/spinach/runner/scenario_runner_test.rb +111 -0
  48. data/test/spinach/runner_test.rb +1 -1
  49. data/test/spinach_test.rb +19 -18
  50. data/test/test_helper.rb +1 -1
  51. metadata +60 -61
  52. data/lib/spinach/runner/scenario.rb +0 -77
  53. data/test/spinach/runner/scenario_test.rb +0 -120
@@ -193,7 +193,7 @@ describe Spinach::Reporter::Stdout do
193
193
  end
194
194
 
195
195
  it 'tells the user what to write in the file' do
196
- @out.string.must_include 'Feature \'This feature does not exist\' do'
196
+ @out.string.must_include 'This feature does not exist'
197
197
  end
198
198
  end
199
199
 
@@ -238,219 +238,6 @@ describe Spinach::Reporter::Stdout do
238
238
  end
239
239
  end
240
240
 
241
- describe '#error_summary' do
242
- it 'prints a summary with all the errors' do
243
- @reporter.expects(:report_error_steps).once
244
- @reporter.expects(:report_failed_steps).once
245
- @reporter.expects(:report_undefined_steps).once
246
- @reporter.expects(:report_undefined_features).once
247
-
248
- @reporter.error_summary
249
-
250
- @error.string.must_include 'Error summary'
251
- end
252
- end
253
-
254
- describe '#run_summary' do
255
- it 'prints a run summary' do
256
- @reporter.run_summary
257
-
258
- @out.string.must_include 'Steps Summary:'
259
- end
260
- end
261
-
262
- describe '#report_error_steps' do
263
- describe 'when some steps have raised an error' do
264
- it 'outputs the errors' do
265
- steps = [anything]
266
- @reporter.stubs(:error_steps).returns(steps)
267
- @reporter.expects(:report_errors).with('Errors', steps, :light_red)
268
-
269
- @reporter.report_error_steps
270
- end
271
- end
272
-
273
- describe 'when there are no error steps' do
274
- it 'does nothing' do
275
- @reporter.expects(:report_errors).never
276
-
277
- @reporter.report_error_steps
278
- end
279
- end
280
- end
281
-
282
- describe '#report_failed_steps' do
283
- describe 'when some steps have failed' do
284
- it 'outputs the failing steps' do
285
- steps = [anything]
286
- @reporter.stubs(:failed_steps).returns(steps)
287
- @reporter.expects(:report_errors).with('Failures', steps, :light_red)
288
-
289
- @reporter.report_failed_steps
290
- end
291
- end
292
-
293
- describe 'when there are no failed steps' do
294
- it 'does nothing' do
295
- @reporter.expects(:report_errors).never
296
-
297
- @reporter.report_failed_steps
298
- end
299
- end
300
- end
301
-
302
- describe '#report_undefined_steps' do
303
- describe 'when some steps have undefined' do
304
- it 'outputs the failing steps' do
305
- steps = [anything]
306
- @reporter.stubs(:undefined_steps).returns(steps)
307
- @reporter.expects(:report_errors).with('Undefined steps', steps, :yellow)
308
-
309
- @reporter.report_undefined_steps
310
- end
311
- end
312
-
313
- describe 'when there are no undefined steps' do
314
- it 'does nothing' do
315
- @reporter.expects(:report_errors).never
316
-
317
- @reporter.report_undefined_steps
318
- end
319
- end
320
- end
321
-
322
- describe '#report_undefined_features' do
323
- describe 'when some features are undefined' do
324
- it 'outputs the undefined features' do
325
- @reporter.undefined_features << {'name' => 'Undefined feature name'}
326
- @reporter.report_undefined_features
327
-
328
- @error.string.must_include "Undefined features (1)"
329
- @error.string.must_include "Undefined feature name"
330
- end
331
- end
332
-
333
- describe 'when there are no undefined features' do
334
- it 'does nothing' do
335
- error = @error.string.dup
336
- @reporter.report_undefined_steps
337
-
338
- error.must_equal @error.string
339
- end
340
- end
341
- end
342
-
343
- describe '#report_errors' do
344
- describe 'when some steps have raised an error' do
345
- it 'outputs a the banner with the number of steps given' do
346
- @reporter.report_errors('Banner', steps, :blue)
347
-
348
- @error.string.must_include 'Banner (1)'
349
- end
350
-
351
- it 'prints a summarized error' do
352
- @reporter.report_errors('Banner', steps, :blue)
353
-
354
- @error.string.must_include 'My feature :: A scenario :: Keyword step name'
355
- end
356
-
357
- it 'colorizes the output' do
358
- String.any_instance.expects(:colorize).with(:blue).at_least_once
359
-
360
- @reporter.report_errors('Banner', [], :blue)
361
- end
362
- end
363
- end
364
-
365
- describe '#report_error' do
366
- it 'raises when given an unsupported format' do
367
- proc {
368
- @reporter.report_error(error, :nil)
369
- }.must_raise RuntimeError, 'Format not defined'
370
- end
371
-
372
- it 'prints a summarized error by default' do
373
- @reporter.expects(:summarized_error).with(error).returns('summarized error')
374
-
375
- @reporter.report_error(error)
376
-
377
- @error.string.must_include 'summarized error'
378
- end
379
-
380
- it 'prints a summarized error' do
381
- @reporter.expects(:summarized_error).with(error).returns('summarized error')
382
-
383
- @reporter.report_error(error, :summarized)
384
-
385
- @error.string.must_include 'summarized error'
386
- end
387
-
388
- it 'prints a full error' do
389
- @reporter.expects(:full_error).with(error).returns('full error')
390
-
391
- @reporter.report_error(error, :full)
392
-
393
- @error.string.must_include 'full error'
394
- end
395
- end
396
-
397
- describe '#summarized_error' do
398
- it 'prints the error' do
399
- summary = @reporter.summarized_error(error)
400
-
401
- summary.must_include 'My feature :: A scenario :: Keyword step name'
402
- end
403
-
404
- it 'colorizes the print' do
405
- String.any_instance.expects(:red)
406
-
407
- @reporter.summarized_error(error)
408
- end
409
-
410
- describe 'when given an undefined step exception' do
411
- it 'prints the error in yellow' do
412
- undefined_error = error
413
- undefined_error.insert(3, Spinach::StepNotDefinedException.new(anything))
414
-
415
- String.any_instance.expects(:yellow)
416
-
417
- @reporter.summarized_error(error)
418
- end
419
- end
420
- end
421
-
422
- describe '#full_error' do
423
- before do
424
- @reporter.expects(:report_exception).with(exception).returns('Exception backtrace')
425
- end
426
-
427
- it 'returns the exception data' do
428
- exception.expects(:backtrace).returns(['first backtrace line'])
429
- output = @reporter.full_error(error)
430
-
431
- output.must_include 'Exception backtrace'
432
- end
433
-
434
- it 'returns the first backtrace line' do
435
- exception.expects(:backtrace).returns(['first backtrace line'])
436
- output = @reporter.full_error(error)
437
-
438
- output.must_include 'first backtrace line'
439
- end
440
-
441
- describe 'when the user wants to print the full backtrace' do
442
- it 'prints the full backtrace' do
443
- @reporter.stubs(:options).returns({backtrace: true})
444
- exception.expects(:backtrace).returns(['first backtrace line', 'second backtrace line'])
445
-
446
- output = @reporter.full_error(error)
447
-
448
- output.must_include 'first backtrace line'
449
- output.must_include 'second backtrace line'
450
- end
451
- end
452
- end
453
-
454
241
  describe '#full_step' do
455
242
  it 'returns the step with keyword and name' do
456
243
  @reporter.full_step({'keyword' => 'Keyword', 'name' => 'step name'}).must_equal 'Keyword step name'
@@ -460,28 +247,4 @@ describe Spinach::Reporter::Stdout do
460
247
  @reporter.full_step({'keyword' => ' Keyword ', 'name' => ' step name '}).must_equal 'Keyword step name'
461
248
  end
462
249
  end
463
-
464
- describe '#report_exception' do
465
- it 'returns the exception data' do
466
- output = @reporter.report_exception(exception)
467
-
468
- output.must_include 'Something went wrong'
469
- end
470
-
471
- it 'colorizes the print' do
472
- String.any_instance.expects(:red)
473
-
474
- @reporter.report_exception(exception)
475
- end
476
-
477
- describe 'when given an undefined step exception' do
478
- it 'prints the error in yellow' do
479
- undefined_exception = Spinach::StepNotDefinedException.new(anything)
480
-
481
- String.any_instance.expects(:yellow)
482
-
483
- @reporter.report_exception(undefined_exception)
484
- end
485
- end
486
- end
487
250
  end
@@ -10,11 +10,6 @@ module Spinach
10
10
  @reporter = Reporter.new(@options)
11
11
  end
12
12
 
13
- describe "#initialize" do
14
- it "initializes the option hash" do
15
- end
16
- end
17
-
18
13
  describe "#options" do
19
14
  it "returns the options passed to the reporter" do
20
15
  @reporter.options[:backtrace].must_equal true
@@ -52,124 +47,84 @@ module Spinach
52
47
  @reporter.stubs(:method)
53
48
  end
54
49
 
55
- it "binds a callback after running all the suite" do
56
- @reporter.expects(:method).with(:after_run).returns(@callback)
57
- @reporter.runner.expects(:after_run).with(@callback)
58
- @reporter.bind
59
- end
60
-
61
- it "binds a callback before running every feature" do
62
- @reporter.expects(:method).with(:before_feature_run).returns(@callback)
63
- @reporter.feature_runner.expects(:before_run).with(@callback)
64
- @reporter.bind
65
- end
66
-
67
- it "binds a callback after running every feature" do
68
- @reporter.expects(:method).with(:after_feature_run).returns(@callback)
69
- @reporter.feature_runner.expects(:after_run).with(@callback)
70
- @reporter.bind
71
- end
72
-
73
- it "binds a callback for not defined features" do
74
- @reporter.expects(:method).with(:on_feature_not_found).returns(@callback)
75
- @reporter.feature_runner.expects(:when_not_found).with(@callback)
76
- @reporter.bind
77
- end
78
-
79
- it "binds a callback before running every scenario" do
80
- @reporter.expects(:method).with(:before_scenario_run).returns(@callback)
81
- @reporter.scenario_runner.expects(:before_run).with(@callback)
82
- @reporter.bind
83
- end
50
+ describe "bindings" do
51
+ before do
52
+ @reporter.bind
53
+ end
84
54
 
85
- it "binds a callback after running every feature" do
86
- @reporter.expects(:method).with(:after_scenario_run).returns(@callback)
87
- @reporter.scenario_runner.expects(:after_run).with(@callback)
88
- @reporter.bind
89
- end
55
+ after do
56
+ Spinach.hooks.reset
57
+ end
90
58
 
91
- describe "when running steps" do
92
- %w{successful failed error undefined skipped}.each do |type|
93
- it "binds a callback after running a #{type} step" do
94
- @reporter.expects(:method).with(:"on_#{type}_step").returns(@callback)
95
- @reporter.scenario_runner.expects(:"on_#{type}_step").with(@callback)
96
- @reporter.bind
97
- end
59
+ it "binds a callback after running" do
60
+ @reporter.expects(:after_run)
61
+ Spinach.hooks.run_after_run
98
62
  end
99
- end
100
63
 
101
- describe "binds the context methods" do
102
- it "binds the current feature setter" do
103
- @reporter.expects(:method).with(:current_feature=).returns(@callback)
104
- @reporter.feature_runner.expects(:before_run).with(@callback)
105
- @reporter.bind
64
+ it "binds a callback before running every feature" do
65
+ @reporter.expects(:before_feature_run)
66
+ Spinach.hooks.run_before_feature(anything)
106
67
  end
107
68
 
108
- it "binds the current feature clearer" do
109
- @reporter.expects(:method).with(:clear_current_feature).returns(@callback)
110
- @reporter.feature_runner.expects(:after_run).with(@callback)
111
- @reporter.bind
69
+ it "binds a callback after running every feature" do
70
+ @reporter.expects(:after_feature_run)
71
+ Spinach.hooks.run_after_feature
112
72
  end
113
73
 
114
- it "binds the current scenario setter" do
115
- @reporter.expects(:method).with(:current_scenario=).returns(@callback)
116
- @reporter.scenario_runner.expects(:before_run).with(@callback)
117
- @reporter.bind
74
+ it "binds a callback when a feature is not found" do
75
+ @reporter.expects(:on_feature_not_found)
76
+ Spinach.hooks.run_on_undefined_feature
118
77
  end
119
78
 
120
- it "binds the current feature clearer" do
121
- @reporter.expects(:method).with(:clear_current_scenario).returns(@callback)
122
- @reporter.scenario_runner.expects(:after_run).with(@callback)
123
- @reporter.bind
79
+ it "binds a callback before every scenario" do
80
+ @reporter.expects(:before_scenario_run)
81
+ Spinach.hooks.run_before_scenario(anything)
124
82
  end
125
- end
126
- end
127
83
 
128
- describe "#clear_current_feature" do
129
- it "clears the current feature" do
130
- @reporter.current_feature = mock
131
- @reporter.clear_current_feature
132
- @reporter.current_feature.must_equal nil
133
- end
134
- end
84
+ it "binds a callback after every scenario" do
85
+ @reporter.expects(:after_scenario_run)
86
+ Spinach.hooks.run_after_scenario
87
+ end
135
88
 
136
- describe "#clear_current_scenario" do
137
- it "clears the current scenario" do
138
- @reporter.current_scenario = mock
139
- @reporter.clear_current_scenario
140
- @reporter.current_scenario.must_equal nil
141
- end
142
- end
89
+ it "binds a callback after every successful step" do
90
+ @reporter.expects(:on_successful_step)
91
+ Spinach.hooks.run_on_successful_step
92
+ end
143
93
 
144
- describe "runner classes" do
145
- describe "#feature_runner" do
146
- it "returns a runner class" do
147
- @reporter.feature_runner.must_be_kind_of Class
94
+ it "binds a callback after every failed step" do
95
+ @reporter.expects(:on_failed_step)
96
+ Spinach.hooks.run_on_failed_step
148
97
  end
149
- end
150
98
 
151
- describe "#scenario_runner" do
152
- it "returns a runner class" do
153
- @reporter.scenario_runner.must_be_kind_of Class
99
+ it "binds a callback after every error step" do
100
+ @reporter.expects(:on_error_step)
101
+ Spinach.hooks.run_on_error_step
154
102
  end
155
- end
156
103
 
157
- describe "#runner" do
158
- it "returns a runner class" do
159
- @reporter.runner.must_be_kind_of Class
104
+ it "binds a callback after every skipped step" do
105
+ @reporter.expects(:on_skipped_step)
106
+ Spinach.hooks.run_on_skipped_step
160
107
  end
161
- end
162
- end
163
108
 
164
- describe "callback methods" do
165
- %w{
166
- after_run before_feature_run after_feature_run before_scenario_run
167
- after_scenario_run on_successful_step on_failed_step on_error_step
168
- on_undefined_step on_skipped_step
169
- }.each do |callback|
170
- describe "##{callback}" do
171
- it "does nothing" do
172
- @reporter.send(callback)
109
+ describe "internals" do
110
+ it "binds a callback before running" do
111
+ @reporter.expects(:set_current_feature)
112
+ Spinach.hooks.run_before_feature({})
113
+ end
114
+
115
+ it "binds a callback after running" do
116
+ @reporter.expects(:clear_current_feature)
117
+ Spinach.hooks.run_after_feature
118
+ end
119
+
120
+ it "binds a callback before every scenario" do
121
+ @reporter.expects(:set_current_scenario)
122
+ Spinach.hooks.run_before_scenario
123
+ end
124
+
125
+ it "binds a callback after every scenario" do
126
+ @reporter.expects(:clear_current_scenario)
127
+ Spinach.hooks.run_after_scenario
173
128
  end
174
129
  end
175
130
  end
@@ -1,17 +1,17 @@
1
1
  require_relative '../../test_helper'
2
2
 
3
- describe Spinach::Runner::Feature do
3
+ describe Spinach::Runner::FeatureRunner do
4
4
  let(:filename) { 'feature/a_cool_feature.feature' }
5
- let(:feature) { Spinach::Runner::Feature.new(filename) }
5
+ subject{ Spinach::Runner::FeatureRunner.new(filename) }
6
6
 
7
7
  describe '#initialize' do
8
8
  it 'initializes the given filename' do
9
- feature.filename.must_equal filename
9
+ subject.filename.must_equal filename
10
10
  end
11
11
 
12
12
  it 'initalizes the given scenario line' do
13
13
  @filename = 'feature/a_cool_feature.feature:12'
14
- @feature = Spinach::Runner::Feature.new(@filename)
14
+ @feature = Spinach::Runner::FeatureRunner.new(@filename)
15
15
 
16
16
  @feature.instance_variable_get(:@scenario_line).must_equal '12'
17
17
  end
@@ -22,77 +22,75 @@ describe Spinach::Runner::Feature do
22
22
  parsed_data = {name: 'A cool feature'}
23
23
  parser = stub(parse: parsed_data)
24
24
  Spinach::Parser.expects(:open_file).returns(parser)
25
- feature.data.must_equal parsed_data
25
+ subject.data.must_equal parsed_data
26
26
  end
27
27
  end
28
28
 
29
29
  describe '#scenarios' do
30
30
  it 'returns the parsed scenarios' do
31
- feature.stubs(data: {'elements' => [1, 2, 3]})
32
- feature.scenarios.must_equal [1,2,3]
31
+ subject.stubs(data: {'elements' => [1, 2, 3]})
32
+ subject.scenarios.must_equal [1,2,3]
33
33
  end
34
34
  end
35
35
 
36
36
  describe '#run' do
37
37
  before do
38
- feature.stubs(data: {
38
+ subject.stubs(data: {
39
39
  'name' => 'A cool feature',
40
40
  'elements' => [{'keyword'=>'Scenario', 'name'=>'Basic guess', 'line'=>6, 'description'=>'', 'type'=>'scenario'},
41
41
  {'keyword'=>'Scenario', 'name'=>'Basic guess II', 'line'=>12, 'description'=>'', 'type'=>'scenario'},
42
42
  {'keyword'=>'Scenario', 'name'=>'Basic guess III', 'line'=>18, 'description'=>'', 'type'=>'scenario'}]
43
43
  })
44
- feature.stubs(feature: stub_everything)
44
+ subject.stubs(feature: stub_everything)
45
45
  end
46
46
 
47
47
  it 'calls the steps as expected' do
48
48
  seq = sequence('feature')
49
49
  3.times do
50
- Spinach::Runner::Scenario.
50
+ Spinach::Runner::ScenarioRunner.
51
51
  expects(:new).
52
52
  returns(stub_everything).
53
53
  in_sequence(seq)
54
54
  end
55
- feature.run
55
+ subject.run
56
56
  end
57
57
 
58
58
  it 'returns true if the execution succeeds' do
59
- Spinach::Runner::Scenario.any_instance.
59
+ Spinach::Runner::ScenarioRunner.any_instance.
60
60
  expects(run: true).times(3)
61
- feature.run.must_equal true
61
+ subject.run.must_equal true
62
62
  end
63
63
 
64
64
  it 'returns false if the execution fails' do
65
- Spinach::Runner::Scenario.any_instance.
65
+ Spinach::Runner::ScenarioRunner.any_instance.
66
66
  expects(run: false).times(3)
67
- feature.run.must_equal false
67
+ subject.run.must_equal false
68
68
  end
69
69
 
70
70
  it 'calls only the given scenario' do
71
71
  @filename = 'feature/a_cool_feature.feature:12'
72
- @feature = Spinach::Runner::Feature.new(@filename)
72
+ @feature = Spinach::Runner::FeatureRunner.new(@filename)
73
73
  @feature.stubs(data: {
74
74
  'name' => 'A cool feature',
75
75
  'elements' => [{'keyword'=>'Scenario', 'name'=>'Basic guess', 'line'=>6, 'description'=>'', 'type'=>'scenario'},
76
76
  {'keyword'=>'Scenario', 'name'=>'Basic guess II', 'line'=>12, 'description'=>'', 'type'=>'scenario'},
77
77
  {'keyword'=>'Scenario', 'name'=>'Basic guess III', 'line'=>18, 'description'=>'', 'type'=>'scenario'}]
78
78
  })
79
- @feature.stubs(feature: stub_everything)
80
79
 
81
- Spinach::Runner::Scenario.expects(:new).with(anything, @feature.scenarios[1], anything).once.returns(stub_everything)
80
+ Spinach::Runner::ScenarioRunner.expects(:new).with(anything, @feature.scenarios[1], anything).once.returns(stub_everything)
82
81
  @feature.run
83
82
  end
84
83
 
85
84
  it "fires a hook if the feature is not defined" do
86
- feature = Spinach::Runner::Feature.new(filename)
87
85
  data = mock
88
86
  exception = Spinach::FeatureStepsNotFoundException.new([anything, anything])
89
- feature.stubs(:scenarios).raises(exception)
90
- feature.stubs(:data).returns(data)
87
+ subject.stubs(:scenarios).raises(exception)
88
+ subject.stubs(:data).returns(data)
91
89
  not_found_called = false
92
- feature.class.when_not_found do |data, exception|
90
+ Spinach.hooks.on_undefined_feature do |data, exception|
93
91
  not_found_called = [data, exception]
94
92
  end
95
- feature.run
93
+ subject.run
96
94
  not_found_called.must_equal [data, exception]
97
95
  end
98
96
  end
@@ -0,0 +1,111 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe Spinach::Runner::ScenarioRunner do
4
+ let(:data) do
5
+ {
6
+ 'name' => 'A cool scenario',
7
+ 'steps' => [
8
+ {'keyword' => 'Given', 'name' => 'I herd you like steps'},
9
+ {'keyword' => 'When', 'name' => 'I test steps'},
10
+ {'keyword' => 'Then', 'name' => 'I go step by step'}
11
+ ]
12
+ }
13
+ end
14
+
15
+ let(:feature_steps) { stub_everything }
16
+ let(:feature_name) { 'My feature' }
17
+ subject{
18
+ scenario = Spinach::Runner::ScenarioRunner.new(feature_name, data)
19
+ scenario.stubs(feature_steps: feature_steps)
20
+ scenario
21
+ }
22
+
23
+ describe '#initialize' do
24
+ it 'lists all the steps' do
25
+ subject.steps.count.must_equal 3
26
+ end
27
+
28
+ it 'sets the feature' do
29
+ subject.feature_steps.must_equal feature_steps
30
+ end
31
+ end
32
+
33
+ describe '#feature' do
34
+ it 'finds the feature given a feature name' do
35
+ subject.unstub(:feature_steps)
36
+ @feature = stub_everything
37
+ subject.stubs(feature_name: 'A cool feature')
38
+ Spinach.expects(:find_feature_steps).with('A cool feature').returns(@feature)
39
+ subject.feature_steps
40
+ end
41
+ end
42
+
43
+ describe '#run' do
44
+ it 'calls the appropiate feature steps' do
45
+ feature_steps.expects(:execute_step).with('I herd you like steps')
46
+ feature_steps.expects(:execute_step).with('I test steps')
47
+ feature_steps.expects(:execute_step).with('I go step by step')
48
+ subject.run
49
+ end
50
+
51
+ describe 'when throwing exceptions' do
52
+ it 'rescues a MiniTest::Assertion' do
53
+ feature_steps.expects(:execute_step).raises(MiniTest::Assertion)
54
+ Spinach.hooks.expects("run_before_scenario").with(has_value("A cool scenario"))
55
+ Spinach.hooks.expects("run_after_scenario").with(has_value("A cool scenario"))
56
+ Spinach.hooks.expects('run_on_failed_step').with(anything, anything, anything)
57
+ Spinach.hooks.expects('run_on_skipped_step').with(anything, anything).twice
58
+ subject.run
59
+ end
60
+
61
+ it 'rescues a Spinach::StepNotDefinedException' do
62
+ feature_steps.expects(:execute_step).raises(
63
+ Spinach::StepNotDefinedException.new('bar'))
64
+ Spinach.hooks.expects("run_before_scenario").with(has_value("A cool scenario"))
65
+ Spinach.hooks.expects("run_after_scenario").with(has_value("A cool scenario"))
66
+ Spinach.hooks.expects("run_on_undefined_step").with(
67
+ anything, anything, anything)
68
+ Spinach.hooks.expects("run_on_skipped_step").with(
69
+ anything, anything).twice
70
+ subject.run
71
+ end
72
+
73
+ it 'rescues any other error' do
74
+ feature_steps.expects(:execute_step).raises
75
+ Spinach.hooks.expects("run_after_scenario").with(has_value("A cool scenario"))
76
+ Spinach.hooks.expects("run_before_scenario").with(has_value("A cool scenario"))
77
+ Spinach.hooks.expects("run_on_error_step").with(anything, anything, anything)
78
+ Spinach.hooks.expects("run_on_skipped_step").with(anything, anything).twice
79
+ subject.run
80
+ end
81
+
82
+ it 'returns an failure' do
83
+ feature_steps.expects(:execute_step).raises(MiniTest::Assertion)
84
+ subject.run.wont_equal nil
85
+ end
86
+ end
87
+
88
+ it 'runs a step' do
89
+ feature_steps.expects(:execute_step).with(anything).times(3)
90
+ subject.run.must_equal true
91
+ end
92
+
93
+ describe 'hooks' do
94
+ it 'fires up the scenario hooks' do
95
+ feature_steps.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('bar'))
96
+ Spinach.hooks.expects(:run_before_scenario).with(has_value("A cool scenario"))
97
+ Spinach.hooks.expects(:run_after_scenario).with(has_value("A cool scenario"))
98
+ subject.run
99
+ end
100
+
101
+ it 'fires up the step hooks' do
102
+ feature_steps.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('bar'))
103
+ %w{before_step after_step}.each do |hook|
104
+ Spinach.hooks.expects("run_#{hook}").with(kind_of(Hash)).times(3)
105
+ end
106
+
107
+ subject.run
108
+ end
109
+ end
110
+ end
111
+ end