spinach 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/README.markdown +61 -1
- data/features/support/env.rb +5 -0
- data/features/support/filesystem.rb +4 -0
- data/lib/spinach/cli.rb +45 -20
- data/lib/spinach/config.rb +5 -0
- data/lib/spinach/generators.rb +12 -14
- data/lib/spinach/generators/feature_generator.rb +1 -0
- data/lib/spinach/version.rb +1 -1
- data/spinach.gemspec +1 -1
- data/test/spinach/cli_test.rb +53 -34
- metadata +7 -7
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -6,7 +6,7 @@ executable specifications of your application or library's acceptance criteria.
|
|
6
6
|
|
7
7
|
Conceived as an alternative to Cucumber, here are some of its design goals:
|
8
8
|
|
9
|
-
* Step
|
9
|
+
* Step maintainability: since features map to their own classes, their steps are
|
10
10
|
just methods of that class. This encourages step encapsulation.
|
11
11
|
|
12
12
|
* Step reusability: In case you want to reuse steps across features, you can
|
@@ -149,6 +149,65 @@ end
|
|
149
149
|
|
150
150
|
Then run your feature again running `spinach` and watch it all turn green! :)
|
151
151
|
|
152
|
+
## Shared Steps
|
153
|
+
|
154
|
+
You'll often find that some steps need to be used in many
|
155
|
+
features. In this case, it makes sense to put these steps in reusable
|
156
|
+
modules. For example, let's say you need a step that logs the
|
157
|
+
user into the site.
|
158
|
+
|
159
|
+
This is one way to make that reusable:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
# ... features/steps/common_steps/login.rb
|
163
|
+
module CommonSteps
|
164
|
+
module Login
|
165
|
+
extend ActiveSupport::Concern
|
166
|
+
|
167
|
+
def self.included(mod)
|
168
|
+
mod.send(:Given, 'I am logged in') do
|
169
|
+
# log in stuff...
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# within a rails app, you might want to use ActiveSupport::Concern
|
176
|
+
module CommonSteps
|
177
|
+
module Login
|
178
|
+
extend ActiveSupport::Concern
|
179
|
+
|
180
|
+
included do
|
181
|
+
Given 'I am logged in' do
|
182
|
+
# log in stuff...
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
Using the module (in any feature):
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
# ... features/steps/buying_a_widget.rb
|
193
|
+
class BuyAWidget < Spinach::FeatureSteps
|
194
|
+
# simply include this module and you are good to go
|
195
|
+
include CommonSteps::Login
|
196
|
+
end
|
197
|
+
```
|
198
|
+
|
199
|
+
Also, don't forgot to require all of these common steps in your env.rb:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
# env.rb
|
203
|
+
common_steps = Dir.glob(Rails.root.join("features/steps/common_steps/**/*.rb"))
|
204
|
+
|
205
|
+
common_steps.each do |f|
|
206
|
+
require f
|
207
|
+
end
|
208
|
+
```
|
209
|
+
|
210
|
+
|
152
211
|
## Tags
|
153
212
|
|
154
213
|
Feature and Scenarios can be marked with tags in the form: `@tag`. Tags can be
|
@@ -275,6 +334,7 @@ Check out our [spinach-sinatra demo](https://github.com/codegram/spinach-sinatra
|
|
275
334
|
|
276
335
|
* [guard-spinach](http://github.com/codegram/guard-spinach)
|
277
336
|
* [spinach-rails](http://github.com/codegram/spinach-rails)
|
337
|
+
* [spinach-console-reporter](https://github.com/ywen/spinach-console-reporter) (to be used with Jenkins)
|
278
338
|
|
279
339
|
### Demos
|
280
340
|
|
data/features/support/env.rb
CHANGED
data/lib/spinach/cli.rb
CHANGED
@@ -21,7 +21,13 @@ module Spinach
|
|
21
21
|
# @api public
|
22
22
|
def run
|
23
23
|
options
|
24
|
-
|
24
|
+
|
25
|
+
# only generating steps, do not run tests
|
26
|
+
if Spinach.config.generate
|
27
|
+
exit 0
|
28
|
+
else
|
29
|
+
Spinach::Runner.new(feature_files).run
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
33
|
# @return [Hash]
|
@@ -36,6 +42,38 @@ module Spinach
|
|
36
42
|
@options ||= parse_options
|
37
43
|
end
|
38
44
|
|
45
|
+
# Uses given args to list the feature files to run. It will find a single
|
46
|
+
# feature, features in a folder and subfolders or every feature file in the
|
47
|
+
# feature path.
|
48
|
+
#
|
49
|
+
# @return [Array]
|
50
|
+
# An array with the feature file names.
|
51
|
+
#
|
52
|
+
# @api public
|
53
|
+
def feature_files
|
54
|
+
files_to_run = []
|
55
|
+
|
56
|
+
@args.each do |arg|
|
57
|
+
if arg.match /\.feature/
|
58
|
+
if File.exists? arg.gsub(/:\d*/, '')
|
59
|
+
files_to_run << arg
|
60
|
+
else
|
61
|
+
fail! "#{arg} could not be found"
|
62
|
+
end
|
63
|
+
elsif File.directory?(arg)
|
64
|
+
files_to_run << Dir.glob(File.join(arg, '**', '*.feature'))
|
65
|
+
else
|
66
|
+
fail! "invalid argument - #{arg}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if !files_to_run.empty?
|
71
|
+
files_to_run.flatten
|
72
|
+
else
|
73
|
+
Dir.glob(File.join(Spinach.config[:features_path], '**', '*.feature'))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
39
77
|
private
|
40
78
|
|
41
79
|
# Parses the arguments into options.
|
@@ -73,7 +111,8 @@ module Spinach
|
|
73
111
|
|
74
112
|
opts.on('-g', '--generate',
|
75
113
|
'Auto-generate the feature steps files') do
|
76
|
-
|
114
|
+
config[:generate] = true
|
115
|
+
Spinach::Generators.run(feature_files)
|
77
116
|
end
|
78
117
|
|
79
118
|
opts.on_tail('--version', 'Show version') do
|
@@ -104,24 +143,10 @@ module Spinach
|
|
104
143
|
end
|
105
144
|
end
|
106
145
|
|
107
|
-
#
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
# @return [Array]
|
112
|
-
# An array with the feature file names.
|
113
|
-
#
|
114
|
-
# @api private
|
115
|
-
def feature_files
|
116
|
-
path = @args.first.to_s
|
117
|
-
|
118
|
-
if File.file?(path.split(":").first.to_s)
|
119
|
-
@args
|
120
|
-
elsif File.directory?(path)
|
121
|
-
Dir.glob(File.join(path, '**', '*.feature'))
|
122
|
-
else
|
123
|
-
Dir.glob(File.join(Spinach.config[:features_path], '**', '*.feature'))
|
124
|
-
end
|
146
|
+
# exit test run with an optional message to the user
|
147
|
+
def fail!(message=nil)
|
148
|
+
puts message if message
|
149
|
+
exit 1
|
125
150
|
end
|
126
151
|
end
|
127
152
|
end
|
data/lib/spinach/config.rb
CHANGED
@@ -29,6 +29,7 @@ module Spinach
|
|
29
29
|
:failure_exceptions,
|
30
30
|
:config_path,
|
31
31
|
:tags,
|
32
|
+
:generate,
|
32
33
|
:save_and_open_page_on_failure,
|
33
34
|
:reporter_class,
|
34
35
|
:reporter_options
|
@@ -85,6 +86,10 @@ module Spinach
|
|
85
86
|
@support_path || "#{self.features_path}/support"
|
86
87
|
end
|
87
88
|
|
89
|
+
def generate
|
90
|
+
@generate || false
|
91
|
+
end
|
92
|
+
|
88
93
|
# Allows you to read the config object using a hash-like syntax.
|
89
94
|
#
|
90
95
|
# @param [String] attribute
|
data/lib/spinach/generators.rb
CHANGED
@@ -3,21 +3,19 @@ module Spinach
|
|
3
3
|
# given some parsed feature data.
|
4
4
|
#
|
5
5
|
module Generators
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
# generates steps for features
|
7
|
+
# @files [Array]
|
8
|
+
# filenames to evaluate for step generation
|
9
|
+
def self.run(files)
|
10
|
+
files.each do |file|
|
11
|
+
feature = Parser.open_file(file).parse
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
rescue FeatureGeneratorException => e
|
20
|
-
$stderr.puts e
|
13
|
+
begin
|
14
|
+
FeatureGenerator.new(feature).store
|
15
|
+
rescue FeatureGeneratorException
|
16
|
+
# probably not optimal, but ignoring this
|
17
|
+
end
|
18
|
+
end
|
21
19
|
end
|
22
20
|
end
|
23
21
|
end
|
data/lib/spinach/version.rb
CHANGED
data/spinach.gemspec
CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.add_development_dependency 'rake'
|
15
15
|
gem.add_development_dependency 'mocha'
|
16
16
|
gem.add_development_dependency 'sinatra'
|
17
|
-
gem.add_development_dependency 'capybara', '~>
|
17
|
+
gem.add_development_dependency 'capybara', '~> 2.0.0'
|
18
18
|
gem.add_development_dependency 'pry'
|
19
19
|
gem.add_development_dependency 'simplecov'
|
20
20
|
gem.add_development_dependency 'rspec'
|
data/test/spinach/cli_test.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
require_relative '../test_helper'
|
2
2
|
|
3
3
|
describe Spinach::Cli do
|
4
|
+
describe '#run' do
|
5
|
+
it 'gets the options and runs the features' do
|
6
|
+
cli = Spinach::Cli.new(['features/some_feature.feature'])
|
7
|
+
cli.stubs(:feature_files).returns(['features/some_feature.feature'])
|
8
|
+
|
9
|
+
cli.expects(:options)
|
10
|
+
Spinach::Runner.any_instance.expects(:run)
|
11
|
+
cli.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
describe '#options' do
|
5
16
|
it 'sets the default options' do
|
6
17
|
config = Spinach::Config.new
|
@@ -131,7 +142,7 @@ tags:
|
|
131
142
|
describe 'generate' do
|
132
143
|
%w{-g --generate}.each do |opt|
|
133
144
|
it 'inits the generator if #{opt}' do
|
134
|
-
Spinach::Generators.expects(:
|
145
|
+
Spinach::Generators.expects(:run)
|
135
146
|
cli = Spinach::Cli.new([opt])
|
136
147
|
options = cli.options
|
137
148
|
end
|
@@ -185,59 +196,67 @@ tags:
|
|
185
196
|
end
|
186
197
|
end
|
187
198
|
|
188
|
-
describe '#
|
199
|
+
describe '#feature_files' do
|
189
200
|
describe 'when a particular feature list is passed' do
|
190
|
-
|
201
|
+
describe 'the feature really exists' do
|
202
|
+
it 'runs the feature' do
|
203
|
+
cli = Spinach::Cli.new(['features/some_feature.feature'])
|
204
|
+
File.stubs(:exists?).returns(true)
|
205
|
+
cli.feature_files.must_equal ['features/some_feature.feature']
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe 'it fails if the feature does not exist' do
|
191
210
|
cli = Spinach::Cli.new(['features/some_feature.feature'])
|
192
|
-
File.
|
211
|
+
File.stubs(:exists?).returns(false)
|
212
|
+
cli.expects(:fail!).with('features/some_feature.feature could not be found')
|
193
213
|
|
194
|
-
|
195
|
-
returns(stub(:run))
|
196
|
-
cli.run
|
214
|
+
cli.feature_files
|
197
215
|
end
|
198
216
|
end
|
199
217
|
|
200
218
|
describe 'when a particular feature list is passed with line' do
|
201
|
-
it '
|
219
|
+
it 'returns the feature with the line number' do
|
202
220
|
cli = Spinach::Cli.new(['features/some_feature.feature:10'])
|
203
|
-
File.
|
221
|
+
File.stubs(:exists?).returns(true)
|
204
222
|
|
205
|
-
|
206
|
-
returns(stub(:run))
|
207
|
-
cli.run
|
223
|
+
cli.feature_files.must_equal ['features/some_feature.feature:10']
|
208
224
|
end
|
209
225
|
end
|
210
226
|
|
211
227
|
describe 'when no feature is passed' do
|
212
|
-
it '
|
228
|
+
it 'returns all the features' do
|
213
229
|
cli = Spinach::Cli.new([])
|
214
|
-
Dir.expects(:glob).with('features/**/*.feature')
|
215
|
-
|
216
|
-
|
217
|
-
returns(stub(:run))
|
218
|
-
cli.run
|
230
|
+
Dir.expects(:glob).with('features/**/*.feature')
|
231
|
+
|
232
|
+
cli.feature_files
|
219
233
|
end
|
220
234
|
end
|
221
235
|
|
222
236
|
describe 'when a folder is given' do
|
223
|
-
it '
|
237
|
+
it 'returns all feature files in the folder and subfolders' do
|
224
238
|
cli = Spinach::Cli.new(['path/to/features'])
|
225
239
|
|
226
|
-
File.
|
227
|
-
Dir.expects(:glob).with('path/to/features/**/*.feature')
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
240
|
+
File.stubs(:directory?).returns(true)
|
241
|
+
Dir.expects(:glob).with('path/to/features/**/*.feature')
|
242
|
+
|
243
|
+
cli.feature_files
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe 'when multiple arguments are passed in' do
|
248
|
+
describe 'a folder followed by file' do
|
249
|
+
it 'returns the features in the folder and the particular file' do
|
250
|
+
cli = Spinach::Cli.new(['path/to/features', 'some_feature.feature'])
|
251
|
+
|
252
|
+
File.stubs(:directory?).returns(true)
|
253
|
+
Dir.expects(:glob).with('path/to/features/**/*.feature')
|
254
|
+
.returns(['several features'])
|
255
|
+
|
256
|
+
File.stubs(:exists?).returns(true)
|
257
|
+
|
258
|
+
cli.feature_files.must_equal ['several features', 'some_feature.feature']
|
259
|
+
end
|
241
260
|
end
|
242
261
|
end
|
243
262
|
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.6.
|
4
|
+
version: 0.6.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2012-
|
15
|
+
date: 2012-12-16 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: gherkin-ruby
|
@@ -101,7 +101,7 @@ dependencies:
|
|
101
101
|
requirements:
|
102
102
|
- - ~>
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
104
|
+
version: 2.0.0
|
105
105
|
type: :development
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
requirements:
|
110
110
|
- - ~>
|
111
111
|
- !ruby/object:Gem::Version
|
112
|
-
version:
|
112
|
+
version: 2.0.0
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: pry
|
115
115
|
requirement: !ruby/object:Gem::Requirement
|
@@ -316,7 +316,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
316
316
|
version: '0'
|
317
317
|
segments:
|
318
318
|
- 0
|
319
|
-
hash: -
|
319
|
+
hash: -2192107922436848750
|
320
320
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
321
321
|
none: false
|
322
322
|
requirements:
|
@@ -325,10 +325,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
325
325
|
version: '0'
|
326
326
|
segments:
|
327
327
|
- 0
|
328
|
-
hash: -
|
328
|
+
hash: -2192107922436848750
|
329
329
|
requirements: []
|
330
330
|
rubyforge_project:
|
331
|
-
rubygems_version: 1.8.
|
331
|
+
rubygems_version: 1.8.23
|
332
332
|
signing_key:
|
333
333
|
specification_version: 3
|
334
334
|
summary: Spinach is a BDD framework on top of gherkin
|