spinach 0.1.3 → 0.1.4
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.
- data/features/generate_features.feature +10 -0
- data/features/steps/automatic_feature_generation.rb +32 -0
- data/features/steps/exit_status.rb +0 -2
- data/features/steps/reporting/display_run_summary.rb +33 -26
- data/features/support/spinach_runner.rb +1 -1
- data/lib/spinach/cli.rb +3 -0
- data/lib/spinach/dsl.rb +5 -5
- data/lib/spinach/exceptions.rb +9 -5
- data/lib/spinach/generators/feature_generator.rb +96 -0
- data/lib/spinach/generators/step_generator.rb +22 -0
- data/lib/spinach/generators.rb +26 -0
- data/lib/spinach/parser.rb +13 -7
- data/lib/spinach/reporter/stdout.rb +28 -18
- data/lib/spinach/runner/feature.rb +6 -5
- data/lib/spinach/support.rb +17 -0
- data/lib/spinach/version.rb +1 -1
- data/lib/spinach.rb +1 -0
- data/spinach.gemspec +1 -0
- data/test/spinach/capybara_test.rb +3 -3
- data/test/spinach/cli_test.rb +11 -0
- data/test/spinach/generators/feature_generator_test.rb +128 -0
- data/test/spinach/generators/step_generator_test.rb +21 -0
- data/test/spinach/generators_test.rb +48 -0
- data/test/spinach/parser_test.rb +9 -12
- data/test/spinach/reporter/stdout_test.rb +24 -3
- data/test/spinach/runner/feature_test.rb +1 -1
- data/test/spinach/runner/scenario_test.rb +5 -5
- data/test/spinach/support_test.rb +8 -0
- data/test/test_helper.rb +4 -1
- metadata +54 -30
@@ -0,0 +1,10 @@
|
|
1
|
+
Feature: Automatic feature generation
|
2
|
+
In order to be faster writing features
|
3
|
+
As a developer
|
4
|
+
I want spinach to automatically generate features for me
|
5
|
+
|
6
|
+
Scenario: Missing feature
|
7
|
+
Given I have defined a "Cheezburger can I has" feature
|
8
|
+
When I run spinach with "--generate"
|
9
|
+
Then I a feature should exist named "features/steps/cheezburger_can_i_has.rb"
|
10
|
+
And that feature should have the example feature steps
|
@@ -0,0 +1,32 @@
|
|
1
|
+
Feature 'Automatic feature generation' do
|
2
|
+
include Integration::SpinachRunner
|
3
|
+
Given 'I have defined a "Cheezburger can I has" feature' do
|
4
|
+
write_file('features/cheezburger_can_i_has.feature',
|
5
|
+
'Feature: Cheezburger can I has
|
6
|
+
Scenario: Some Lulz
|
7
|
+
Given I haz a sad
|
8
|
+
When I get some lulz
|
9
|
+
Then I haz a happy')
|
10
|
+
end
|
11
|
+
|
12
|
+
When 'I run spinach with "--generate"' do
|
13
|
+
run_feature 'features/cheezburger_can_i_has.feature', append: '--generate'
|
14
|
+
end
|
15
|
+
|
16
|
+
Then 'I a feature should exist named "features/steps/cheezburger_can_i_has.rb"' do
|
17
|
+
stop_processes!
|
18
|
+
in_current_dir do
|
19
|
+
@file = 'features/steps/cheezburger_can_i_has.rb'
|
20
|
+
File.exists?(@file).must_equal true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
And "that feature should have the example feature steps" do
|
25
|
+
in_current_dir do
|
26
|
+
content = File.read(@file)
|
27
|
+
content.must_include "I haz a sad"
|
28
|
+
content.must_include "I get some lulz"
|
29
|
+
content.must_include "I haz a happy"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -12,38 +12,45 @@ Feature "Display run summary" do
|
|
12
12
|
When I jump from Codegrams roof
|
13
13
|
Then I must be pwned by floor
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
15
|
+
Scenario: Failed scenario
|
16
|
+
Given I love risk
|
17
|
+
When I jump from Codegrams roof
|
18
|
+
Then my parachute must open
|
19
|
+
Then I must not be pwned by floor
|
20
|
+
|
21
|
+
Scenario: Error scenario
|
22
|
+
Given I am not a fool
|
23
|
+
When I go downstairs
|
24
|
+
Then I must succeed
|
25
25
|
')
|
26
26
|
write_file('features/steps/test_feature.rb',
|
27
27
|
'Feature "A test feature" do
|
28
28
|
Given "I am a fool" do
|
29
29
|
end
|
30
|
+
|
30
31
|
When "I jump from Codegrams roof" do
|
31
32
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
33
|
+
|
34
|
+
Given "I love risk" do
|
35
|
+
end
|
36
|
+
|
37
|
+
And "my parachute must open" do
|
38
|
+
false.must_equal true
|
39
|
+
end
|
40
|
+
|
41
|
+
Given "I am a fool" do
|
42
|
+
end
|
43
|
+
|
44
|
+
Given "I am not a fool" do
|
45
|
+
adaksjdald
|
46
|
+
end
|
47
|
+
|
48
|
+
When "I go downstairs" do
|
49
|
+
end
|
50
|
+
|
51
|
+
Then "I must succeed" do
|
52
|
+
true
|
53
|
+
end
|
47
54
|
end')
|
48
55
|
@feature = "features/test_feature.feature"
|
49
56
|
end
|
@@ -54,7 +61,7 @@ Feature "Display run summary" do
|
|
54
61
|
|
55
62
|
Then "I should see a summary with steps status information" do
|
56
63
|
all_stdout.must_match(
|
57
|
-
/Summary:.*
|
64
|
+
/Summary:.*4.*Successful.*1.*Undefined.*1.*Failed.*1.*Error/
|
58
65
|
)
|
59
66
|
end
|
60
67
|
end
|
data/lib/spinach/cli.rb
CHANGED
@@ -67,6 +67,9 @@ module Spinach
|
|
67
67
|
opts.on('-b', '--backtrace', 'Show backtrace of errors') do |v|
|
68
68
|
reporter_options[:backtrace] = v
|
69
69
|
end
|
70
|
+
opts.on('-g', '--generate', 'Auto-generate the feeature steps files') do |v|
|
71
|
+
Spinach::Generators.bind
|
72
|
+
end
|
70
73
|
opts.on_tail('--version', 'Show version') do
|
71
74
|
puts Spinach::VERSION
|
72
75
|
exit
|
data/lib/spinach/dsl.rb
CHANGED
@@ -82,13 +82,13 @@ module Spinach
|
|
82
82
|
#
|
83
83
|
# @api public
|
84
84
|
def execute_step(step)
|
85
|
-
|
85
|
+
undercored_step = Spinach::Support.underscore(step)
|
86
86
|
location = nil
|
87
|
-
if self.respond_to?(
|
88
|
-
location = method(
|
89
|
-
self.send(
|
87
|
+
if self.respond_to?(undercored_step)
|
88
|
+
location = method(undercored_step).source_location
|
89
|
+
self.send(undercored_step)
|
90
90
|
else
|
91
|
-
raise Spinach::StepNotDefinedException.new(
|
91
|
+
raise Spinach::StepNotDefinedException.new(step)
|
92
92
|
end
|
93
93
|
location
|
94
94
|
end
|
data/lib/spinach/exceptions.rb
CHANGED
@@ -28,16 +28,20 @@ module Spinach
|
|
28
28
|
class StepNotDefinedException < StandardError
|
29
29
|
attr_reader :feature, :step
|
30
30
|
|
31
|
-
# @param [Feature] feature
|
32
|
-
# The container feature.
|
33
|
-
#
|
34
31
|
# @param [Hash] step
|
35
32
|
# The missing step.
|
36
33
|
#
|
37
34
|
# @api pulic
|
38
|
-
def initialize(
|
39
|
-
@feature = feature
|
35
|
+
def initialize(step)
|
40
36
|
@step = step
|
41
37
|
end
|
38
|
+
|
39
|
+
# @return [String]
|
40
|
+
# A custom message when scenario steps aren't found.
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def message
|
44
|
+
"Step '#{@step}' not found"
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Spinach
|
2
|
+
module Generators
|
3
|
+
# A feature generator generates and/or writes an example feature steps class
|
4
|
+
# given the parsed feture data
|
5
|
+
class FeatureGenerator
|
6
|
+
|
7
|
+
# @param [Hash] data
|
8
|
+
# the parsed feature data returned from the {Parser}
|
9
|
+
def initialize(data)
|
10
|
+
@data = data
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Array<Hash>]
|
14
|
+
# an array of unique steps found in this scenario, avoiding name
|
15
|
+
# repetition
|
16
|
+
def steps
|
17
|
+
return @steps if @steps
|
18
|
+
@steps = []
|
19
|
+
if scenarios = @data['elements']
|
20
|
+
scenarios.each do |scenario|
|
21
|
+
if scenario_steps = scenario['steps']
|
22
|
+
scenario_steps.each do |step|
|
23
|
+
unless @steps.any?{|s| s['name'] == step['name']}
|
24
|
+
@steps << {
|
25
|
+
'keyword' => step['keyword'].strip,
|
26
|
+
'name' => step['name'].strip
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
@steps
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String]
|
37
|
+
# this feature's name
|
38
|
+
def name
|
39
|
+
@data['name'].strip if @data['name']
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [String]
|
43
|
+
# an example feature steps definition
|
44
|
+
def generate
|
45
|
+
result = StringIO.new
|
46
|
+
result.puts "Feature '#{Spinach::Support.escape_single_commas name}' do"
|
47
|
+
generated_steps = steps.map do |step|
|
48
|
+
step_generator = Generators::StepGenerator.new(step)
|
49
|
+
step_generator.generate.split("\n").map do |line|
|
50
|
+
" #{line}"
|
51
|
+
end.join("\n")
|
52
|
+
end
|
53
|
+
result.puts generated_steps.join("\n\n")
|
54
|
+
result.puts "end"
|
55
|
+
result.string
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [String]
|
59
|
+
# an example filename for this feature steps
|
60
|
+
def filename
|
61
|
+
Spinach::Support.underscore (
|
62
|
+
Spinach::Support.camelize name
|
63
|
+
) + ".rb"
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [String]
|
67
|
+
# the path where this feature steps may be saved
|
68
|
+
def path
|
69
|
+
Spinach.config[:step_definitions_path]
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String]
|
73
|
+
# the expanded path where this feature steps may be saved
|
74
|
+
def filename_with_path
|
75
|
+
File.expand_path File.join(path, filename)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Stores the example feature steps definition into an expected path
|
79
|
+
#
|
80
|
+
def store
|
81
|
+
if File.exists?(filename_with_path)
|
82
|
+
raise FeatureGeneratorException.new("File already exists")
|
83
|
+
else
|
84
|
+
FileUtils.mkdir_p path
|
85
|
+
File.open(filename_with_path, 'w') do |file|
|
86
|
+
file.write(generate)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
class FeatureGeneratorException < Exception; end;
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Spinach
|
2
|
+
# A step generator generates an example output for a step given the parsed
|
3
|
+
# feature data.
|
4
|
+
#
|
5
|
+
class Generators::StepGenerator
|
6
|
+
|
7
|
+
# @param [Hash] data
|
8
|
+
# the parsed step data returned from the {Parser}
|
9
|
+
def initialize(data)
|
10
|
+
@data = data
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String]
|
14
|
+
# an example step definition
|
15
|
+
def generate
|
16
|
+
result = StringIO.new
|
17
|
+
result.puts "#{@data['keyword']} '#{Spinach::Support.escape_single_commas @data['name']}' do"
|
18
|
+
result.puts "end"
|
19
|
+
result.string
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spinach
|
2
|
+
# Spinach generators are a set of utils that auto-generates example features
|
3
|
+
# given some parsed feature data.
|
4
|
+
#
|
5
|
+
module Generators
|
6
|
+
# Binds the feature generator to the "feature not found" hook
|
7
|
+
def self.bind
|
8
|
+
Spinach::Runner::Feature.when_not_found do |data|
|
9
|
+
Spinach::Generators.generate_feature(data)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Generates a feature given a parsed feature data
|
14
|
+
#
|
15
|
+
# @param [Hash] data
|
16
|
+
# the parsed feature data
|
17
|
+
def self.generate_feature(data)
|
18
|
+
FeatureGenerator.new(data).store
|
19
|
+
rescue FeatureGeneratorException => e
|
20
|
+
$stderr.puts e
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require_relative 'generators/feature_generator'
|
26
|
+
require_relative 'generators/step_generator'
|
data/lib/spinach/parser.rb
CHANGED
@@ -5,25 +5,31 @@ module Spinach
|
|
5
5
|
# Parser leverages Gherkin to parse the feature definition.
|
6
6
|
#
|
7
7
|
class Parser
|
8
|
-
# @param [String]
|
9
|
-
# The
|
8
|
+
# @param [String] content
|
9
|
+
# The content to parse.
|
10
10
|
#
|
11
11
|
# @api public
|
12
|
-
def initialize(
|
13
|
-
@
|
12
|
+
def initialize(content)
|
13
|
+
@content = content
|
14
14
|
@formatter = Gherkin::Formatter::JSONFormatter.new(nil)
|
15
15
|
@parser = Gherkin::Parser::Parser.new(@formatter)
|
16
16
|
end
|
17
17
|
|
18
|
+
# @param [String] filename
|
19
|
+
# The filename to parse.
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def self.open_file(filename)
|
23
|
+
new File.read(filename)
|
24
|
+
end
|
25
|
+
|
18
26
|
# Gets the plain text content out of the feature file.
|
19
27
|
#
|
20
28
|
# @return [String]
|
21
29
|
# The plain feature content.
|
22
30
|
#
|
23
31
|
# @api public
|
24
|
-
|
25
|
-
File.read(@filename)
|
26
|
-
end
|
32
|
+
attr_reader :content
|
27
33
|
|
28
34
|
# Parses the feature file and returns an AST as a Hash.
|
29
35
|
#
|
@@ -11,6 +11,8 @@ module Spinach
|
|
11
11
|
|
12
12
|
# The last scenario error
|
13
13
|
attr_accessor :scenario_error
|
14
|
+
|
15
|
+
# The last scenario
|
14
16
|
attr_accessor :scenario
|
15
17
|
|
16
18
|
# Initialitzes the runner
|
@@ -64,6 +66,9 @@ module Spinach
|
|
64
66
|
# @param [Hash] step
|
65
67
|
# The step in a JSON Gherkin format
|
66
68
|
#
|
69
|
+
# @param [Array] step_location
|
70
|
+
# The step source location
|
71
|
+
#
|
67
72
|
def on_successful_step(step, step_location)
|
68
73
|
output_step('✔', step, :green, step_location)
|
69
74
|
self.scenario = [current_feature, current_scenario, step]
|
@@ -105,7 +110,7 @@ module Spinach
|
|
105
110
|
#
|
106
111
|
def on_undefined_step(step, failure)
|
107
112
|
output_step('?', step, :yellow)
|
108
|
-
self.scenario_error = [current_feature, current_scenario, step]
|
113
|
+
self.scenario_error = [current_feature, current_scenario, step, failure]
|
109
114
|
undefined_steps << scenario_error
|
110
115
|
end
|
111
116
|
|
@@ -120,20 +125,15 @@ module Spinach
|
|
120
125
|
def on_feature_not_found(feature, exception)
|
121
126
|
lines = "#{exception.message}\n"
|
122
127
|
|
123
|
-
|
128
|
+
generator = Generators::FeatureGenerator.new(feature)
|
129
|
+
lines << "\nPlease create the file #{generator.filename} at #{generator.path}, with:\n\n"
|
124
130
|
|
125
|
-
lines <<
|
126
|
-
|
127
|
-
# TODO: Write the actual steps. We can do this since we have the entire
|
128
|
-
# feature just here. We should iterate over all the scenarios and return
|
129
|
-
# the different steps
|
130
|
-
#
|
131
|
-
lines << " # Write your steps here\n"
|
132
|
-
lines << "end\n\n"
|
131
|
+
lines << generator.generate
|
133
132
|
|
134
133
|
lines.split("\n").each do |line|
|
135
134
|
out.puts " #{line}".yellow
|
136
135
|
end
|
136
|
+
out.puts "\n\n"
|
137
137
|
|
138
138
|
undefined_features << feature
|
139
139
|
end
|
@@ -181,7 +181,7 @@ module Spinach
|
|
181
181
|
run_summary
|
182
182
|
end
|
183
183
|
|
184
|
-
# Prints the feature success
|
184
|
+
# Prints the feature success summary for this run.
|
185
185
|
#
|
186
186
|
def run_summary
|
187
187
|
successful_summary = "(".colorize(:green)+successful_steps.length.to_s.colorize(:light_green)+") Successful".colorize(:green)
|
@@ -191,7 +191,7 @@ module Spinach
|
|
191
191
|
out.puts "Steps Summary: #{successful_summary}, #{undefined_summary}, #{failed_summary}, #{error_summary}\n\n"
|
192
192
|
end
|
193
193
|
|
194
|
-
# Prints the errors for
|
194
|
+
# Prints the errors for this run.
|
195
195
|
#
|
196
196
|
def error_summary
|
197
197
|
error.puts "\nError summary:\n"
|
@@ -298,17 +298,27 @@ module Spinach
|
|
298
298
|
#
|
299
299
|
def full_error(error)
|
300
300
|
feature, scenario, step, exception = error
|
301
|
-
output =
|
301
|
+
output = "\n"
|
302
302
|
output += report_exception(exception)
|
303
303
|
output +="\n"
|
304
304
|
|
305
|
-
if
|
306
|
-
output
|
307
|
-
|
308
|
-
|
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
|
309
311
|
end
|
312
|
+
output << "\n"
|
310
313
|
else
|
311
|
-
|
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
|
312
322
|
end
|
313
323
|
output
|
314
324
|
end
|
@@ -36,7 +36,7 @@ module Spinach
|
|
36
36
|
#
|
37
37
|
# @api public
|
38
38
|
def data
|
39
|
-
@data ||= Spinach::Parser.
|
39
|
+
@data ||= Spinach::Parser.open_file(filename).parse
|
40
40
|
end
|
41
41
|
|
42
42
|
# @return [String]
|
@@ -66,16 +66,17 @@ module Spinach
|
|
66
66
|
|
67
67
|
scenarios.each do |scenario|
|
68
68
|
if !@scenario_line || scenario['line'].to_s == @scenario_line
|
69
|
-
|
69
|
+
success = Scenario.new(feature_name, scenario).run
|
70
|
+
@failed = true unless success
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
run_hook :after_run, data
|
74
|
-
|
75
74
|
rescue Spinach::FeatureStepsNotFoundException => e
|
76
75
|
run_hook :when_not_found, data, e
|
76
|
+
@failed = true
|
77
77
|
ensure
|
78
|
-
|
78
|
+
run_hook :after_run, data
|
79
|
+
return !@failed
|
79
80
|
end
|
80
81
|
end
|
81
82
|
end
|
data/lib/spinach/support.rb
CHANGED
@@ -38,5 +38,22 @@ module Spinach
|
|
38
38
|
word.downcase!
|
39
39
|
word
|
40
40
|
end
|
41
|
+
|
42
|
+
# Escapes the single commas of a given text. Mostly used in the {Generators}
|
43
|
+
# classes
|
44
|
+
#
|
45
|
+
# @param [String] text
|
46
|
+
# The text to escape
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
# The +text+ with escaped commas
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# Spinach::Support.escape_single_commas("I've been bad")
|
53
|
+
# # => "I\'ve been bad"
|
54
|
+
#
|
55
|
+
def self.escape_single_commas(text)
|
56
|
+
text.sub("'", "\\\\'")
|
57
|
+
end
|
41
58
|
end
|
42
59
|
end
|
data/lib/spinach/version.rb
CHANGED
data/lib/spinach.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative 'spinach/dsl'
|
|
8
8
|
require_relative 'spinach/feature_steps'
|
9
9
|
require_relative 'spinach/reporter'
|
10
10
|
require_relative 'spinach/cli'
|
11
|
+
require_relative 'spinach/generators'
|
11
12
|
|
12
13
|
# Spinach is a BDD framework leveraging the great Gherkin language. This
|
13
14
|
# language is the one used defining features in Cucumber, the BDD framework
|
data/spinach.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |gem|
|
|
22
22
|
gem.add_development_dependency 'pry'
|
23
23
|
gem.add_development_dependency 'simplecov'
|
24
24
|
gem.add_development_dependency 'rspec'
|
25
|
+
gem.add_development_dependency 'fakefs'
|
25
26
|
|
26
27
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
28
|
gem.files = `git ls-files`.split("\n")
|
@@ -36,9 +36,9 @@ describe Spinach::FeatureSteps::Capybara do
|
|
36
36
|
|
37
37
|
it 'resets the capybara session after each scenario' do
|
38
38
|
@feature_runner = Spinach::Runner::Feature.new(
|
39
|
-
|
39
|
+
'a_feature.feature')
|
40
40
|
|
41
|
-
Spinach::Parser.
|
41
|
+
@feature_runner.stubs(data: Spinach::Parser.new('
|
42
42
|
Feature: A test feature
|
43
43
|
Scenario: A test scenario
|
44
44
|
Given Hello
|
@@ -46,7 +46,7 @@ describe Spinach::FeatureSteps::Capybara do
|
|
46
46
|
Scenario: Another test scenario
|
47
47
|
Given Hello
|
48
48
|
Then Goodbye
|
49
|
-
').at_least_once
|
49
|
+
').parse).at_least_once
|
50
50
|
|
51
51
|
Spinach::Runner::Scenario.any_instance.stubs(feature: @feature)
|
52
52
|
|
data/test/spinach/cli_test.rb
CHANGED
@@ -17,6 +17,17 @@ describe Spinach::Cli do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
describe 'backtrace' do
|
22
|
+
%w{-g --generate}.each do |opt|
|
23
|
+
it 'inits the generator if #{opt}' do
|
24
|
+
Spinach::Generators.expects(:bind)
|
25
|
+
cli = Spinach::Cli.new([opt])
|
26
|
+
options = cli.options
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
20
31
|
describe "version" do
|
21
32
|
%w{-v --version}.each do |opt|
|
22
33
|
it "outputs the version" do
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
require_relative '../../../lib/spinach/generators'
|
3
|
+
|
4
|
+
module Spinach::Generators
|
5
|
+
describe FeatureGenerator do
|
6
|
+
subject do
|
7
|
+
FeatureGenerator.new(data)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:data) do
|
11
|
+
Spinach::Parser.new("
|
12
|
+
Feature: Cheezburger can I has
|
13
|
+
Scenario: Some Lulz
|
14
|
+
Given I haz a sad
|
15
|
+
When I get some lulz
|
16
|
+
Then I haz a happy
|
17
|
+
Scenario: Some sad
|
18
|
+
Given I haz a happy
|
19
|
+
When I get some lulz
|
20
|
+
Then I am OMG ROFLMAO").parse
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#name" do
|
24
|
+
it "returns the scenario name" do
|
25
|
+
subject.name.must_equal 'Cheezburger can I has'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns nil if no name present" do
|
29
|
+
data['name'] = nil
|
30
|
+
subject.name.must_equal nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#steps" do
|
35
|
+
it "returns a correct number different steps for this data" do
|
36
|
+
subject.steps.length.must_equal 4
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "includes the correct steps" do
|
40
|
+
it "includes 'Given I haz a sad'" do
|
41
|
+
subject.steps.any?{ |step|
|
42
|
+
(step['keyword'] == 'Given') && (step['name'] == 'I haz a sad')
|
43
|
+
}.must_equal true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "includes 'When I get some lulz'" do
|
47
|
+
subject.steps.any?{ |step|
|
48
|
+
(step['keyword'] == 'When') && (step['name'] == 'I get some lulz')
|
49
|
+
}.must_equal true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "includes 'Then I has a happy'" do
|
53
|
+
subject.steps.any?{ |step|
|
54
|
+
(step['keyword'] == 'Then') && (step['name'] == 'I haz a happy')
|
55
|
+
}.must_equal true
|
56
|
+
end
|
57
|
+
|
58
|
+
it "does not include 'Given I haz a happy'" do
|
59
|
+
subject.steps.any?{ |step|
|
60
|
+
(step['keyword'] == 'Given') && (step['name'] == 'I haz a happy')
|
61
|
+
}.must_equal false
|
62
|
+
end
|
63
|
+
|
64
|
+
it "includes 'Then I am OMG ROFLMAO'" do
|
65
|
+
subject.steps.any?{ |step|
|
66
|
+
(step['keyword'] == 'Then') && (step['name'] == 'I am OMG ROFLMAO')
|
67
|
+
}.must_equal true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#generate" do
|
73
|
+
it "generates an entire feature_steps class definition" do
|
74
|
+
result = subject.generate
|
75
|
+
klass = eval(result)
|
76
|
+
feature_runner = Spinach::Runner::Feature.new(stub_everything)
|
77
|
+
feature_runner.stubs(data: data)
|
78
|
+
feature_runner.run.must_equal true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#filename" do
|
83
|
+
it "returns a valid filename for the feature" do
|
84
|
+
subject.filename.must_equal "cheezburger_can_i_has.rb"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#path" do
|
89
|
+
it "should return a valid path" do
|
90
|
+
subject.path.must_include 'features/steps'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#filename_with_path" do
|
95
|
+
it "should the filename prepended with the path" do
|
96
|
+
subject.filename_with_path.
|
97
|
+
must_include 'features/steps/cheezburger_can_i_has.rb'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#store" do
|
102
|
+
it "stores the generated feature into a file" do
|
103
|
+
FakeFS.activate!
|
104
|
+
subject.store
|
105
|
+
File.directory?("features/steps/").must_equal true
|
106
|
+
File.exists?("features/steps/cheezburger_can_i_has.rb").must_equal true
|
107
|
+
File.read("features/steps/cheezburger_can_i_has.rb").strip.must_equal(
|
108
|
+
subject.generate.strip
|
109
|
+
)
|
110
|
+
FileUtils.rm_rf("features/steps")
|
111
|
+
FakeFS.deactivate!
|
112
|
+
end
|
113
|
+
|
114
|
+
it "raises an error if the file already exists and does nothing" do
|
115
|
+
file = "features/steps/cheezburger_can_i_has.rb"
|
116
|
+
FakeFS.activate!
|
117
|
+
FileUtils.mkdir_p "features/steps"
|
118
|
+
File.open(file, 'w') do |f|
|
119
|
+
f.write("Fake content")
|
120
|
+
end
|
121
|
+
Proc.new{subject.store}.must_raise(
|
122
|
+
Spinach::Generators::FeatureGeneratorException)
|
123
|
+
FileUtils.rm_rf("features/steps")
|
124
|
+
FakeFS.deactivate!
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
require_relative '../../../lib/spinach/generators'
|
3
|
+
|
4
|
+
module Spinach::Generators
|
5
|
+
describe StepGenerator do
|
6
|
+
subject do
|
7
|
+
StepGenerator.new(data)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:data) do
|
11
|
+
{'keyword' => 'Given', 'name' => "I has a sad"}
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#generate" do
|
15
|
+
it "generates a step" do
|
16
|
+
subject.generate.must_match /Given.*I has a sad/
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Spinach::Generators do
|
4
|
+
subject do
|
5
|
+
Spinach::Generators
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:data) do
|
9
|
+
Spinach::Parser.new("
|
10
|
+
Feature: Cheezburger can I has
|
11
|
+
Scenario: Some Lulz
|
12
|
+
Given I haz a sad
|
13
|
+
When I get some lulz
|
14
|
+
Then I haz a happy
|
15
|
+
Scenario: Some sad
|
16
|
+
Given I haz a happy
|
17
|
+
When I get some lulz
|
18
|
+
Then I am OMG ROFLMAO").parse
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#bind" do
|
22
|
+
it "binds the generator to the missing feature hook" do
|
23
|
+
subject.expects(:generate_feature).with(data)
|
24
|
+
subject.bind
|
25
|
+
Spinach::Runner::Feature.new(stub_everything).run_hook :when_not_found, data
|
26
|
+
Spinach::Runner::Feature._when_not_found_callbacks = []
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#generate_feature" do
|
31
|
+
it "generates a file" do
|
32
|
+
feature_data = data
|
33
|
+
FakeFS.activate!
|
34
|
+
subject.generate_feature(feature_data)
|
35
|
+
File.exists?("features/steps/cheezburger_can_i_has.rb").must_equal true
|
36
|
+
FileUtils.rm_rf("features/steps")
|
37
|
+
FakeFS.deactivate!
|
38
|
+
end
|
39
|
+
it "outputs a message if feature cannot be generated" do
|
40
|
+
subject::FeatureGenerator.expects(:new).raises(
|
41
|
+
Spinach::Generators::FeatureGeneratorException.new("File already exists"))
|
42
|
+
capture_stdout do
|
43
|
+
subject.generate_feature(data)
|
44
|
+
end.must_include "File already exists"
|
45
|
+
File.exists?("features/steps/cheezburger_can_i_has.rb").must_equal false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/test/spinach/parser_test.rb
CHANGED
@@ -2,22 +2,18 @@ require_relative '../test_helper'
|
|
2
2
|
|
3
3
|
describe Spinach::Parser do
|
4
4
|
before do
|
5
|
-
@parser = Spinach::Parser.new(
|
6
|
-
|
7
|
-
|
8
|
-
let(:parsed) { @parser.parse }
|
9
|
-
|
10
|
-
describe '#parse' do
|
11
|
-
before do
|
12
|
-
@parser.stubs(:content).returns("
|
13
|
-
Feature: User authentication
|
5
|
+
@parser = Spinach::Parser.new(
|
6
|
+
"Feature: User authentication
|
14
7
|
Scenario: User logs in
|
15
8
|
Given I am on the front page
|
16
9
|
When I fill in the login form and press 'login'
|
17
10
|
Then I should be on my dashboard
|
18
11
|
")
|
19
|
-
|
12
|
+
end
|
20
13
|
|
14
|
+
let(:parsed) { @parser.parse }
|
15
|
+
|
16
|
+
describe '#parse' do
|
21
17
|
it 'parses the feature name' do
|
22
18
|
parsed['name'].must_equal 'User authentication'
|
23
19
|
end
|
@@ -41,10 +37,11 @@ describe Spinach::Parser do
|
|
41
37
|
end
|
42
38
|
end
|
43
39
|
|
44
|
-
describe '
|
40
|
+
describe '.open_file' do
|
45
41
|
it 'reads the disk and returns the file content' do
|
46
42
|
File.expects(:read).with('feature_definition.feature')
|
47
|
-
@parser.
|
43
|
+
@parser = Spinach::Parser.open_file(
|
44
|
+
'feature_definition.feature')
|
48
45
|
end
|
49
46
|
end
|
50
47
|
end
|
@@ -68,14 +68,27 @@ describe Spinach::Reporter::Stdout do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
describe '#on_successful_step' do
|
71
|
+
let(:step) { {'keyword' => 'Given', 'name' => 'I am too cool'} }
|
71
72
|
let(:step_location){['error_step_location', 1]}
|
72
73
|
it 'adds the step to the output buffer' do
|
73
|
-
@reporter.on_successful_step(
|
74
|
+
@reporter.on_successful_step(step, step_location)
|
74
75
|
|
75
76
|
@out.string.must_include '✔'
|
76
77
|
@out.string.must_include 'Given'
|
77
78
|
@out.string.must_include 'am too cool'
|
78
79
|
end
|
80
|
+
|
81
|
+
it 'sets the current scenario' do
|
82
|
+
@reporter.on_successful_step(step, step_location)
|
83
|
+
|
84
|
+
@reporter.scenario.must_include step
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'adds the step to the successful steps' do
|
88
|
+
@reporter.on_successful_step(step, step_location)
|
89
|
+
|
90
|
+
@reporter.successful_steps.last.must_include step
|
91
|
+
end
|
79
92
|
end
|
80
93
|
|
81
94
|
describe '#on_failed_step' do
|
@@ -238,6 +251,14 @@ describe Spinach::Reporter::Stdout do
|
|
238
251
|
end
|
239
252
|
end
|
240
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
|
+
|
241
262
|
describe '#report_error_steps' do
|
242
263
|
describe 'when some steps have raised an error' do
|
243
264
|
it 'outputs the errors' do
|
@@ -389,7 +410,7 @@ describe Spinach::Reporter::Stdout do
|
|
389
410
|
describe 'when given an undefined step exception' do
|
390
411
|
it 'prints the error in yellow' do
|
391
412
|
undefined_error = error
|
392
|
-
undefined_error.insert(3, Spinach::StepNotDefinedException.new(anything
|
413
|
+
undefined_error.insert(3, Spinach::StepNotDefinedException.new(anything))
|
393
414
|
|
394
415
|
String.any_instance.expects(:yellow)
|
395
416
|
|
@@ -455,7 +476,7 @@ describe Spinach::Reporter::Stdout do
|
|
455
476
|
|
456
477
|
describe 'when given an undefined step exception' do
|
457
478
|
it 'prints the error in yellow' do
|
458
|
-
undefined_exception = Spinach::StepNotDefinedException.new(anything
|
479
|
+
undefined_exception = Spinach::StepNotDefinedException.new(anything)
|
459
480
|
|
460
481
|
String.any_instance.expects(:yellow)
|
461
482
|
|
@@ -21,7 +21,7 @@ describe Spinach::Runner::Feature do
|
|
21
21
|
it 'returns the parsed data' do
|
22
22
|
parsed_data = {name: 'A cool feature'}
|
23
23
|
parser = stub(parse: parsed_data)
|
24
|
-
Spinach::Parser.expects(:
|
24
|
+
Spinach::Parser.expects(:open_file).returns(parser)
|
25
25
|
feature.data.must_equal parsed_data
|
26
26
|
end
|
27
27
|
end
|
@@ -14,8 +14,8 @@ describe Spinach::Runner::Scenario do
|
|
14
14
|
|
15
15
|
let(:feature) { stub_everything }
|
16
16
|
let(:feature_name) { 'My feature' }
|
17
|
-
let(:scenario) {
|
18
|
-
scenario = Spinach::Runner::Scenario.new(feature_name, data)
|
17
|
+
let(:scenario) {
|
18
|
+
scenario = Spinach::Runner::Scenario.new(feature_name, data)
|
19
19
|
scenario.stubs(feature: feature)
|
20
20
|
scenario
|
21
21
|
}
|
@@ -62,7 +62,7 @@ describe Spinach::Runner::Scenario do
|
|
62
62
|
|
63
63
|
it 'rescues a Spinach::StepNotDefinedException' do
|
64
64
|
feature.expects(:execute_step).raises(
|
65
|
-
Spinach::StepNotDefinedException.new('
|
65
|
+
Spinach::StepNotDefinedException.new('bar'))
|
66
66
|
scenario.expects(:run_hook).with(:before_run, has_value("A cool scenario"))
|
67
67
|
scenario.expects(:run_hook).with(:after_run, has_value("A cool scenario"))
|
68
68
|
scenario.expects(:run_hook).with(
|
@@ -96,14 +96,14 @@ describe Spinach::Runner::Scenario do
|
|
96
96
|
|
97
97
|
describe 'hooks' do
|
98
98
|
it 'fires up the scenario hooks' do
|
99
|
-
feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('
|
99
|
+
feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('bar'))
|
100
100
|
feature.expects(:run_hook).with(:before_scenario, has_value("A cool scenario"))
|
101
101
|
feature.expects(:run_hook).with(:after_scenario, has_value("A cool scenario"))
|
102
102
|
scenario.run
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'fires up the step hooks' do
|
106
|
-
feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('
|
106
|
+
feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('bar'))
|
107
107
|
%w{before_step after_step}.each do |hook|
|
108
108
|
feature.expects(:run_hook).with(
|
109
109
|
hook.to_sym, kind_of(Hash))
|
@@ -55,4 +55,12 @@ describe Spinach::Support do
|
|
55
55
|
Spinach::Support.underscore(:FeatureName).must_equal 'feature_name'
|
56
56
|
end
|
57
57
|
end
|
58
|
+
|
59
|
+
describe "#escape" do
|
60
|
+
it "escapes the name" do
|
61
|
+
Spinach::Support.escape_single_commas(
|
62
|
+
"I've been doing bad things"
|
63
|
+
).must_include "I\\'ve been doing bad things"
|
64
|
+
end
|
65
|
+
end
|
58
66
|
end
|
data/test/test_helper.rb
CHANGED
@@ -16,6 +16,7 @@ require 'ostruct'
|
|
16
16
|
require 'purdytest'
|
17
17
|
require 'stringio'
|
18
18
|
require 'pry'
|
19
|
+
require 'fakefs/safe'
|
19
20
|
|
20
21
|
require 'spinach'
|
21
22
|
require 'spinach/capybara'
|
@@ -24,9 +25,11 @@ module Kernel
|
|
24
25
|
def capture_stdout
|
25
26
|
out = StringIO.new
|
26
27
|
$stdout = out
|
28
|
+
$stderr = out
|
27
29
|
yield
|
28
|
-
return out
|
30
|
+
return out.string
|
29
31
|
ensure
|
30
32
|
$stdout = STDOUT
|
33
|
+
$stdout = STDERR
|
31
34
|
end
|
32
35
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spinach
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,11 +12,11 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2011-10-
|
15
|
+
date: 2011-10-11 00:00:00.000000000Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: gherkin
|
19
|
-
requirement: &
|
19
|
+
requirement: &2152679240 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ! '>='
|
@@ -24,10 +24,10 @@ dependencies:
|
|
24
24
|
version: '0'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *2152679240
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: minitest
|
30
|
-
requirement: &
|
30
|
+
requirement: &2152678820 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ! '>='
|
@@ -35,10 +35,10 @@ dependencies:
|
|
35
35
|
version: '0'
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
|
-
version_requirements: *
|
38
|
+
version_requirements: *2152678820
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: colorize
|
41
|
-
requirement: &
|
41
|
+
requirement: &2152678400 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ! '>='
|
@@ -46,10 +46,10 @@ dependencies:
|
|
46
46
|
version: '0'
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
|
-
version_requirements: *
|
49
|
+
version_requirements: *2152678400
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: hooks
|
52
|
-
requirement: &
|
52
|
+
requirement: &2152677960 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
55
|
- - ! '>='
|
@@ -57,10 +57,10 @@ dependencies:
|
|
57
57
|
version: '0'
|
58
58
|
type: :runtime
|
59
59
|
prerelease: false
|
60
|
-
version_requirements: *
|
60
|
+
version_requirements: *2152677960
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: purdytest
|
63
|
-
requirement: &
|
63
|
+
requirement: &2152677520 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
65
65
|
requirements:
|
66
66
|
- - ! '>='
|
@@ -68,10 +68,10 @@ dependencies:
|
|
68
68
|
version: '0'
|
69
69
|
type: :development
|
70
70
|
prerelease: false
|
71
|
-
version_requirements: *
|
71
|
+
version_requirements: *2152677520
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: rake
|
74
|
-
requirement: &
|
74
|
+
requirement: &2152677060 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
77
|
- - ! '>='
|
@@ -79,10 +79,10 @@ dependencies:
|
|
79
79
|
version: '0'
|
80
80
|
type: :development
|
81
81
|
prerelease: false
|
82
|
-
version_requirements: *
|
82
|
+
version_requirements: *2152677060
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: mocha
|
85
|
-
requirement: &
|
85
|
+
requirement: &2152676620 !ruby/object:Gem::Requirement
|
86
86
|
none: false
|
87
87
|
requirements:
|
88
88
|
- - ! '>='
|
@@ -90,10 +90,10 @@ dependencies:
|
|
90
90
|
version: '0'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
|
-
version_requirements: *
|
93
|
+
version_requirements: *2152676620
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: sinatra
|
96
|
-
requirement: &
|
96
|
+
requirement: &2152676180 !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
99
|
- - ! '>='
|
@@ -101,10 +101,10 @@ dependencies:
|
|
101
101
|
version: '0'
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
|
-
version_requirements: *
|
104
|
+
version_requirements: *2152676180
|
105
105
|
- !ruby/object:Gem::Dependency
|
106
106
|
name: capybara
|
107
|
-
requirement: &
|
107
|
+
requirement: &2152675720 !ruby/object:Gem::Requirement
|
108
108
|
none: false
|
109
109
|
requirements:
|
110
110
|
- - ! '>='
|
@@ -112,10 +112,10 @@ dependencies:
|
|
112
112
|
version: '0'
|
113
113
|
type: :development
|
114
114
|
prerelease: false
|
115
|
-
version_requirements: *
|
115
|
+
version_requirements: *2152675720
|
116
116
|
- !ruby/object:Gem::Dependency
|
117
117
|
name: aruba
|
118
|
-
requirement: &
|
118
|
+
requirement: &2152675280 !ruby/object:Gem::Requirement
|
119
119
|
none: false
|
120
120
|
requirements:
|
121
121
|
- - ! '>='
|
@@ -123,10 +123,10 @@ dependencies:
|
|
123
123
|
version: '0'
|
124
124
|
type: :development
|
125
125
|
prerelease: false
|
126
|
-
version_requirements: *
|
126
|
+
version_requirements: *2152675280
|
127
127
|
- !ruby/object:Gem::Dependency
|
128
128
|
name: pry
|
129
|
-
requirement: &
|
129
|
+
requirement: &2152674840 !ruby/object:Gem::Requirement
|
130
130
|
none: false
|
131
131
|
requirements:
|
132
132
|
- - ! '>='
|
@@ -134,10 +134,10 @@ dependencies:
|
|
134
134
|
version: '0'
|
135
135
|
type: :development
|
136
136
|
prerelease: false
|
137
|
-
version_requirements: *
|
137
|
+
version_requirements: *2152674840
|
138
138
|
- !ruby/object:Gem::Dependency
|
139
139
|
name: simplecov
|
140
|
-
requirement: &
|
140
|
+
requirement: &2152674400 !ruby/object:Gem::Requirement
|
141
141
|
none: false
|
142
142
|
requirements:
|
143
143
|
- - ! '>='
|
@@ -145,10 +145,10 @@ dependencies:
|
|
145
145
|
version: '0'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
|
-
version_requirements: *
|
148
|
+
version_requirements: *2152674400
|
149
149
|
- !ruby/object:Gem::Dependency
|
150
150
|
name: rspec
|
151
|
-
requirement: &
|
151
|
+
requirement: &2152673980 !ruby/object:Gem::Requirement
|
152
152
|
none: false
|
153
153
|
requirements:
|
154
154
|
- - ! '>='
|
@@ -156,7 +156,18 @@ dependencies:
|
|
156
156
|
version: '0'
|
157
157
|
type: :development
|
158
158
|
prerelease: false
|
159
|
-
version_requirements: *
|
159
|
+
version_requirements: *2152673980
|
160
|
+
- !ruby/object:Gem::Dependency
|
161
|
+
name: fakefs
|
162
|
+
requirement: &2152673560 !ruby/object:Gem::Requirement
|
163
|
+
none: false
|
164
|
+
requirements:
|
165
|
+
- - ! '>='
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
type: :development
|
169
|
+
prerelease: false
|
170
|
+
version_requirements: *2152673560
|
160
171
|
description: Spinach is a BDD framework on top of gherkin
|
161
172
|
email:
|
162
173
|
- info@codegram.com
|
@@ -179,11 +190,13 @@ files:
|
|
179
190
|
- bin/spinach
|
180
191
|
- features/exit_status.feature
|
181
192
|
- features/feature_name_guessing.feature
|
193
|
+
- features/generate_features.feature
|
182
194
|
- features/reporting/display_run_summary.feature
|
183
195
|
- features/reporting/error_reporting.feature
|
184
196
|
- features/reporting/show_step_source_location.feature
|
185
197
|
- features/reporting/undefined_feature_reporting.feature
|
186
198
|
- features/rspec_compatibility.feature
|
199
|
+
- features/steps/automatic_feature_generation.rb
|
187
200
|
- features/steps/exit_status.rb
|
188
201
|
- features/steps/feature_name_guessing.rb
|
189
202
|
- features/steps/reporting/display_run_summary.rb
|
@@ -201,6 +214,9 @@ files:
|
|
201
214
|
- lib/spinach/dsl.rb
|
202
215
|
- lib/spinach/exceptions.rb
|
203
216
|
- lib/spinach/feature_steps.rb
|
217
|
+
- lib/spinach/generators.rb
|
218
|
+
- lib/spinach/generators/feature_generator.rb
|
219
|
+
- lib/spinach/generators/step_generator.rb
|
204
220
|
- lib/spinach/parser.rb
|
205
221
|
- lib/spinach/reporter.rb
|
206
222
|
- lib/spinach/reporter/stdout.rb
|
@@ -219,6 +235,9 @@ files:
|
|
219
235
|
- test/spinach/config_test.rb
|
220
236
|
- test/spinach/dsl_test.rb
|
221
237
|
- test/spinach/feature_steps_test.rb
|
238
|
+
- test/spinach/generators/feature_generator_test.rb
|
239
|
+
- test/spinach/generators/step_generator_test.rb
|
240
|
+
- test/spinach/generators_test.rb
|
222
241
|
- test/spinach/parser_test.rb
|
223
242
|
- test/spinach/reporter/stdout_test.rb
|
224
243
|
- test/spinach/reporter_test.rb
|
@@ -243,7 +262,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
243
262
|
version: '0'
|
244
263
|
segments:
|
245
264
|
- 0
|
246
|
-
hash:
|
265
|
+
hash: 3283376077311958142
|
247
266
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
248
267
|
none: false
|
249
268
|
requirements:
|
@@ -252,7 +271,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
252
271
|
version: '0'
|
253
272
|
segments:
|
254
273
|
- 0
|
255
|
-
hash:
|
274
|
+
hash: 3283376077311958142
|
256
275
|
requirements: []
|
257
276
|
rubyforge_project:
|
258
277
|
rubygems_version: 1.8.6
|
@@ -262,11 +281,13 @@ summary: Spinach is a BDD framework on top of gherkin
|
|
262
281
|
test_files:
|
263
282
|
- features/exit_status.feature
|
264
283
|
- features/feature_name_guessing.feature
|
284
|
+
- features/generate_features.feature
|
265
285
|
- features/reporting/display_run_summary.feature
|
266
286
|
- features/reporting/error_reporting.feature
|
267
287
|
- features/reporting/show_step_source_location.feature
|
268
288
|
- features/reporting/undefined_feature_reporting.feature
|
269
289
|
- features/rspec_compatibility.feature
|
290
|
+
- features/steps/automatic_feature_generation.rb
|
270
291
|
- features/steps/exit_status.rb
|
271
292
|
- features/steps/feature_name_guessing.rb
|
272
293
|
- features/steps/reporting/display_run_summary.rb
|
@@ -283,6 +304,9 @@ test_files:
|
|
283
304
|
- test/spinach/config_test.rb
|
284
305
|
- test/spinach/dsl_test.rb
|
285
306
|
- test/spinach/feature_steps_test.rb
|
307
|
+
- test/spinach/generators/feature_generator_test.rb
|
308
|
+
- test/spinach/generators/step_generator_test.rb
|
309
|
+
- test/spinach/generators_test.rb
|
286
310
|
- test/spinach/parser_test.rb
|
287
311
|
- test/spinach/reporter/stdout_test.rb
|
288
312
|
- test/spinach/reporter_test.rb
|