spinach 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|