spinach 0.1.5.4 → 0.2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/README.markdown +18 -12
- data/features/background.feature +13 -0
- data/features/reporting/show_step_source_location.feature +11 -1
- data/features/steps/automatic_feature_generation.rb +7 -7
- data/features/steps/background.rb +30 -0
- data/features/steps/exit_status.rb +12 -13
- data/features/steps/feature_name_guessing.rb +7 -7
- data/features/steps/reporting/display_run_summary.rb +22 -22
- data/features/steps/reporting/error_reporting.rb +7 -7
- data/features/steps/reporting/show_step_source_location.rb +63 -14
- data/features/steps/reporting/undefined_feature_reporting.rb +7 -7
- data/features/steps/rspec_compatibility.rb +14 -14
- data/features/support/error_reporting.rb +5 -5
- data/features/support/filesystem.rb +71 -0
- data/features/support/spinach_runner.rb +5 -6
- data/lib/spinach.rb +11 -6
- data/lib/spinach/background.rb +11 -0
- data/lib/spinach/capybara.rb +7 -1
- data/lib/spinach/cli.rb +36 -13
- data/lib/spinach/config.rb +40 -6
- data/lib/spinach/dsl.rb +14 -11
- data/lib/spinach/exceptions.rb +1 -1
- data/lib/spinach/feature.rb +16 -0
- data/lib/spinach/frameworks.rb +2 -0
- data/lib/spinach/{suites → frameworks}/minitest.rb +0 -0
- data/lib/spinach/{suites → frameworks}/rspec.rb +0 -0
- data/lib/spinach/generators/feature_generator.rb +12 -23
- data/lib/spinach/generators/step_generator.rb +5 -5
- data/lib/spinach/hookable.rb +6 -4
- data/lib/spinach/hooks.rb +12 -4
- data/lib/spinach/parser.rb +6 -8
- data/lib/spinach/parser/visitor.rb +109 -0
- data/lib/spinach/reporter.rb +10 -6
- data/lib/spinach/reporter/stdout.rb +41 -16
- data/lib/spinach/reporter/stdout/error_reporting.rb +2 -2
- data/lib/spinach/runner.rb +9 -6
- data/lib/spinach/runner/feature_runner.rb +40 -34
- data/lib/spinach/runner/scenario_runner.rb +63 -36
- data/lib/spinach/scenario.rb +12 -0
- data/lib/spinach/step.rb +10 -0
- data/lib/spinach/version.rb +1 -1
- data/spinach.gemspec +3 -3
- data/test/spinach/background_test.rb +6 -0
- data/test/spinach/capybara_test.rb +30 -13
- data/test/spinach/cli_test.rb +46 -1
- data/test/spinach/config_test.rb +39 -0
- data/test/spinach/dsl_test.rb +12 -10
- data/test/spinach/feature_steps_test.rb +3 -3
- data/test/spinach/feature_test.rb +6 -0
- data/test/spinach/{suites → frameworks}/minitest_test.rb +2 -2
- data/test/spinach/generators/feature_generator_test.rb +18 -58
- data/test/spinach/generators/step_generator_test.rb +3 -3
- data/test/spinach/generators_test.rb +12 -10
- data/test/spinach/hookable_test.rb +8 -0
- data/test/spinach/hooks_test.rb +6 -7
- data/test/spinach/parser/visitor_test.rb +173 -0
- data/test/spinach/parser_test.rb +14 -27
- data/test/spinach/reporter/stdout/error_reporting_test.rb +9 -9
- data/test/spinach/reporter/stdout_test.rb +15 -19
- data/test/spinach/reporter_test.rb +15 -0
- data/test/spinach/runner/feature_runner_test.rb +79 -69
- data/test/spinach/runner/scenario_runner_test.rb +118 -92
- data/test/spinach/runner_test.rb +10 -6
- data/test/spinach/scenario_test.rb +6 -0
- data/test/spinach/step_test.rb +6 -0
- data/test/spinach_test.rb +7 -7
- metadata +60 -39
- data/lib/spinach/suites.rb +0 -2
data/test/spinach/parser_test.rb
CHANGED
@@ -2,38 +2,25 @@ require_relative '../test_helper'
|
|
2
2
|
|
3
3
|
describe Spinach::Parser do
|
4
4
|
before do
|
5
|
-
@
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
@contents = """
|
6
|
+
Feature: User authentication
|
7
|
+
|
8
|
+
Scenario: User logs in
|
9
|
+
Given I am on the front page
|
10
|
+
When I fill in the login form and press 'login'
|
11
|
+
Then I should be on my dashboard
|
12
|
+
"""
|
13
|
+
@parser = Spinach::Parser.new(@contents)
|
12
14
|
end
|
13
15
|
|
14
16
|
let(:parsed) { @parser.parse }
|
15
17
|
|
16
18
|
describe '#parse' do
|
17
|
-
it 'parses the
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
before do
|
23
|
-
@scenario = parsed['elements'][0]
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'parses the scenario name' do
|
27
|
-
@scenario['name'].must_equal 'User logs in'
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'parses the scenario steps' do
|
31
|
-
@scenario['steps'][0]['name'].must_equal 'I am on the front page'
|
32
|
-
@scenario['steps'][1]['name'].must_equal(
|
33
|
-
'I fill in the login form and press \'login\''
|
34
|
-
)
|
35
|
-
@scenario['steps'][2]['name'].must_equal 'I should be on my dashboard'
|
36
|
-
end
|
19
|
+
it 'parses the file' do
|
20
|
+
Gherkin.expects(:parse).with(@contents.strip).returns ast = stub
|
21
|
+
Spinach::Parser::Visitor.stubs(:new).returns visitor = stub
|
22
|
+
visitor.expects(:visit).with ast
|
23
|
+
@parser.parse
|
37
24
|
end
|
38
25
|
end
|
39
26
|
|
@@ -6,9 +6,9 @@ describe Spinach::Reporter::Stdout do
|
|
6
6
|
let(:exception) { StandardError.new('Something went wrong') }
|
7
7
|
|
8
8
|
let(:error) do
|
9
|
-
[
|
10
|
-
|
11
|
-
|
9
|
+
[stub(name: 'My feature'),
|
10
|
+
stub(name: 'A scenario'),
|
11
|
+
stub(keyword: 'Keyword', name: 'step name'),
|
12
12
|
exception]
|
13
13
|
end
|
14
14
|
|
@@ -110,7 +110,7 @@ describe Spinach::Reporter::Stdout do
|
|
110
110
|
describe '#report_undefined_features' do
|
111
111
|
describe 'when some features are undefined' do
|
112
112
|
it 'outputs the undefined features' do
|
113
|
-
@reporter.undefined_features <<
|
113
|
+
@reporter.undefined_features << stub(name: 'Undefined feature name')
|
114
114
|
@reporter.report_undefined_features
|
115
115
|
|
116
116
|
@error.string.must_include "Undefined features (1)"
|
@@ -242,10 +242,10 @@ describe Spinach::Reporter::Stdout do
|
|
242
242
|
|
243
243
|
describe "when it's a step not defined exception" do
|
244
244
|
it "returns a suggestion" do
|
245
|
-
@exception = Spinach::StepNotDefinedException.new("foo")
|
246
|
-
@error = [
|
247
|
-
|
248
|
-
|
245
|
+
@exception = Spinach::StepNotDefinedException.new(stub(name: "foo"))
|
246
|
+
@error = [stub(name: 'My feature'),
|
247
|
+
stub(name: 'A scenario'),
|
248
|
+
stub(keyword: 'Given', name: 'foo'),
|
249
249
|
@exception]
|
250
250
|
output = @reporter.full_error(@error)
|
251
251
|
output.must_include "Given"
|
@@ -269,7 +269,7 @@ describe Spinach::Reporter::Stdout do
|
|
269
269
|
|
270
270
|
describe 'when given an undefined step exception' do
|
271
271
|
it 'prints the error in yellow' do
|
272
|
-
undefined_exception = Spinach::StepNotDefinedException.new(
|
272
|
+
undefined_exception = Spinach::StepNotDefinedException.new(stub(name: 'some step'))
|
273
273
|
|
274
274
|
String.any_instance.expects(:yellow)
|
275
275
|
|
@@ -6,9 +6,9 @@ describe Spinach::Reporter::Stdout do
|
|
6
6
|
let(:exception) { StandardError.new('Something went wrong') }
|
7
7
|
|
8
8
|
let(:error) do
|
9
|
-
[
|
10
|
-
|
11
|
-
|
9
|
+
[stub(name: 'My feature'),
|
10
|
+
stub(name: 'A scenario'),
|
11
|
+
stub(keyword: 'Keyword', name: 'step name'),
|
12
12
|
exception]
|
13
13
|
end
|
14
14
|
|
@@ -28,7 +28,8 @@ describe Spinach::Reporter::Stdout do
|
|
28
28
|
|
29
29
|
describe '#before_feature_run' do
|
30
30
|
it 'outputs the feature' do
|
31
|
-
|
31
|
+
feature = stub_everything(name: 'A cool feature')
|
32
|
+
@reporter.before_feature_run(feature)
|
32
33
|
|
33
34
|
@out.string.must_include 'Feature'
|
34
35
|
@out.string.must_include 'A cool feature'
|
@@ -37,7 +38,8 @@ describe Spinach::Reporter::Stdout do
|
|
37
38
|
|
38
39
|
describe '#before_scenario_run' do
|
39
40
|
it 'outputs the scenario' do
|
40
|
-
|
41
|
+
scenario = stub_everything(name: 'Arbitrary scenario', steps: [])
|
42
|
+
@reporter.before_scenario_run(scenario)
|
41
43
|
|
42
44
|
@out.string.must_include 'Scenario'
|
43
45
|
@out.string.must_include 'Arbitrary scenario'
|
@@ -68,7 +70,7 @@ describe Spinach::Reporter::Stdout do
|
|
68
70
|
end
|
69
71
|
|
70
72
|
describe '#on_successful_step' do
|
71
|
-
let(:step) {
|
73
|
+
let(:step) { stub(keyword: 'Given', name: 'I am too cool') }
|
72
74
|
let(:step_location){['error_step_location', 1]}
|
73
75
|
it 'adds the step to the output buffer' do
|
74
76
|
@reporter.on_successful_step(step, step_location)
|
@@ -92,7 +94,7 @@ describe Spinach::Reporter::Stdout do
|
|
92
94
|
end
|
93
95
|
|
94
96
|
describe '#on_failed_step' do
|
95
|
-
let(:step) {
|
97
|
+
let(:step) { stub(keyword: 'Then', name: 'I write failing steps') }
|
96
98
|
let(:step_location){['error_step_location', 1]}
|
97
99
|
|
98
100
|
it 'adds the step to the output buffer' do
|
@@ -117,7 +119,7 @@ describe Spinach::Reporter::Stdout do
|
|
117
119
|
end
|
118
120
|
|
119
121
|
describe '#on_error_step' do
|
120
|
-
let(:step) {
|
122
|
+
let(:step) { stub(keyword: 'And', name: 'I even make syntax errors') }
|
121
123
|
let(:step_location){['error_step_location', 1]}
|
122
124
|
|
123
125
|
it 'adds the step to the output buffer' do
|
@@ -142,7 +144,7 @@ describe Spinach::Reporter::Stdout do
|
|
142
144
|
end
|
143
145
|
|
144
146
|
describe '#on_undefined_step' do
|
145
|
-
let(:step) {
|
147
|
+
let(:step) { stub(keyword: 'When', name: 'I forgot to write steps') }
|
146
148
|
|
147
149
|
it 'adds the step to the output buffer' do
|
148
150
|
@reporter.on_undefined_step(step, anything)
|
@@ -167,9 +169,7 @@ describe Spinach::Reporter::Stdout do
|
|
167
169
|
|
168
170
|
describe "#on_feature_not_found" do
|
169
171
|
before do
|
170
|
-
@feature =
|
171
|
-
'name' => 'This feature does not exist'
|
172
|
-
}
|
172
|
+
@feature = stub(name: 'This feature does not exist', scenarios: [], background_steps: [])
|
173
173
|
Spinach.config.stubs(:step_definitions_path).returns('my/path')
|
174
174
|
@reporter.on_feature_not_found(@feature)
|
175
175
|
end
|
@@ -195,7 +195,7 @@ describe Spinach::Reporter::Stdout do
|
|
195
195
|
|
196
196
|
describe '#on_skipped_step' do
|
197
197
|
it 'adds the step to the output buffer' do
|
198
|
-
@reporter.on_skipped_step(
|
198
|
+
@reporter.on_skipped_step(stub(keyword: 'Then', name: 'some steps are not even called'))
|
199
199
|
|
200
200
|
@out.string.must_include '~'
|
201
201
|
@out.string.must_include 'Then'
|
@@ -205,7 +205,7 @@ describe Spinach::Reporter::Stdout do
|
|
205
205
|
|
206
206
|
describe '#output_step' do
|
207
207
|
it 'adds a step to the output buffer with nice colors' do
|
208
|
-
step =
|
208
|
+
step = stub(keyword: 'Keyword', name: 'step name')
|
209
209
|
@reporter.output_step('symbol', step, :blue)
|
210
210
|
|
211
211
|
@out.string.must_include 'symbol'
|
@@ -236,11 +236,7 @@ describe Spinach::Reporter::Stdout do
|
|
236
236
|
|
237
237
|
describe '#full_step' do
|
238
238
|
it 'returns the step with keyword and name' do
|
239
|
-
@reporter.full_step(
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'strips the arguments' do
|
243
|
-
@reporter.full_step({'keyword' => ' Keyword ', 'name' => ' step name '}).must_equal 'Keyword step name'
|
239
|
+
@reporter.full_step(stub(keyword: 'Keyword', name: 'step name')).must_equal 'Keyword step name'
|
244
240
|
end
|
245
241
|
end
|
246
242
|
end
|
@@ -81,6 +81,21 @@ module Spinach
|
|
81
81
|
Spinach.hooks.run_before_scenario(anything)
|
82
82
|
end
|
83
83
|
|
84
|
+
it "binds a callback around every scenario" do
|
85
|
+
@reporter.expects(:around_scenario_run)
|
86
|
+
Spinach.hooks.run_around_scenario(anything) do
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "yields to around scenario callback" do
|
92
|
+
called = false
|
93
|
+
@reporter.around_scenario_run do
|
94
|
+
called = true
|
95
|
+
end
|
96
|
+
called.must_equal true
|
97
|
+
end
|
98
|
+
|
84
99
|
it "binds a callback after every scenario" do
|
85
100
|
@reporter.expects(:after_scenario_run)
|
86
101
|
Spinach.hooks.run_after_scenario
|
@@ -1,100 +1,110 @@
|
|
1
1
|
require_relative '../../test_helper'
|
2
2
|
|
3
3
|
describe Spinach::Runner::FeatureRunner do
|
4
|
-
let(:
|
5
|
-
subject{ Spinach::Runner::FeatureRunner.new(
|
4
|
+
let(:feature) { stub('feature', name: 'Feature') }
|
5
|
+
subject{ Spinach::Runner::FeatureRunner.new(feature) }
|
6
6
|
|
7
7
|
describe '#initialize' do
|
8
8
|
it 'initializes the given filename' do
|
9
|
-
subject.
|
9
|
+
subject.feature.must_equal feature
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'initalizes the given scenario line' do
|
13
|
-
@
|
14
|
-
@
|
15
|
-
|
16
|
-
@feature.instance_variable_get(:@scenario_line).must_equal '12'
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe '#data' do
|
21
|
-
it 'returns the parsed data' do
|
22
|
-
parsed_data = {name: 'A cool feature'}
|
23
|
-
parser = stub(parse: parsed_data)
|
24
|
-
Spinach::Parser.expects(:open_file).returns(parser)
|
25
|
-
subject.data.must_equal parsed_data
|
13
|
+
@runner = Spinach::Runner::FeatureRunner.new(feature, '34')
|
14
|
+
@runner.instance_variable_get(:@line).must_equal 34
|
26
15
|
end
|
27
16
|
end
|
28
17
|
|
29
18
|
describe '#scenarios' do
|
30
|
-
it '
|
31
|
-
subject.stubs(
|
19
|
+
it 'delegates to the feature' do
|
20
|
+
subject.feature.stubs(scenarios: [1,2,3])
|
32
21
|
subject.scenarios.must_equal [1,2,3]
|
33
22
|
end
|
34
23
|
end
|
35
24
|
|
36
25
|
describe '#run' do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
{'keyword'=>'Scenario', 'name'=>'Basic guess III', 'line'=>18, 'description'=>'', 'type'=>'scenario'}]
|
43
|
-
})
|
44
|
-
subject.stubs(feature: stub_everything)
|
45
|
-
end
|
26
|
+
it 'runs the hooks in order' do
|
27
|
+
hooks = sequence('hooks')
|
28
|
+
Spinach.hooks.expects(:run_before_feature).with(feature).in_sequence(hooks)
|
29
|
+
Spinach.expects(:find_step_definitions).returns(false).in_sequence(hooks)
|
30
|
+
Spinach.hooks.expects(:run_after_feature).with(feature).in_sequence(hooks)
|
46
31
|
|
47
|
-
it 'calls the steps as expected' do
|
48
|
-
Spinach.expects(:find_feature_steps).returns(true)
|
49
|
-
seq = sequence('feature')
|
50
|
-
3.times do
|
51
|
-
Spinach::Runner::ScenarioRunner.
|
52
|
-
expects(:new).
|
53
|
-
returns(stub_everything).
|
54
|
-
in_sequence(seq)
|
55
|
-
end
|
56
32
|
subject.run
|
57
33
|
end
|
58
34
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
35
|
+
describe 'when the steps exist' do
|
36
|
+
before do
|
37
|
+
@feature = stub('feature', name: 'Feature')
|
38
|
+
Spinach.stubs(:find_step_definitions).returns(true)
|
39
|
+
@scenarios = [
|
40
|
+
scenario = stub,
|
41
|
+
another_scenario = stub
|
42
|
+
]
|
43
|
+
@feature.stubs(:scenarios).returns @scenarios
|
44
|
+
@runner = Spinach::Runner::FeatureRunner.new(@feature)
|
45
|
+
end
|
65
46
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
47
|
+
describe 'and the scenarios pass' do
|
48
|
+
it 'runs the scenarios and returns true' do
|
49
|
+
@scenarios.each do |scenario|
|
50
|
+
runner = stub(run: true)
|
51
|
+
Spinach::Runner::ScenarioRunner.expects(:new).with(scenario).returns runner
|
52
|
+
end
|
53
|
+
|
54
|
+
@runner.run.must_equal true
|
55
|
+
end
|
56
|
+
end
|
72
57
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
'elements' => [{'keyword'=>'Scenario', 'name'=>'Basic guess', 'line'=>6, 'description'=>'', 'type'=>'scenario'},
|
80
|
-
{'keyword'=>'Scenario', 'name'=>'Basic guess II', 'line'=>12, 'description'=>'', 'type'=>'scenario'},
|
81
|
-
{'keyword'=>'Scenario', 'name'=>'Basic guess III', 'line'=>18, 'description'=>'', 'type'=>'scenario'}]
|
82
|
-
})
|
58
|
+
describe 'and the scenarios fail' do
|
59
|
+
it 'runs the scenarios and returns false' do
|
60
|
+
@scenarios.each do |scenario|
|
61
|
+
runner = stub(run: false)
|
62
|
+
Spinach::Runner::ScenarioRunner.expects(:new).with(scenario).returns runner
|
63
|
+
end
|
83
64
|
|
84
|
-
|
85
|
-
|
65
|
+
@runner.run.must_equal false
|
66
|
+
end
|
67
|
+
end
|
86
68
|
end
|
87
69
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
70
|
+
describe "when the steps don't exist" do
|
71
|
+
it 'runs the corresponding hooks and returns false' do
|
72
|
+
Spinach.stubs(:find_step_definitions).returns(false)
|
73
|
+
Spinach.hooks.expects(:run_on_undefined_feature).with(feature)
|
74
|
+
subject.run.must_equal false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "when a line is given" do
|
79
|
+
before do
|
80
|
+
@feature = stub('feature', name: 'Feature')
|
81
|
+
Spinach.stubs(:find_step_definitions).returns(true)
|
82
|
+
@scenarios = [
|
83
|
+
scenario = stub(line: 4),
|
84
|
+
another_scenario = stub(line: 12)
|
85
|
+
]
|
86
|
+
@feature.stubs(:scenarios).returns @scenarios
|
87
|
+
end
|
88
|
+
it "runs exactly matching scenario" do
|
89
|
+
Spinach::Runner::ScenarioRunner.expects(:new).with(@scenarios[1]).returns stub(run: true)
|
90
|
+
@runner = Spinach::Runner::FeatureRunner.new(@feature, "12")
|
91
|
+
@runner.run
|
92
|
+
end
|
93
|
+
it "runs no scenario and returns false" do
|
94
|
+
Spinach::Runner::ScenarioRunner.expects(:new).never
|
95
|
+
@runner = Spinach::Runner::FeatureRunner.new(@feature, "3")
|
96
|
+
@runner.run
|
97
|
+
end
|
98
|
+
it "runs matching scenario" do
|
99
|
+
Spinach::Runner::ScenarioRunner.expects(:new).with(@scenarios[0]).returns stub(run: true)
|
100
|
+
@runner = Spinach::Runner::FeatureRunner.new(@feature, "8")
|
101
|
+
@runner.run
|
102
|
+
end
|
103
|
+
it "runs last scenario" do
|
104
|
+
Spinach::Runner::ScenarioRunner.expects(:new).with(@scenarios[1]).returns stub(run: true)
|
105
|
+
@runner = Spinach::Runner::FeatureRunner.new(@feature, "15")
|
106
|
+
@runner.run
|
95
107
|
end
|
96
|
-
subject.run
|
97
|
-
not_found_called.must_equal data
|
98
108
|
end
|
99
109
|
end
|
100
110
|
end
|
@@ -1,111 +1,137 @@
|
|
1
1
|
require_relative '../../test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
3
|
+
module Spinach
|
4
|
+
class Runner
|
5
|
+
describe ScenarioRunner do
|
6
|
+
let(:feature) { stub(name: 'Feature', background_steps: []) }
|
7
|
+
let(:steps) { [stub(name: 'go shopping'), stub(name: 'do something')] }
|
8
|
+
let(:scenario) do
|
9
|
+
stub(
|
10
|
+
feature: feature,
|
11
|
+
steps: steps
|
12
|
+
)
|
13
|
+
end
|
32
14
|
|
33
|
-
|
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
|
15
|
+
subject { ScenarioRunner.new(scenario) }
|
42
16
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
feature_steps.expects(:execute_step).with('I go step by step')
|
48
|
-
subject.run
|
49
|
-
end
|
17
|
+
describe 'delegations' do
|
18
|
+
it 'delegates #feature to the scenario' do
|
19
|
+
subject.feature.must_equal feature
|
20
|
+
end
|
50
21
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
feature_steps.expects(:execute_step).raises(MiniTest::Assertion)
|
55
|
-
Spinach.hooks.expects("run_before_scenario").with(has_value("A cool scenario"))
|
56
|
-
Spinach.hooks.expects("run_after_scenario").with(has_value("A cool scenario"))
|
57
|
-
Spinach.hooks.expects('run_on_failed_step').with(anything, anything, anything)
|
58
|
-
Spinach.hooks.expects('run_on_skipped_step').with(anything, anything).twice
|
59
|
-
subject.run
|
22
|
+
it 'delegates #steps to the scenario' do
|
23
|
+
subject.steps.must_equal steps
|
24
|
+
end
|
60
25
|
end
|
61
26
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
anything, anything, anything)
|
69
|
-
Spinach.hooks.expects("run_on_skipped_step").with(
|
70
|
-
anything, anything).twice
|
71
|
-
subject.run
|
27
|
+
describe '#step_definitions' do
|
28
|
+
it 'looks up the step definitions' do
|
29
|
+
klass = Class.new
|
30
|
+
Spinach.expects(:find_step_definitions).with('Feature').returns klass
|
31
|
+
subject.step_definitions
|
32
|
+
end
|
72
33
|
end
|
73
34
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
Spinach.hooks.expects("run_on_skipped_step").with(anything, anything).twice
|
80
|
-
subject.run
|
81
|
-
end
|
35
|
+
describe '#run' do
|
36
|
+
describe 'hooks' do
|
37
|
+
it 'runs hooks in order' do
|
38
|
+
hooks = sequence('hooks')
|
39
|
+
subject.stubs(:step_definitions).returns step_definitions = stub
|
82
40
|
|
83
|
-
|
84
|
-
|
85
|
-
subject.run.wont_equal nil
|
86
|
-
end
|
87
|
-
end
|
41
|
+
Spinach.hooks.expects(:run_before_scenario).with(scenario).in_sequence(hooks)
|
42
|
+
Spinach.hooks.expects(:run_around_scenario).with(scenario).in_sequence(hooks).yields
|
88
43
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
44
|
+
Spinach.hooks.expects(:run_before_step).with(steps.first).in_sequence(hooks)
|
45
|
+
subject.expects(:run_step).with(steps.first)
|
46
|
+
Spinach.hooks.expects(:run_after_step).with(steps.first).in_sequence(hooks)
|
47
|
+
|
48
|
+
Spinach.hooks.expects(:run_before_step).with(steps.last).in_sequence(hooks)
|
49
|
+
subject.expects(:run_step).with(steps.last)
|
50
|
+
Spinach.hooks.expects(:run_after_step).with(steps.last).in_sequence(hooks)
|
51
|
+
|
52
|
+
Spinach.hooks.expects(:run_after_scenario).with(scenario).in_sequence(hooks)
|
93
53
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
54
|
+
subject.run
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'raises if around hook does not yield' do
|
58
|
+
subject.stubs(:step_definitions).returns stub
|
59
|
+
|
60
|
+
Spinach.hooks.stubs(:run_around_scenario).with(scenario)
|
61
|
+
|
62
|
+
proc do
|
63
|
+
subject.run
|
64
|
+
end.must_raise RuntimeError
|
65
|
+
end
|
66
|
+
end
|
100
67
|
end
|
101
68
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
69
|
+
describe '#run_step' do
|
70
|
+
before do
|
71
|
+
@step = stub(name: 'Go shopping')
|
72
|
+
@step_definitions = stub
|
73
|
+
@step_definitions.stubs(:step_location_for).with('Go shopping').returns @location = stub
|
74
|
+
subject.stubs(:step_definitions).returns @step_definitions
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'when the step is successful' do
|
78
|
+
it 'runs the successful hooks' do
|
79
|
+
@step_definitions.stubs(:execute).with(@step).returns true
|
80
|
+
Spinach.hooks.expects(:run_on_successful_step).with(@step, @location)
|
81
|
+
|
82
|
+
subject.run_step(@step)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'when the step fails' do
|
87
|
+
before do
|
88
|
+
@failure_exception = Class.new(StandardError)
|
89
|
+
Spinach.stubs(:config).returns({ failure_exceptions: [@failure_exception] })
|
90
|
+
@step_definitions.stubs(:execute).with(@step).raises @failure_exception
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'sets the exception' do
|
94
|
+
subject.run_step(@step)
|
95
|
+
subject.instance_variable_get(:@exception).must_be_kind_of(@failure_exception)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'runs the failed hooks' do
|
99
|
+
Spinach.hooks.expects(:run_on_failed_step).with(@step, kind_of(@failure_exception), @location)
|
100
|
+
subject.run_step(@step)
|
101
|
+
end
|
106
102
|
end
|
107
103
|
|
108
|
-
|
104
|
+
describe 'when the step is undefined' do
|
105
|
+
before do
|
106
|
+
@step_definitions.stubs(:execute).with(@step).raises Spinach::StepNotDefinedException, @step
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'sets the exception' do
|
110
|
+
subject.run_step(@step)
|
111
|
+
subject.instance_variable_get(:@exception).must_be_kind_of(Spinach::StepNotDefinedException)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'runs the undefined hooks' do
|
115
|
+
Spinach.hooks.expects(:run_on_undefined_step).with(@step, kind_of(Spinach::StepNotDefinedException))
|
116
|
+
subject.run_step(@step)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'when the step raises an error' do
|
121
|
+
before do
|
122
|
+
@step_definitions.stubs(:execute).with(@step).raises StandardError
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'sets the exception' do
|
126
|
+
subject.run_step(@step)
|
127
|
+
subject.instance_variable_get(:@exception).must_be_kind_of(StandardError)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'runs the error hooks' do
|
131
|
+
Spinach.hooks.expects(:run_on_error_step).with(@step, kind_of(StandardError), @location)
|
132
|
+
subject.run_step(@step)
|
133
|
+
end
|
134
|
+
end
|
109
135
|
end
|
110
136
|
end
|
111
137
|
end
|