spinach 0.9.0 → 0.10.0
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.
- checksums.yaml +4 -4
- data/README.markdown +23 -0
- data/features/step_auditing.feature +59 -0
- data/features/steps/step_auditing.rb +324 -0
- data/features/support/env.rb +1 -1
- data/lib/spinach.rb +1 -0
- data/lib/spinach/auditor.rb +128 -0
- data/lib/spinach/cli.rb +8 -0
- data/lib/spinach/config.rb +12 -1
- data/lib/spinach/dsl.rb +6 -0
- data/lib/spinach/feature.rb +5 -0
- data/lib/spinach/runner/scenario_runner.rb +1 -1
- data/lib/spinach/version.rb +1 -1
- data/test/spinach/capybara_test.rb +1 -1
- metadata +39 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3695a752a99edd4e91fd72df976576aef38a93a
|
4
|
+
data.tar.gz: 8148e0be9f45bd1808f0091edd87630967db287e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f57752557ea737923da6ab5356f7e76c1374590bc0c16dc22142cad4355f17513dac875f13e833dbecb126cb69e7b0515afc3306c2dcd651e6eb0a660484e7b1
|
7
|
+
data.tar.gz: 7452e29f5d8c40f6ba0883c27fbc6ddb93fa24aa53a05ab36a9313765abc651546cc33897c01a4b82177829a0a587bfaaa7ca2a4ba47f8bd3d886fd17c459690
|
data/README.markdown
CHANGED
@@ -181,6 +181,29 @@ class Spinach::Features::BuyAWidget < Spinach::FeatureSteps
|
|
181
181
|
end
|
182
182
|
```
|
183
183
|
|
184
|
+
## Audit
|
185
|
+
|
186
|
+
Over time, the definitions of your features will change. When you add, remove
|
187
|
+
or change steps in the feature files, you can easily audit your existing step
|
188
|
+
files with:
|
189
|
+
|
190
|
+
```shell
|
191
|
+
$ spinach --audit
|
192
|
+
```
|
193
|
+
|
194
|
+
This will find any new steps and print out boilerplate for them, and alert you
|
195
|
+
to the filename and line number of any unused steps in your step files.
|
196
|
+
|
197
|
+
This does not modify the step files, so you will need to paste the boilerplate
|
198
|
+
into the appropriate places. If a new feature file is detected, you will be
|
199
|
+
asked to run `spinach --generate` beforehand.
|
200
|
+
|
201
|
+
**Important**: If auditing individual files, common steps (as above) may be
|
202
|
+
reported as unused when they are actually used in a feature file that is not
|
203
|
+
currently being audited. To avoid this, run the audit with no arguments to
|
204
|
+
audit all step files simultaneously.
|
205
|
+
|
206
|
+
|
184
207
|
## Tags
|
185
208
|
|
186
209
|
Feature and Scenarios can be marked with tags in the form: `@tag`. Tags can be
|
@@ -0,0 +1,59 @@
|
|
1
|
+
Feature: Step auditing
|
2
|
+
In order to be able to update my features
|
3
|
+
As a developer
|
4
|
+
I want spinach to automatically audit which steps are missing and obsolete
|
5
|
+
|
6
|
+
Scenario: Step file out of date
|
7
|
+
Given I have defined a "Cheezburger can I has" feature
|
8
|
+
And I have an associated step file with missing steps and obsolete steps
|
9
|
+
When I run spinach with "--audit"
|
10
|
+
Then I should see a list of unused steps
|
11
|
+
And I should see the code to paste for missing steps
|
12
|
+
|
13
|
+
Scenario: With common steps
|
14
|
+
Given I have defined a "Cheezburger can I has" feature
|
15
|
+
And I have an associated step file with some steps in a common module
|
16
|
+
When I run spinach with "--audit"
|
17
|
+
Then I should not see any steps marked as missing
|
18
|
+
|
19
|
+
Scenario: Steps not marked unused if they're in common modules
|
20
|
+
Given I have defined a "Cheezburger can I has" feature
|
21
|
+
And I have defined an "Awesome new feature" feature
|
22
|
+
And I have associated step files with common steps that are all used somewhere
|
23
|
+
When I run spinach with "--audit"
|
24
|
+
Then I should not see any steps marked as unused
|
25
|
+
|
26
|
+
Scenario: Common steps are reported as missing if not used by any feature
|
27
|
+
Given I have defined a "Cheezburger can I has" feature
|
28
|
+
And I have defined an "Awesome new feature" feature
|
29
|
+
And I have step files for both with common steps, but one common step is not used by either
|
30
|
+
When I run spinach with "--audit"
|
31
|
+
Then I should be told the extra step is unused
|
32
|
+
But I should not be told the other common steps are unused
|
33
|
+
|
34
|
+
Scenario: Tells the user to generate if step file missing
|
35
|
+
Given I have defined a "Cheezburger can I has" feature
|
36
|
+
And I have not created an associated step file
|
37
|
+
When I run spinach with "--audit"
|
38
|
+
Then I should be told to run "--generate"
|
39
|
+
|
40
|
+
Scenario: Steps still marked unused if they appear in the wrong file
|
41
|
+
Given I have defined a "Cheezburger can I has" feature
|
42
|
+
And I have defined an "Awesome new feature" feature
|
43
|
+
And I have created a step file for each with a step from one feature pasted into the other's file
|
44
|
+
When I run spinach with "--audit"
|
45
|
+
Then I should be told that step is unused
|
46
|
+
|
47
|
+
Scenario: Reports a clean audit if no steps are missing
|
48
|
+
Given I have defined a "Cheezburger can I has" feature
|
49
|
+
And I have defined an "Awesome new feature" feature
|
50
|
+
And I have complete step files for both
|
51
|
+
When I run spinach with "--audit"
|
52
|
+
Then I should be told this was a clean audit
|
53
|
+
|
54
|
+
Scenario: Should not report a step as missing more than once
|
55
|
+
Given I have defined an "Exciting feature" feature with reused steps
|
56
|
+
And I have created a step file without those reused steps
|
57
|
+
When I run spinach with "--audit"
|
58
|
+
Then I should see the missing steps reported only once
|
59
|
+
|
@@ -0,0 +1,324 @@
|
|
1
|
+
class Spinach::Features::StepAuditing < Spinach::FeatureSteps
|
2
|
+
|
3
|
+
include Integration::SpinachRunner
|
4
|
+
step 'I have defined a "Cheezburger can I has" feature' do
|
5
|
+
write_file('features/cheezburger_can_i_has.feature', """
|
6
|
+
Feature: Cheezburger can I has
|
7
|
+
Scenario: Some Lulz
|
8
|
+
Given I haz a sad
|
9
|
+
When I get some lulz
|
10
|
+
Then I haz a happy
|
11
|
+
Scenario: Cannot haz
|
12
|
+
Given I wantz cheezburger
|
13
|
+
When I ask can haz
|
14
|
+
Then I cannot haz
|
15
|
+
""")
|
16
|
+
end
|
17
|
+
|
18
|
+
step 'I have an associated step file with missing steps and obsolete steps' do
|
19
|
+
write_file('features/steps/cheezburger_can_i_has.rb', """
|
20
|
+
class Spinach::Features::CheezburgerCanIHas < Spinach::FeatureSteps
|
21
|
+
step 'I haz a sad' do
|
22
|
+
pending 'step not implemented'
|
23
|
+
end
|
24
|
+
step 'I get some roxxorz' do
|
25
|
+
pending 'step not implemented'
|
26
|
+
end
|
27
|
+
step 'I haz a happy' do
|
28
|
+
pending 'step not implemented'
|
29
|
+
end
|
30
|
+
step 'I ask can haz' do
|
31
|
+
pending 'step not implemented'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
""")
|
35
|
+
end
|
36
|
+
|
37
|
+
step 'I run spinach with "--audit"' do
|
38
|
+
run_feature 'features', append: '--audit'
|
39
|
+
end
|
40
|
+
|
41
|
+
step 'I should see a list of unused steps' do
|
42
|
+
@stdout.must_match(/Unused step: .*cheezburger_can_i_has.rb:6 'I get some roxxorz'/)
|
43
|
+
end
|
44
|
+
|
45
|
+
step 'I should see the code to paste for missing steps' do
|
46
|
+
@stdout.must_match("Missing steps")
|
47
|
+
@stdout.must_match("step 'I get some lulz' do")
|
48
|
+
@stdout.must_match("step 'I cannot haz' do")
|
49
|
+
end
|
50
|
+
|
51
|
+
step 'I have an associated step file with some steps in a common module' do
|
52
|
+
write_file('features/steps/cheezburger_can_i_has.rb', """
|
53
|
+
class Spinach::Features::CheezburgerCanIHas < Spinach::FeatureSteps
|
54
|
+
include HappySad
|
55
|
+
step 'I get some roxxorz' do
|
56
|
+
pending 'step not implemented'
|
57
|
+
end
|
58
|
+
step 'I ask can haz' do
|
59
|
+
pending 'step not implemented'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
""")
|
63
|
+
write_file('features/steps/happy_sad.rb', """
|
64
|
+
module HappySad
|
65
|
+
include Spinach::DSL
|
66
|
+
step 'I haz a sad' do
|
67
|
+
pending 'step not implemented'
|
68
|
+
end
|
69
|
+
step 'I haz a happy' do
|
70
|
+
pending 'step not implemented'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
""")
|
74
|
+
end
|
75
|
+
|
76
|
+
step 'I should not see any steps marked as missing' do
|
77
|
+
@stdout.wont_match("Missing steps")
|
78
|
+
end
|
79
|
+
|
80
|
+
step 'I should not see any steps marked as unused' do
|
81
|
+
@stdout.wont_match("Unused step")
|
82
|
+
end
|
83
|
+
|
84
|
+
step 'I have defined an "Awesome new feature" feature' do
|
85
|
+
write_file('features/awesome_new_feature.feature', """
|
86
|
+
Feature: Awesome new feature
|
87
|
+
Scenario: Awesomeness
|
88
|
+
Given I am awesome
|
89
|
+
When I do anything
|
90
|
+
Then people will cheer
|
91
|
+
""")
|
92
|
+
end
|
93
|
+
|
94
|
+
step 'I have associated step files with common steps that are all used somewhere' do
|
95
|
+
write_file('features/steps/cheezburger_can_i_has.rb', """
|
96
|
+
class Spinach::Features::CheezburgerCanIHas < Spinach::FeatureSteps
|
97
|
+
include Awesome
|
98
|
+
step 'I haz a sad' do
|
99
|
+
pending 'step not implemented'
|
100
|
+
end
|
101
|
+
step 'I get some lulz' do
|
102
|
+
pending 'step not implemented'
|
103
|
+
end
|
104
|
+
step 'I wantz cheezburger' do
|
105
|
+
pending 'step not implemented'
|
106
|
+
end
|
107
|
+
step 'I ask can haz' do
|
108
|
+
pending 'step not implemented'
|
109
|
+
end
|
110
|
+
step 'I cannot haz' do
|
111
|
+
pending 'step not implemented'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
""")
|
115
|
+
write_file('features/steps/awesome_new_feature.rb', """
|
116
|
+
class Spinach::Features::AwesomeNewFeature < Spinach::FeatureSteps
|
117
|
+
include Awesome
|
118
|
+
step 'I do anything' do
|
119
|
+
pending 'step not implemented'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
""")
|
123
|
+
write_file('features/steps/awesome.rb', """
|
124
|
+
module Awesome
|
125
|
+
include Spinach::DSL
|
126
|
+
step 'I am awesome' do
|
127
|
+
pending 'step not implemented'
|
128
|
+
end
|
129
|
+
step 'people will cheer' do
|
130
|
+
pending 'step not implemented'
|
131
|
+
end
|
132
|
+
step 'I haz a happy' do
|
133
|
+
pending 'step not implemented'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
""")
|
137
|
+
end
|
138
|
+
|
139
|
+
step 'I have not created an associated step file' do
|
140
|
+
# Do nothing
|
141
|
+
end
|
142
|
+
|
143
|
+
step 'I should be told to run "--generate"' do
|
144
|
+
@stdout.must_match("Step file missing: please run --generate first!")
|
145
|
+
end
|
146
|
+
|
147
|
+
step 'I have created a step file for each with a step from one feature pasted into the other\'s file' do
|
148
|
+
write_file('features/steps/cheezburger_can_i_has.rb', """
|
149
|
+
class Spinach::Features::CheezburgerCanIHas < Spinach::FeatureSteps
|
150
|
+
step 'I haz a sad' do
|
151
|
+
pending 'step not implemented'
|
152
|
+
end
|
153
|
+
step 'I get some lulz' do
|
154
|
+
pending 'step not implemented'
|
155
|
+
end
|
156
|
+
step 'I haz a happy' do
|
157
|
+
pending 'step not implemented'
|
158
|
+
end
|
159
|
+
step 'I wantz cheezburger' do
|
160
|
+
pending 'step not implemented'
|
161
|
+
end
|
162
|
+
step 'I ask can haz' do
|
163
|
+
pending 'step not implemented'
|
164
|
+
end
|
165
|
+
step 'I cannot haz' do
|
166
|
+
pending 'step not implemented'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
""")
|
170
|
+
write_file('features/steps/awesome_new_feature.rb', """
|
171
|
+
class Spinach::Features::AwesomeNewFeature < Spinach::FeatureSteps
|
172
|
+
step 'I am awesome' do
|
173
|
+
pending 'step not implemented'
|
174
|
+
end
|
175
|
+
step 'I do anything' do
|
176
|
+
pending 'step not implemented'
|
177
|
+
end
|
178
|
+
step 'people will cheer' do
|
179
|
+
pending 'step not implemented'
|
180
|
+
end
|
181
|
+
step 'I haz a happy' do
|
182
|
+
pending 'step not implemented'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
""")
|
186
|
+
end
|
187
|
+
|
188
|
+
step 'I should be told that step is unused' do
|
189
|
+
@stdout.must_match(/Unused step: .*awesome_new_feature.rb:12 'I haz a happy'/)
|
190
|
+
end
|
191
|
+
|
192
|
+
step 'I have complete step files for both' do
|
193
|
+
write_file('features/steps/cheezburger_can_i_has.rb', """
|
194
|
+
class Spinach::Features::CheezburgerCanIHas < Spinach::FeatureSteps
|
195
|
+
step 'I haz a sad' do
|
196
|
+
pending 'step not implemented'
|
197
|
+
end
|
198
|
+
step 'I get some lulz' do
|
199
|
+
pending 'step not implemented'
|
200
|
+
end
|
201
|
+
step 'I haz a happy' do
|
202
|
+
pending 'step not implemented'
|
203
|
+
end
|
204
|
+
step 'I wantz cheezburger' do
|
205
|
+
pending 'step not implemented'
|
206
|
+
end
|
207
|
+
step 'I ask can haz' do
|
208
|
+
pending 'step not implemented'
|
209
|
+
end
|
210
|
+
step 'I cannot haz' do
|
211
|
+
pending 'step not implemented'
|
212
|
+
end
|
213
|
+
end
|
214
|
+
""")
|
215
|
+
write_file('features/steps/awesome_new_feature.rb', """
|
216
|
+
class Spinach::Features::AwesomeNewFeature < Spinach::FeatureSteps
|
217
|
+
step 'I am awesome' do
|
218
|
+
pending 'step not implemented'
|
219
|
+
end
|
220
|
+
step 'I do anything' do
|
221
|
+
pending 'step not implemented'
|
222
|
+
end
|
223
|
+
step 'people will cheer' do
|
224
|
+
pending 'step not implemented'
|
225
|
+
end
|
226
|
+
end
|
227
|
+
""")
|
228
|
+
end
|
229
|
+
|
230
|
+
step 'I should be told this was a clean audit' do
|
231
|
+
@stdout.must_match('Audit clean - no missing steps.')
|
232
|
+
end
|
233
|
+
|
234
|
+
step 'I have defined an "Exciting feature" feature with reused steps' do
|
235
|
+
write_file('features/exciting_feature.feature', """
|
236
|
+
Feature: Exciting feature
|
237
|
+
Scenario: One
|
238
|
+
Given I exist
|
239
|
+
When I do nothing
|
240
|
+
Then I should still exist
|
241
|
+
Scenario: Two
|
242
|
+
Given I exist
|
243
|
+
When I jump up and down
|
244
|
+
Then I should still exist
|
245
|
+
""")
|
246
|
+
end
|
247
|
+
|
248
|
+
step 'I have created a step file without those reused steps' do
|
249
|
+
write_file('features/steps/exciting_feature.rb', """
|
250
|
+
class Spinach::Features::ExcitingFeature < Spinach::FeatureSteps
|
251
|
+
step 'I do nothing' do
|
252
|
+
pending 'step not implemented'
|
253
|
+
end
|
254
|
+
end
|
255
|
+
""")
|
256
|
+
end
|
257
|
+
|
258
|
+
step 'I should see the missing steps reported only once' do
|
259
|
+
@stdout.scan('I exist').count.must_equal 1
|
260
|
+
@stdout.scan('I should still exist').count.must_equal 1
|
261
|
+
end
|
262
|
+
|
263
|
+
step 'I have step files for both with common steps, but one common step is not used by either' do
|
264
|
+
write_file('features/steps/cheezburger_can_i_has.rb', """
|
265
|
+
class Spinach::Features::CheezburgerCanIHas < Spinach::FeatureSteps
|
266
|
+
include Awesome
|
267
|
+
step 'I haz a sad' do
|
268
|
+
pending 'step not implemented'
|
269
|
+
end
|
270
|
+
step 'I get some lulz' do
|
271
|
+
pending 'step not implemented'
|
272
|
+
end
|
273
|
+
step 'I wantz cheezburger' do
|
274
|
+
pending 'step not implemented'
|
275
|
+
end
|
276
|
+
step 'I ask can haz' do
|
277
|
+
pending 'step not implemented'
|
278
|
+
end
|
279
|
+
step 'I cannot haz' do
|
280
|
+
pending 'step not implemented'
|
281
|
+
end
|
282
|
+
end
|
283
|
+
""")
|
284
|
+
write_file('features/steps/awesome_new_feature.rb', """
|
285
|
+
class Spinach::Features::AwesomeNewFeature < Spinach::FeatureSteps
|
286
|
+
include Awesome
|
287
|
+
step 'I am awesome' do
|
288
|
+
pending 'step not implemented'
|
289
|
+
end
|
290
|
+
step 'people will cheer' do
|
291
|
+
pending 'step not implemented';
|
292
|
+
end
|
293
|
+
end
|
294
|
+
""")
|
295
|
+
write_file('features/steps/awesome.rb', """
|
296
|
+
module Awesome
|
297
|
+
include Spinach::DSL
|
298
|
+
step 'I do anything' do
|
299
|
+
pending 'step not implemented'
|
300
|
+
end
|
301
|
+
step 'I haz a happy' do
|
302
|
+
pending 'step not implemented'
|
303
|
+
end
|
304
|
+
step 'I enter the void' do
|
305
|
+
pending 'step not implemented'
|
306
|
+
end
|
307
|
+
end
|
308
|
+
""")
|
309
|
+
end
|
310
|
+
|
311
|
+
step 'I should be told the extra step is unused' do
|
312
|
+
@stdout.must_match(/Unused step: .*awesome.rb:10 'I enter the void'/)
|
313
|
+
end
|
314
|
+
|
315
|
+
step 'I should not be told the other common steps are unused' do
|
316
|
+
@stdout.wont_match('I do anything')
|
317
|
+
@stdout.wont_match('I haz a happy')
|
318
|
+
end
|
319
|
+
|
320
|
+
step 'bad' do
|
321
|
+
pending 'hello'
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
data/features/support/env.rb
CHANGED
data/lib/spinach.rb
CHANGED
@@ -11,6 +11,7 @@ require_relative 'spinach/feature_steps'
|
|
11
11
|
require_relative 'spinach/reporter'
|
12
12
|
require_relative 'spinach/cli'
|
13
13
|
require_relative 'spinach/generators'
|
14
|
+
require_relative 'spinach/auditor'
|
14
15
|
|
15
16
|
require_relative 'spinach/background'
|
16
17
|
require_relative 'spinach/feature'
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Spinach
|
4
|
+
# The auditor audits steps and determines if any are missing or obsolete.
|
5
|
+
#
|
6
|
+
# It is a subclass of Runner because it uses many of the Runner's features
|
7
|
+
# when auditing.
|
8
|
+
#
|
9
|
+
class Auditor < Runner
|
10
|
+
attr_accessor :unused_steps, :used_steps
|
11
|
+
|
12
|
+
def initialize(filenames)
|
13
|
+
super(filenames)
|
14
|
+
@unused_steps = {}
|
15
|
+
@used_steps = Set.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# audits features
|
19
|
+
# @files [Array]
|
20
|
+
# filenames to audit
|
21
|
+
def run
|
22
|
+
require_dependencies
|
23
|
+
|
24
|
+
# Find any missing steps in each file, and keep track of unused steps
|
25
|
+
clean = true
|
26
|
+
filenames.each do |file|
|
27
|
+
result = audit_file(file)
|
28
|
+
clean &&= result # set to false if any result is false
|
29
|
+
end
|
30
|
+
|
31
|
+
# At the end, report any unused steps
|
32
|
+
report_unused_steps
|
33
|
+
|
34
|
+
# If the audit was clean, make sure the user knows
|
35
|
+
puts "\nAudit clean - no missing steps.".colorize(:light_green) if clean
|
36
|
+
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def audit_file(file)
|
43
|
+
puts "\nAuditing: ".colorize(:magenta) + file.colorize(:light_magenta)
|
44
|
+
|
45
|
+
# Find the feature definition and its associated step defs class
|
46
|
+
feature, step_defs_class = get_feature_and_defs(file)
|
47
|
+
return step_file_missing if step_defs_class.nil?
|
48
|
+
step_defs = step_defs_class.new
|
49
|
+
unused_step_names = step_names_for_class(step_defs_class)
|
50
|
+
|
51
|
+
missing_steps = {}
|
52
|
+
|
53
|
+
feature.each_step do |step|
|
54
|
+
# Audit the step
|
55
|
+
missing_steps[step.name] = step if step_missing?(step, step_defs)
|
56
|
+
# Having audited the step, remove it from the list of unused steps
|
57
|
+
unused_step_names.delete step.name
|
58
|
+
end
|
59
|
+
|
60
|
+
# If there are any steps left at the end, let's mark them as unused
|
61
|
+
store_unused_steps(unused_step_names, step_defs)
|
62
|
+
|
63
|
+
# And then generate a report of missing steps
|
64
|
+
return true if missing_steps.empty?
|
65
|
+
report_missing_steps(missing_steps.values)
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
# Get the feature and its definitions from the appropriate files
|
70
|
+
def get_feature_and_defs(file)
|
71
|
+
feature = Parser.open_file(file).parse
|
72
|
+
[feature, Spinach.find_step_definitions(feature.name)]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Process a step from the feature file using the given step_defs.
|
76
|
+
# If it is missing, return true. Otherwise, add it to the used_steps for
|
77
|
+
# the report at the end and return false.
|
78
|
+
def step_missing?(step, step_defs)
|
79
|
+
method_name = Spinach::Support.underscore step.name
|
80
|
+
return true unless step_defs.respond_to?(method_name)
|
81
|
+
# Remember that we have used this step
|
82
|
+
used_steps << step_defs.step_location_for(step.name).join(':')
|
83
|
+
false
|
84
|
+
end
|
85
|
+
|
86
|
+
# Store any unused step names for the report at the end of the audit
|
87
|
+
def store_unused_steps(names, step_defs)
|
88
|
+
names.each do |name|
|
89
|
+
location = step_defs.step_location_for(name).join(':')
|
90
|
+
unused_steps[location] = name
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Print a message alerting the user that there is no step file for this
|
95
|
+
# feature
|
96
|
+
def step_file_missing
|
97
|
+
puts 'Step file missing: please run --generate first!'
|
98
|
+
.colorize(:light_red)
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
102
|
+
# Get the step names for all steps in the given class, including those in
|
103
|
+
# common modules
|
104
|
+
def step_names_for_class(klass)
|
105
|
+
klass.ancestors.map { |a| a.respond_to?(:steps) ? a.steps : [] }.flatten
|
106
|
+
end
|
107
|
+
|
108
|
+
# Produce a report of unused steps that were not found anywhere in the audit
|
109
|
+
def report_unused_steps
|
110
|
+
# Remove any unused_steps that were in common modules and used
|
111
|
+
# in another feature
|
112
|
+
used_steps.each { |location| unused_steps.delete location }
|
113
|
+
unused_steps.each do |location, name|
|
114
|
+
puts "\n" + "Unused step: #{location} ".colorize(:yellow) +
|
115
|
+
"'#{name}'".colorize(:light_yellow)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Print a report of the missing step objects provided
|
120
|
+
def report_missing_steps(steps)
|
121
|
+
puts "\nMissing steps:".colorize(:light_cyan)
|
122
|
+
steps.each do |step|
|
123
|
+
puts Generators::StepGenerator.new(step).generate.gsub(/^/, ' ')
|
124
|
+
.colorize(:cyan)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/spinach/cli.rb
CHANGED
@@ -24,6 +24,8 @@ module Spinach
|
|
24
24
|
|
25
25
|
if Spinach.config.generate
|
26
26
|
Spinach::Generators.run(feature_files)
|
27
|
+
elsif Spinach.config.audit
|
28
|
+
Spinach::Auditor.new(feature_files).run
|
27
29
|
else
|
28
30
|
Spinach::Runner.new(feature_files).run
|
29
31
|
end
|
@@ -132,6 +134,12 @@ module Spinach
|
|
132
134
|
'Terminate the suite run on the first failure') do |class_name|
|
133
135
|
config[:fail_fast] = true
|
134
136
|
end
|
137
|
+
|
138
|
+
opts.on('-a', '--audit',
|
139
|
+
"Audit steps instead of running them, outputting missing \
|
140
|
+
and obsolete steps") do
|
141
|
+
config[:audit] = true
|
142
|
+
end
|
135
143
|
end.parse!(@args)
|
136
144
|
|
137
145
|
Spinach.config.parse_from_file
|
data/lib/spinach/config.rb
CHANGED
@@ -33,7 +33,8 @@ module Spinach
|
|
33
33
|
:save_and_open_page_on_failure,
|
34
34
|
:reporter_class,
|
35
35
|
:reporter_options,
|
36
|
-
:fail_fast
|
36
|
+
:fail_fast,
|
37
|
+
:audit
|
37
38
|
|
38
39
|
|
39
40
|
# The "features path" holds the place where your features will be
|
@@ -143,6 +144,16 @@ module Spinach
|
|
143
144
|
@fail_fast
|
144
145
|
end
|
145
146
|
|
147
|
+
# "audit" enables step auditing mode
|
148
|
+
#
|
149
|
+
# @return [true/false]
|
150
|
+
# The audit flag.
|
151
|
+
#
|
152
|
+
# @api public
|
153
|
+
def audit
|
154
|
+
@audit || false
|
155
|
+
end
|
156
|
+
|
146
157
|
# It allows you to set a config file to parse for all the other options to be set
|
147
158
|
#
|
148
159
|
# @return [String]
|
data/lib/spinach/dsl.rb
CHANGED
@@ -56,6 +56,7 @@ module Spinach
|
|
56
56
|
end
|
57
57
|
|
58
58
|
define_method(Spinach::Support.underscore(step), &method_body)
|
59
|
+
steps << step
|
59
60
|
end
|
60
61
|
|
61
62
|
alias_method :Given, :step
|
@@ -142,6 +143,11 @@ module Spinach
|
|
142
143
|
@feature_name = name
|
143
144
|
end
|
144
145
|
|
146
|
+
# Get the list of step names in this class
|
147
|
+
def steps
|
148
|
+
@steps ||= []
|
149
|
+
end
|
150
|
+
|
145
151
|
private
|
146
152
|
|
147
153
|
def before_or_after_private_method_name(location)
|
data/lib/spinach/feature.rb
CHANGED
@@ -86,7 +86,7 @@ module Spinach
|
|
86
86
|
e.step = step
|
87
87
|
@has_pending_step = true
|
88
88
|
Spinach.hooks.run_on_pending_step step, e
|
89
|
-
rescue
|
89
|
+
rescue StandardError => e
|
90
90
|
@exception = e
|
91
91
|
Spinach.hooks.run_on_error_step step, @exception, step_location, step_definitions
|
92
92
|
end
|
data/lib/spinach/version.rb
CHANGED
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.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep Jaume Rey
|
@@ -11,174 +11,174 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2017-01-16 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: gherkin-ruby
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
19
19
|
requirements:
|
20
|
-
- -
|
20
|
+
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 0.3.2
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 0.3.2
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: colorize
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
|
-
- -
|
34
|
+
- - ">="
|
35
35
|
- !ruby/object:Gem::Version
|
36
36
|
version: '0'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
|
-
- -
|
41
|
+
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: '0'
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
45
|
name: json
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
|
-
- -
|
48
|
+
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
50
|
version: '0'
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
|
-
- -
|
55
|
+
- - ">="
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: '0'
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rake
|
60
60
|
requirement: !ruby/object:Gem::Requirement
|
61
61
|
requirements:
|
62
|
-
- -
|
62
|
+
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
64
|
version: '0'
|
65
65
|
type: :development
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
|
-
- -
|
69
|
+
- - ">="
|
70
70
|
- !ruby/object:Gem::Version
|
71
71
|
version: '0'
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: mocha
|
74
74
|
requirement: !ruby/object:Gem::Requirement
|
75
75
|
requirements:
|
76
|
-
- - ~>
|
76
|
+
- - "~>"
|
77
77
|
- !ruby/object:Gem::Version
|
78
78
|
version: '1.0'
|
79
79
|
type: :development
|
80
80
|
prerelease: false
|
81
81
|
version_requirements: !ruby/object:Gem::Requirement
|
82
82
|
requirements:
|
83
|
-
- - ~>
|
83
|
+
- - "~>"
|
84
84
|
- !ruby/object:Gem::Version
|
85
85
|
version: '1.0'
|
86
86
|
- !ruby/object:Gem::Dependency
|
87
87
|
name: sinatra
|
88
88
|
requirement: !ruby/object:Gem::Requirement
|
89
89
|
requirements:
|
90
|
-
- -
|
90
|
+
- - ">="
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '0'
|
93
93
|
type: :development
|
94
94
|
prerelease: false
|
95
95
|
version_requirements: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
|
-
- -
|
97
|
+
- - ">="
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '0'
|
100
100
|
- !ruby/object:Gem::Dependency
|
101
101
|
name: capybara
|
102
102
|
requirement: !ruby/object:Gem::Requirement
|
103
103
|
requirements:
|
104
|
-
- -
|
104
|
+
- - ">="
|
105
105
|
- !ruby/object:Gem::Version
|
106
106
|
version: '0'
|
107
107
|
type: :development
|
108
108
|
prerelease: false
|
109
109
|
version_requirements: !ruby/object:Gem::Requirement
|
110
110
|
requirements:
|
111
|
-
- -
|
111
|
+
- - ">="
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: '0'
|
114
114
|
- !ruby/object:Gem::Dependency
|
115
115
|
name: pry
|
116
116
|
requirement: !ruby/object:Gem::Requirement
|
117
117
|
requirements:
|
118
|
-
- -
|
118
|
+
- - ">="
|
119
119
|
- !ruby/object:Gem::Version
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
123
|
version_requirements: !ruby/object:Gem::Requirement
|
124
124
|
requirements:
|
125
|
-
- -
|
125
|
+
- - ">="
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: '0'
|
128
128
|
- !ruby/object:Gem::Dependency
|
129
129
|
name: simplecov
|
130
130
|
requirement: !ruby/object:Gem::Requirement
|
131
131
|
requirements:
|
132
|
-
- -
|
132
|
+
- - ">="
|
133
133
|
- !ruby/object:Gem::Version
|
134
134
|
version: '0'
|
135
135
|
type: :development
|
136
136
|
prerelease: false
|
137
137
|
version_requirements: !ruby/object:Gem::Requirement
|
138
138
|
requirements:
|
139
|
-
- -
|
139
|
+
- - ">="
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
- !ruby/object:Gem::Dependency
|
143
143
|
name: rspec
|
144
144
|
requirement: !ruby/object:Gem::Requirement
|
145
145
|
requirements:
|
146
|
-
- -
|
146
|
+
- - ">="
|
147
147
|
- !ruby/object:Gem::Version
|
148
148
|
version: '0'
|
149
149
|
type: :development
|
150
150
|
prerelease: false
|
151
151
|
version_requirements: !ruby/object:Gem::Requirement
|
152
152
|
requirements:
|
153
|
-
- -
|
153
|
+
- - ">="
|
154
154
|
- !ruby/object:Gem::Version
|
155
155
|
version: '0'
|
156
156
|
- !ruby/object:Gem::Dependency
|
157
157
|
name: minitest
|
158
158
|
requirement: !ruby/object:Gem::Requirement
|
159
159
|
requirements:
|
160
|
-
- - <
|
160
|
+
- - "<"
|
161
161
|
- !ruby/object:Gem::Version
|
162
162
|
version: '5.0'
|
163
163
|
type: :development
|
164
164
|
prerelease: false
|
165
165
|
version_requirements: !ruby/object:Gem::Requirement
|
166
166
|
requirements:
|
167
|
-
- - <
|
167
|
+
- - "<"
|
168
168
|
- !ruby/object:Gem::Version
|
169
169
|
version: '5.0'
|
170
170
|
- !ruby/object:Gem::Dependency
|
171
171
|
name: fakefs
|
172
172
|
requirement: !ruby/object:Gem::Requirement
|
173
173
|
requirements:
|
174
|
-
- -
|
174
|
+
- - ">="
|
175
175
|
- !ruby/object:Gem::Version
|
176
176
|
version: 0.5.2
|
177
177
|
type: :development
|
178
178
|
prerelease: false
|
179
179
|
version_requirements: !ruby/object:Gem::Requirement
|
180
180
|
requirements:
|
181
|
-
- -
|
181
|
+
- - ">="
|
182
182
|
- !ruby/object:Gem::Version
|
183
183
|
version: 0.5.2
|
184
184
|
description: Spinach is a BDD framework on top of gherkin
|
@@ -193,11 +193,11 @@ executables:
|
|
193
193
|
extensions: []
|
194
194
|
extra_rdoc_files: []
|
195
195
|
files:
|
196
|
-
- .document
|
197
|
-
- .gitignore
|
198
|
-
- .ruby-gemset
|
199
|
-
- .ruby-version
|
200
|
-
- .travis.yml
|
196
|
+
- ".document"
|
197
|
+
- ".gitignore"
|
198
|
+
- ".ruby-gemset"
|
199
|
+
- ".ruby-version"
|
200
|
+
- ".travis.yml"
|
201
201
|
- CHANGELOG.md
|
202
202
|
- Gemfile
|
203
203
|
- Guardfile
|
@@ -220,6 +220,7 @@ files:
|
|
220
220
|
- features/reporting/show_step_source_location.feature
|
221
221
|
- features/reporting/undefined_feature_reporting.feature
|
222
222
|
- features/rspec_compatibility.feature
|
223
|
+
- features/step_auditing.feature
|
223
224
|
- features/steps/automatic_feature_generation.rb
|
224
225
|
- features/steps/background.rb
|
225
226
|
- features/steps/before_and_after_hooks.rb
|
@@ -235,12 +236,14 @@ files:
|
|
235
236
|
- features/steps/reporting/undefined_feature_reporting.rb
|
236
237
|
- features/steps/reporting/use_customized_reporter.rb
|
237
238
|
- features/steps/rspec_compatibility.rb
|
239
|
+
- features/steps/step_auditing.rb
|
238
240
|
- features/support/env.rb
|
239
241
|
- features/support/error_reporting.rb
|
240
242
|
- features/support/feature_generator.rb
|
241
243
|
- features/support/filesystem.rb
|
242
244
|
- features/support/spinach_runner.rb
|
243
245
|
- lib/spinach.rb
|
246
|
+
- lib/spinach/auditor.rb
|
244
247
|
- lib/spinach/background.rb
|
245
248
|
- lib/spinach/capybara.rb
|
246
249
|
- lib/spinach/cli.rb
|
@@ -312,17 +315,17 @@ require_paths:
|
|
312
315
|
- lib
|
313
316
|
required_ruby_version: !ruby/object:Gem::Requirement
|
314
317
|
requirements:
|
315
|
-
- -
|
318
|
+
- - ">="
|
316
319
|
- !ruby/object:Gem::Version
|
317
320
|
version: '0'
|
318
321
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
319
322
|
requirements:
|
320
|
-
- -
|
323
|
+
- - ">="
|
321
324
|
- !ruby/object:Gem::Version
|
322
325
|
version: '0'
|
323
326
|
requirements: []
|
324
327
|
rubyforge_project:
|
325
|
-
rubygems_version: 2.
|
328
|
+
rubygems_version: 2.5.1
|
326
329
|
signing_key:
|
327
330
|
specification_version: 4
|
328
331
|
summary: Spinach is a BDD framework on top of gherkin
|
@@ -342,6 +345,7 @@ test_files:
|
|
342
345
|
- features/reporting/show_step_source_location.feature
|
343
346
|
- features/reporting/undefined_feature_reporting.feature
|
344
347
|
- features/rspec_compatibility.feature
|
348
|
+
- features/step_auditing.feature
|
345
349
|
- features/steps/automatic_feature_generation.rb
|
346
350
|
- features/steps/background.rb
|
347
351
|
- features/steps/before_and_after_hooks.rb
|
@@ -357,6 +361,7 @@ test_files:
|
|
357
361
|
- features/steps/reporting/undefined_feature_reporting.rb
|
358
362
|
- features/steps/reporting/use_customized_reporter.rb
|
359
363
|
- features/steps/rspec_compatibility.rb
|
364
|
+
- features/steps/step_auditing.rb
|
360
365
|
- features/support/env.rb
|
361
366
|
- features/support/error_reporting.rb
|
362
367
|
- features/support/feature_generator.rb
|
@@ -391,4 +396,3 @@ test_files:
|
|
391
396
|
- test/spinach_test.rb
|
392
397
|
- test/support/filesystem.rb
|
393
398
|
- test/test_helper.rb
|
394
|
-
has_rdoc:
|