spinach 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.yardopts +6 -0
- data/Gemfile +1 -0
- data/Guardfile +7 -0
- data/Rakefile +1 -0
- data/Readme.md +147 -10
- data/features/{generate_features.feature → automatic_feature_generation.feature} +0 -0
- data/features/steps/automatic_feature_generation.rb +5 -2
- data/features/steps/exit_status.rb +8 -3
- data/features/steps/feature_name_guessing.rb +4 -1
- data/features/steps/reporting/display_run_summary.rb +7 -4
- data/features/steps/reporting/error_reporting.rb +7 -2
- data/features/steps/reporting/show_step_source_location.rb +9 -5
- data/features/steps/reporting/undefined_feature_reporting.rb +4 -1
- data/features/steps/rspec_compatibility.rb +6 -2
- data/features/support/spinach_runner.rb +2 -9
- data/lib/spinach/capybara.rb +3 -4
- data/lib/spinach/cli.rb +0 -1
- data/lib/spinach/config.rb +0 -8
- data/lib/spinach/dsl.rb +4 -13
- data/lib/spinach/exceptions.rb +1 -1
- data/lib/spinach/feature_steps.rb +1 -9
- data/lib/spinach/generators/feature_generator.rb +3 -2
- data/lib/spinach/generators.rb +1 -1
- data/lib/spinach/hookable.rb +81 -0
- data/lib/spinach/hooks.rb +132 -0
- data/lib/spinach/reporter/stdout/error_reporting.rb +163 -0
- data/lib/spinach/reporter/stdout.rb +3 -151
- data/lib/spinach/reporter.rb +39 -25
- data/lib/spinach/runner/{feature.rb → feature_runner.rb} +5 -15
- data/lib/spinach/runner/scenario_runner.rb +65 -0
- data/lib/spinach/runner.rb +5 -11
- data/lib/spinach/version.rb +1 -1
- data/lib/spinach.rb +20 -8
- data/spinach.gemspec +2 -3
- data/test/spinach/capybara_test.rb +4 -3
- data/test/spinach/cli_test.rb +0 -1
- data/test/spinach/feature_steps_test.rb +6 -23
- data/test/spinach/generators/feature_generator_test.rb +2 -2
- data/test/spinach/generators_test.rb +2 -2
- data/test/spinach/hookable_test.rb +59 -0
- data/test/spinach/hooks_test.rb +28 -0
- data/test/spinach/reporter/stdout/error_reporting_test.rb +265 -0
- data/test/spinach/reporter/stdout_test.rb +1 -238
- data/test/spinach/reporter_test.rb +58 -103
- data/test/spinach/runner/{feature_test.rb → feature_runner_test.rb} +21 -23
- data/test/spinach/runner/scenario_runner_test.rb +111 -0
- data/test/spinach/runner_test.rb +1 -1
- data/test/spinach_test.rb +19 -18
- data/test/test_helper.rb +1 -1
- metadata +60 -61
- data/lib/spinach/runner/scenario.rb +0 -77
- data/test/spinach/runner/scenario_test.rb +0 -120
@@ -0,0 +1,132 @@
|
|
1
|
+
require_relative 'hookable'
|
2
|
+
|
3
|
+
module Spinach
|
4
|
+
# Spinach's hooks is a subscription mechanism to allow developers to define
|
5
|
+
# certain callbacks given several Spinach signals, like running a feature,
|
6
|
+
# executing a particular step and such.
|
7
|
+
class Hooks
|
8
|
+
include Hookable
|
9
|
+
|
10
|
+
# Runs before the entire spinach run
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# Spinach.before_run do
|
14
|
+
# # Whatever
|
15
|
+
# end
|
16
|
+
hook :before_run
|
17
|
+
|
18
|
+
# Runs after the entire spinach run
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# Spinach.after_run do |status|
|
22
|
+
# # status is true when the run is successful, false otherwise
|
23
|
+
# end
|
24
|
+
hook :after_run
|
25
|
+
|
26
|
+
# Runs before every feature,
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# Spinach.before_feature do |feature_data|
|
30
|
+
# # feature_data is a hash of the parsed feature data
|
31
|
+
# end
|
32
|
+
hook :before_feature
|
33
|
+
|
34
|
+
# Runs after every feature
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# Spinach.after_feature do |feature_data|
|
38
|
+
# # feature_data is a hash of the parsed feature data
|
39
|
+
# end
|
40
|
+
hook :after_feature
|
41
|
+
|
42
|
+
# Runs when an undefined feature is found
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# Spinach.on_undefined_feature do |feature_data, exception|
|
46
|
+
# # feature_data is a hash of the parsed feature data
|
47
|
+
# # exception contains the thrown exception
|
48
|
+
# end
|
49
|
+
hook :on_undefined_feature
|
50
|
+
|
51
|
+
# Runs before every scenario
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# Spinach.before_scenario do |scenario_data|
|
55
|
+
# # feature_data is a hash of the parsed scenario data
|
56
|
+
# end
|
57
|
+
hook :before_scenario
|
58
|
+
|
59
|
+
# Runs after every scenario
|
60
|
+
#
|
61
|
+
# @example
|
62
|
+
# Spinach.after_scenario do |scenario_data|
|
63
|
+
# # feature_data is a hash of the parsed scenario data
|
64
|
+
# end
|
65
|
+
hook :after_scenario
|
66
|
+
|
67
|
+
# Runs before every step execution
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# Spinach.before_step do |step_data|
|
71
|
+
# # step_data contains a hash with this step's data
|
72
|
+
# end
|
73
|
+
hook :before_step
|
74
|
+
|
75
|
+
# Runs after every step execution
|
76
|
+
#
|
77
|
+
# @example
|
78
|
+
# Spinach.before_step do |step_data|
|
79
|
+
# # step_data contains a hash with this step's data
|
80
|
+
# end
|
81
|
+
hook :after_step
|
82
|
+
|
83
|
+
# Runs after every successful step execution
|
84
|
+
#
|
85
|
+
# @example
|
86
|
+
# Spinach.on_successful_step do |step_data, location|
|
87
|
+
# # step_data contains a hash with this step's data
|
88
|
+
# # step_location contains a string indication this step definition's
|
89
|
+
# # location
|
90
|
+
# end
|
91
|
+
hook :on_successful_step
|
92
|
+
|
93
|
+
# Runs after every failed step execution
|
94
|
+
#
|
95
|
+
# @example
|
96
|
+
# Spinach.on_failed_step do |step_data, location|
|
97
|
+
# # step_data contains a hash with this step's data
|
98
|
+
# # step_location contains a string indication this step definition's
|
99
|
+
# # location
|
100
|
+
# end
|
101
|
+
hook :on_failed_step
|
102
|
+
|
103
|
+
# Runs after every step execution that raises an exception
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# Spinach.on_error_step do |step_data, location|
|
107
|
+
# # step_data contains a hash with this step's data
|
108
|
+
# # step_location contains a string indication this step definition's
|
109
|
+
# # location
|
110
|
+
# end
|
111
|
+
hook :on_error_step
|
112
|
+
|
113
|
+
# Runs every time a step which is not defined is called
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# Spinach.on_undefined_step do |step_data, location|
|
117
|
+
# # step_data contains a hash with this step's data
|
118
|
+
# # step_location contains a string indication this step definition's
|
119
|
+
# # location
|
120
|
+
# end
|
121
|
+
hook :on_undefined_step
|
122
|
+
|
123
|
+
# Runs every time a step is skipped because there has been an unsuccessful
|
124
|
+
# one just before.
|
125
|
+
#
|
126
|
+
# @example
|
127
|
+
# Spinach.on_undefined_step do |step_data|
|
128
|
+
# # step_data contains a hash with this step's data
|
129
|
+
# end
|
130
|
+
hook :on_skipped_step
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Spinach
|
2
|
+
class Reporter
|
3
|
+
class Stdout < Reporter
|
4
|
+
# This module handles Stdout's reporter error reporting capabilities.
|
5
|
+
module ErrorReporting
|
6
|
+
|
7
|
+
# Prints the errors for this run.
|
8
|
+
#
|
9
|
+
def error_summary
|
10
|
+
error.puts "\nError summary:\n"
|
11
|
+
report_error_steps
|
12
|
+
report_failed_steps
|
13
|
+
report_undefined_features
|
14
|
+
report_undefined_steps
|
15
|
+
end
|
16
|
+
|
17
|
+
# Prints the steps that raised an error.
|
18
|
+
#
|
19
|
+
def report_error_steps
|
20
|
+
report_errors('Errors', error_steps, :light_red) if error_steps.any?
|
21
|
+
end
|
22
|
+
|
23
|
+
# Prints failing steps.
|
24
|
+
#
|
25
|
+
def report_failed_steps
|
26
|
+
report_errors('Failures', failed_steps, :light_red) if failed_steps.any?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Prints undefined steps.
|
30
|
+
#
|
31
|
+
def report_undefined_steps
|
32
|
+
report_errors('Undefined steps', undefined_steps, :yellow) if undefined_steps.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
def report_undefined_features
|
36
|
+
if undefined_features.any?
|
37
|
+
error.puts " Undefined features (#{undefined_features.length})".light_yellow
|
38
|
+
undefined_features.each do |feature|
|
39
|
+
error.puts " #{feature['name']}".yellow
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Prints the error for a given set of steps
|
45
|
+
#
|
46
|
+
# @param [String] banner
|
47
|
+
# the text to prepend as the title
|
48
|
+
#
|
49
|
+
# @param [Array] steps
|
50
|
+
# the steps to output
|
51
|
+
#
|
52
|
+
# @param [Symbol] color
|
53
|
+
# The color code to use with Colorize to colorize the output.
|
54
|
+
#
|
55
|
+
def report_errors(banner, steps, color)
|
56
|
+
error.puts " #{banner} (#{steps.length})".colorize(color)
|
57
|
+
steps.each do |error|
|
58
|
+
report_error error
|
59
|
+
end
|
60
|
+
error.puts ""
|
61
|
+
end
|
62
|
+
|
63
|
+
# Prints an error in a nice format
|
64
|
+
#
|
65
|
+
# @param [Array] error
|
66
|
+
# An array containing the feature, scenario, step and exception
|
67
|
+
#
|
68
|
+
# @param [Symbol] format
|
69
|
+
# The format to output the error. Currently supproted formats are
|
70
|
+
# :summarized (default) and :full
|
71
|
+
#
|
72
|
+
# @return [String]
|
73
|
+
# The error report
|
74
|
+
#
|
75
|
+
def report_error(error, format=:summarized)
|
76
|
+
case format
|
77
|
+
when :summarized
|
78
|
+
self.error.puts summarized_error(error)
|
79
|
+
when :full
|
80
|
+
self.error.puts full_error(error)
|
81
|
+
else
|
82
|
+
raise "Format not defined"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns summarized error report
|
87
|
+
#
|
88
|
+
# @param [Array] error
|
89
|
+
# An array containing the feature, scenario, step and exception
|
90
|
+
#
|
91
|
+
# @return [String]
|
92
|
+
# The summarized error report
|
93
|
+
#
|
94
|
+
def summarized_error(error)
|
95
|
+
feature, scenario, step, exception = error
|
96
|
+
summary = " #{feature['name']} :: #{scenario['name']} :: #{full_step step}"
|
97
|
+
if exception.kind_of?(Spinach::StepNotDefinedException)
|
98
|
+
summary.yellow
|
99
|
+
else
|
100
|
+
summary.red
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns a complete error report
|
105
|
+
#
|
106
|
+
# @param [Array] error
|
107
|
+
# An array containing the feature, scenario, step and exception
|
108
|
+
#
|
109
|
+
# @return [String]
|
110
|
+
# The coplete error report
|
111
|
+
#
|
112
|
+
def full_error(error)
|
113
|
+
feature, scenario, step, exception = error
|
114
|
+
output = "\n"
|
115
|
+
output += report_exception(exception)
|
116
|
+
output +="\n"
|
117
|
+
|
118
|
+
if exception.kind_of?(Spinach::StepNotDefinedException)
|
119
|
+
output << "\n"
|
120
|
+
output << " You can define it with: \n\n".yellow
|
121
|
+
suggestion = Generators::StepGenerator.new(step).generate
|
122
|
+
suggestion.split("\n").each do |line|
|
123
|
+
output << " #{line}\n".yellow
|
124
|
+
end
|
125
|
+
output << "\n"
|
126
|
+
else
|
127
|
+
if options[:backtrace]
|
128
|
+
output += "\n"
|
129
|
+
exception.backtrace.map do |line|
|
130
|
+
output << " #{line}\n"
|
131
|
+
end
|
132
|
+
else
|
133
|
+
output << " #{exception.backtrace[0]}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
output
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Prints a information when an exception is raised.
|
141
|
+
#
|
142
|
+
# @param [Exception] exception
|
143
|
+
# The exception to report
|
144
|
+
#
|
145
|
+
# @return [String]
|
146
|
+
# The exception report
|
147
|
+
#
|
148
|
+
def report_exception(exception)
|
149
|
+
output = exception.message.split("\n").map{ |line|
|
150
|
+
" #{line}"
|
151
|
+
}.join("\n")
|
152
|
+
|
153
|
+
if exception.kind_of?(Spinach::StepNotDefinedException)
|
154
|
+
output.yellow
|
155
|
+
else
|
156
|
+
output.red
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require_relative 'stdout/error_reporting'
|
2
3
|
|
3
4
|
module Spinach
|
4
5
|
class Reporter
|
@@ -6,6 +7,8 @@ module Spinach
|
|
6
7
|
#
|
7
8
|
class Stdout < Reporter
|
8
9
|
|
10
|
+
include ErrorReporting
|
11
|
+
|
9
12
|
# The output buffers to store the reports.
|
10
13
|
attr_reader :out, :error
|
11
14
|
|
@@ -191,138 +194,6 @@ module Spinach
|
|
191
194
|
out.puts "Steps Summary: #{successful_summary}, #{undefined_summary}, #{failed_summary}, #{error_summary}\n\n"
|
192
195
|
end
|
193
196
|
|
194
|
-
# Prints the errors for this run.
|
195
|
-
#
|
196
|
-
def error_summary
|
197
|
-
error.puts "\nError summary:\n"
|
198
|
-
report_error_steps
|
199
|
-
report_failed_steps
|
200
|
-
report_undefined_features
|
201
|
-
report_undefined_steps
|
202
|
-
end
|
203
|
-
|
204
|
-
# Prints the steps that raised an error.
|
205
|
-
#
|
206
|
-
def report_error_steps
|
207
|
-
report_errors('Errors', error_steps, :light_red) if error_steps.any?
|
208
|
-
end
|
209
|
-
|
210
|
-
# Prints failing steps.
|
211
|
-
#
|
212
|
-
def report_failed_steps
|
213
|
-
report_errors('Failures', failed_steps, :light_red) if failed_steps.any?
|
214
|
-
end
|
215
|
-
|
216
|
-
# Prints undefined steps.
|
217
|
-
#
|
218
|
-
def report_undefined_steps
|
219
|
-
report_errors('Undefined steps', undefined_steps, :yellow) if undefined_steps.any?
|
220
|
-
end
|
221
|
-
|
222
|
-
def report_undefined_features
|
223
|
-
if undefined_features.any?
|
224
|
-
error.puts " Undefined features (#{undefined_features.length})".light_yellow
|
225
|
-
undefined_features.each do |feature|
|
226
|
-
error.puts " #{feature['name']}".yellow
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
# Prints the error for a given set of steps
|
232
|
-
#
|
233
|
-
# @param [String] banner
|
234
|
-
# the text to prepend as the title
|
235
|
-
#
|
236
|
-
# @param [Array] steps
|
237
|
-
# the steps to output
|
238
|
-
#
|
239
|
-
# @param [Symbol] color
|
240
|
-
# The color code to use with Colorize to colorize the output.
|
241
|
-
#
|
242
|
-
def report_errors(banner, steps, color)
|
243
|
-
error.puts " #{banner} (#{steps.length})".colorize(color)
|
244
|
-
steps.each do |error|
|
245
|
-
report_error error
|
246
|
-
end
|
247
|
-
error.puts ""
|
248
|
-
end
|
249
|
-
|
250
|
-
# Prints an error in a nice format
|
251
|
-
#
|
252
|
-
# @param [Array] error
|
253
|
-
# An array containing the feature, scenario, step and exception
|
254
|
-
#
|
255
|
-
# @param [Symbol] format
|
256
|
-
# The format to output the error. Currently supproted formats are
|
257
|
-
# :summarized (default) and :full
|
258
|
-
#
|
259
|
-
# @returns [String]
|
260
|
-
# The error report
|
261
|
-
#
|
262
|
-
def report_error(error, format=:summarized)
|
263
|
-
case format
|
264
|
-
when :summarized
|
265
|
-
self.error.puts summarized_error(error)
|
266
|
-
when :full
|
267
|
-
self.error.puts full_error(error)
|
268
|
-
else
|
269
|
-
raise "Format not defined"
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
# Returns summarized error report
|
274
|
-
#
|
275
|
-
# @param [Array] error
|
276
|
-
# An array containing the feature, scenario, step and exception
|
277
|
-
#
|
278
|
-
# @returns [String]
|
279
|
-
# The summarized error report
|
280
|
-
#
|
281
|
-
def summarized_error(error)
|
282
|
-
feature, scenario, step, exception = error
|
283
|
-
summary = " #{feature['name']} :: #{scenario['name']} :: #{full_step step}"
|
284
|
-
if exception.kind_of?(Spinach::StepNotDefinedException)
|
285
|
-
summary.yellow
|
286
|
-
else
|
287
|
-
summary.red
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
# Returns a complete error report
|
292
|
-
#
|
293
|
-
# @param [Array] error
|
294
|
-
# An array containing the feature, scenario, step and exception
|
295
|
-
#
|
296
|
-
# @returns [String]
|
297
|
-
# The coplete error report
|
298
|
-
#
|
299
|
-
def full_error(error)
|
300
|
-
feature, scenario, step, exception = error
|
301
|
-
output = "\n"
|
302
|
-
output += report_exception(exception)
|
303
|
-
output +="\n"
|
304
|
-
|
305
|
-
if exception.kind_of?(Spinach::StepNotDefinedException)
|
306
|
-
output << "\n"
|
307
|
-
output << " You can define it with: \n\n".yellow
|
308
|
-
suggestion = Generators::StepGenerator.new(step).generate
|
309
|
-
suggestion.split("\n").each do |line|
|
310
|
-
output << " #{line}\n".yellow
|
311
|
-
end
|
312
|
-
output << "\n"
|
313
|
-
else
|
314
|
-
if options[:backtrace]
|
315
|
-
output += "\n"
|
316
|
-
exception.backtrace.map do |line|
|
317
|
-
output << " #{line}\n"
|
318
|
-
end
|
319
|
-
else
|
320
|
-
output << " #{exception.backtrace[0]}"
|
321
|
-
end
|
322
|
-
end
|
323
|
-
output
|
324
|
-
end
|
325
|
-
|
326
197
|
# Constructs the full step definition
|
327
198
|
#
|
328
199
|
# @param [Hash] step
|
@@ -332,25 +203,6 @@ module Spinach
|
|
332
203
|
"#{step['keyword'].strip} #{step['name'].strip}"
|
333
204
|
end
|
334
205
|
|
335
|
-
# Prints a information when an exception is raised.
|
336
|
-
#
|
337
|
-
# @param [Exception] exception
|
338
|
-
# The exception to report
|
339
|
-
#
|
340
|
-
# @returns [String]
|
341
|
-
# The exception report
|
342
|
-
#
|
343
|
-
def report_exception(exception)
|
344
|
-
output = exception.message.split("\n").map{ |line|
|
345
|
-
" #{line}"
|
346
|
-
}.join("\n")
|
347
|
-
|
348
|
-
if exception.kind_of?(Spinach::StepNotDefinedException)
|
349
|
-
output.yellow
|
350
|
-
else
|
351
|
-
output.red
|
352
|
-
end
|
353
|
-
end
|
354
206
|
end
|
355
207
|
end
|
356
208
|
end
|
data/lib/spinach/reporter.rb
CHANGED
@@ -19,35 +19,32 @@ module Spinach
|
|
19
19
|
|
20
20
|
# A Hash with options for the reporter
|
21
21
|
#
|
22
|
-
attr_reader :options
|
23
|
-
|
24
|
-
attr_accessor :current_feature, :current_scenario
|
22
|
+
attr_reader :options, :current_feature, :current_scenario
|
25
23
|
|
26
24
|
attr_reader :undefined_steps, :failed_steps, :error_steps, :undefined_features, :successful_steps
|
27
25
|
|
26
|
+
# Hooks the reporter to the runner endpoints
|
28
27
|
def bind
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
28
|
+
Spinach.hooks.tap do |hooks|
|
29
|
+
hooks.after_run { |*args| after_run(*args) }
|
30
|
+
hooks.before_feature { |*args| before_feature_run(*args) }
|
31
|
+
hooks.after_feature { |*args| after_feature_run(*args) }
|
32
|
+
hooks.on_undefined_feature { |*args| on_feature_not_found(*args) }
|
33
|
+
hooks.before_scenario { |*args| before_scenario_run(*args) }
|
34
|
+
hooks.after_scenario { |*args| after_scenario_run(*args) }
|
35
|
+
hooks.on_successful_step { |*args| on_successful_step(*args) }
|
36
|
+
hooks.on_undefined_step { |*args| on_undefined_step(*args) }
|
37
|
+
hooks.on_failed_step { |*args| on_failed_step(*args) }
|
38
|
+
hooks.on_error_step { |*args| on_error_step(*args) }
|
39
|
+
hooks.on_skipped_step { |*args| on_skipped_step(*args) }
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
hooks.before_feature { |*args| set_current_feature(*args) }
|
42
|
+
hooks.after_feature { |*args| clear_current_feature(*args) }
|
43
|
+
hooks.before_scenario { |*args| set_current_scenario(*args) }
|
44
|
+
hooks.after_scenario { |*args| clear_current_scenario(*args) }
|
45
|
+
end
|
45
46
|
end
|
46
47
|
|
47
|
-
def feature_runner; Runner::Feature; end
|
48
|
-
def scenario_runner; Runner::Scenario; end
|
49
|
-
def runner; Runner; end
|
50
|
-
|
51
48
|
def after_run(*args); end;
|
52
49
|
def before_feature_run(*args); end
|
53
50
|
def after_feature_run(*args); end
|
@@ -60,14 +57,31 @@ module Spinach
|
|
60
57
|
def on_undefined_step(*args); end;
|
61
58
|
def on_skipped_step(*args); end;
|
62
59
|
|
60
|
+
# Stores the current feature
|
61
|
+
#
|
62
|
+
# @param [Hash]
|
63
|
+
# the data for this feature
|
64
|
+
def set_current_feature(data)
|
65
|
+
@current_feature = data
|
66
|
+
end
|
67
|
+
|
68
|
+
# Clears this current feature
|
63
69
|
def clear_current_feature(*args)
|
64
|
-
|
70
|
+
@current_feature = nil
|
65
71
|
end
|
66
72
|
|
67
|
-
|
68
|
-
|
73
|
+
# Stores the current scenario
|
74
|
+
#
|
75
|
+
# @param [Hash]
|
76
|
+
# the data for this scenario
|
77
|
+
def set_current_scenario(data)
|
78
|
+
@current_scenario = data
|
69
79
|
end
|
70
80
|
|
81
|
+
# Clears this current scenario
|
82
|
+
def clear_current_scenario(*args)
|
83
|
+
@current_scenario = nil
|
84
|
+
end
|
71
85
|
end
|
72
86
|
end
|
73
87
|
|
@@ -1,22 +1,12 @@
|
|
1
|
-
require 'hooks'
|
2
|
-
|
3
1
|
module Spinach
|
4
2
|
class Runner
|
5
3
|
# A feature runner handles a particular feature run.
|
6
4
|
#
|
7
|
-
class
|
8
|
-
include Hooks
|
9
|
-
|
10
|
-
# The {Reporter} used in this feature.
|
11
|
-
attr_reader :reporter
|
5
|
+
class FeatureRunner
|
12
6
|
|
13
7
|
# The file that describes the feature.
|
14
8
|
attr_reader :filename
|
15
9
|
|
16
|
-
define_hook :before_run
|
17
|
-
define_hook :after_run
|
18
|
-
define_hook :when_not_found
|
19
|
-
|
20
10
|
# @param [String] filename
|
21
11
|
# path to the feature file. Scenario line could be passed to run just
|
22
12
|
# that scenario.
|
@@ -62,20 +52,20 @@ module Spinach
|
|
62
52
|
#
|
63
53
|
# @api public
|
64
54
|
def run
|
65
|
-
|
55
|
+
Spinach.hooks.run_before_feature data
|
66
56
|
|
67
57
|
scenarios.each do |scenario|
|
68
58
|
if !@scenario_line || scenario['line'].to_s == @scenario_line
|
69
|
-
success =
|
59
|
+
success = ScenarioRunner.new(feature_name, scenario).run
|
70
60
|
@failed = true unless success
|
71
61
|
end
|
72
62
|
end
|
73
63
|
|
74
64
|
rescue Spinach::FeatureStepsNotFoundException => e
|
75
|
-
|
65
|
+
Spinach.hooks.run_on_undefined_feature data, e
|
76
66
|
@failed = true
|
77
67
|
ensure
|
78
|
-
|
68
|
+
Spinach.hooks.run_after_feature data
|
79
69
|
return !@failed
|
80
70
|
end
|
81
71
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Spinach
|
2
|
+
class Runner
|
3
|
+
# A Scenario Runner handles a particular scenario run.
|
4
|
+
#
|
5
|
+
class ScenarioRunner
|
6
|
+
attr_reader :feature_name, :data
|
7
|
+
|
8
|
+
# @param [String] feature_name
|
9
|
+
# The feature name
|
10
|
+
#
|
11
|
+
# @param [Hash] data
|
12
|
+
# The parsed feature data.
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
def initialize(feature_name, data)
|
16
|
+
@feature_name = feature_name
|
17
|
+
@data = data
|
18
|
+
end
|
19
|
+
|
20
|
+
def steps
|
21
|
+
@steps ||= data['steps']
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [FeatureSteps]
|
25
|
+
# The feature object used to run this scenario.
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def feature_steps
|
29
|
+
@feature_steps ||= Spinach.find_feature_steps(feature_name).new
|
30
|
+
end
|
31
|
+
|
32
|
+
# Runs this scenario
|
33
|
+
# @return [True, False]
|
34
|
+
# true if this scenario succeeded, false if not
|
35
|
+
def run
|
36
|
+
Spinach.hooks.run_before_scenario data
|
37
|
+
steps.each do |step|
|
38
|
+
Spinach.hooks.run_before_step step
|
39
|
+
unless @exception
|
40
|
+
begin
|
41
|
+
step_location = feature_steps.execute_step(step['name'])
|
42
|
+
Spinach.hooks.run_on_successful_step step, step_location
|
43
|
+
rescue Spinach::FeatureStepsNotFoundException => e
|
44
|
+
raise e
|
45
|
+
rescue *Spinach.config[:failure_exceptions] => e
|
46
|
+
@exception = e
|
47
|
+
Spinach.hooks.run_on_failed_step step, @exception, step_location
|
48
|
+
rescue Spinach::StepNotDefinedException => e
|
49
|
+
@exception = e
|
50
|
+
Spinach.hooks.run_on_undefined_step step, @exception
|
51
|
+
rescue Exception => e
|
52
|
+
@exception = e
|
53
|
+
Spinach.hooks.run_on_error_step step, @exception, step_location
|
54
|
+
end
|
55
|
+
else
|
56
|
+
Spinach.hooks.run_on_skipped_step step
|
57
|
+
end
|
58
|
+
Spinach.hooks.run_after_step step
|
59
|
+
end
|
60
|
+
Spinach.hooks.run_after_scenario data
|
61
|
+
!@exception
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|