spinach 0.6.0 → 0.6.1

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/Gemfile CHANGED
@@ -9,7 +9,7 @@ group :test do
9
9
  gem 'guard'
10
10
  gem 'guard-minitest'
11
11
  gem 'guard-spinach'
12
- gem 'capybara', '~> 1.1.3'
12
+ gem 'capybara', '~> 2.0.0'
13
13
  end
14
14
 
15
15
  group :darwin do
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 maintanability: since features map to their own classes, their steps are
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
 
@@ -1 +1,6 @@
1
1
  require 'minitest/spec'
2
+ require_relative 'filesystem'
3
+
4
+ Spinach.hooks.after_run do |scenario|
5
+ FileUtils.rm_rf(Filesystem.dirs)
6
+ end
@@ -4,6 +4,10 @@ require 'fileutils'
4
4
  # and lets the host know about it.
5
5
  #
6
6
  module Filesystem
7
+ def self.dirs
8
+ ['tmp/fs']
9
+ end
10
+
7
11
  # Writes a file with some contents.
8
12
  #
9
13
  # @param [String] filename
data/lib/spinach/cli.rb CHANGED
@@ -21,7 +21,13 @@ module Spinach
21
21
  # @api public
22
22
  def run
23
23
  options
24
- Spinach::Runner.new(feature_files).run
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
- Spinach::Generators.bind
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
- # Uses given args to list the feature files to run. It will find a single
108
- # feature, features in a folder and subfolders or every feature file in the
109
- # feature path.
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
@@ -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
@@ -3,21 +3,19 @@ module Spinach
3
3
  # given some parsed feature data.
4
4
  #
5
5
  module Generators
6
- # Binds the feature generator to the "feature not found" hook
7
- def self.bind
8
- Spinach.hooks.on_undefined_feature do |data|
9
- Spinach::Generators.generate_feature(data)
10
- end
11
- end
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
- # 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
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
@@ -75,6 +75,7 @@ module Spinach
75
75
  FileUtils.mkdir_p path
76
76
  File.open(filename_with_path, 'w') do |file|
77
77
  file.write(generate)
78
+ puts "generating #{File.basename(filename_with_path)}"
78
79
  end
79
80
  end
80
81
  end
@@ -1,4 +1,4 @@
1
1
  module Spinach
2
2
  # Spinach version.
3
- VERSION = "0.6.0"
3
+ VERSION = "0.6.1"
4
4
  end
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', '~> 1.1.3'
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'
@@ -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(:bind)
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 '#run' do
199
+ describe '#feature_files' do
189
200
  describe 'when a particular feature list is passed' do
190
- it 'runs the feature' do
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.expects(:file?).with('features/some_feature.feature').returns(true)
211
+ File.stubs(:exists?).returns(false)
212
+ cli.expects(:fail!).with('features/some_feature.feature could not be found')
193
213
 
194
- Spinach::Runner.expects(:new).with(['features/some_feature.feature']).
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 'runs the feature' do
219
+ it 'returns the feature with the line number' do
202
220
  cli = Spinach::Cli.new(['features/some_feature.feature:10'])
203
- File.expects(:file?).with('features/some_feature.feature').returns(true)
221
+ File.stubs(:exists?).returns(true)
204
222
 
205
- Spinach::Runner.expects(:new).with(['features/some_feature.feature:10']).
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 'runs the feature' do
228
+ it 'returns all the features' do
213
229
  cli = Spinach::Cli.new([])
214
- Dir.expects(:glob).with('features/**/*.feature').
215
- returns(['features/some_feature.feature'])
216
- Spinach::Runner.expects(:new).with(['features/some_feature.feature']).
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 'runs all feature files in the folder and subfolders' do
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.expects(:directory?).with('path/to/features').returns(true)
227
- Dir.expects(:glob).with('path/to/features/**/*.feature').
228
- returns(['path/to/features/feature1.feature',
229
- 'path/to/features/feature2.feature',
230
- 'path/to/features/feature3.feature',
231
- 'path/to/features/domain/feature4.feature'])
232
-
233
- Spinach::Runner.expects(:new).with([
234
- 'path/to/features/feature1.feature',
235
- 'path/to/features/feature2.feature',
236
- 'path/to/features/feature3.feature',
237
- 'path/to/features/domain/feature4.feature']).
238
- returns(stub(:run))
239
-
240
- cli.run
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.0
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-11-27 00:00:00.000000000 Z
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: 1.1.3
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: 1.1.3
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: -489699544028213773
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: -489699544028213773
328
+ hash: -2192107922436848750
329
329
  requirements: []
330
330
  rubyforge_project:
331
- rubygems_version: 1.8.24
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