cellophane 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.cellophane.yaml.sample +7 -0
- data/README.textile +70 -5
- data/VERSION +1 -1
- data/cellophane.gemspec +2 -2
- data/features/step_definitions.feature +102 -0
- data/lib/cellophane/main.rb +45 -7
- data/lib/cellophane/options.rb +21 -1
- metadata +3 -3
data/.cellophane.yaml.sample
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
cuke_command: cucumber
|
2
|
+
# cuke_command: bundle exec cucumber
|
3
|
+
# cuke_command: script/cucumber
|
4
|
+
# cuke_command: cuke # shell alias
|
1
5
|
cucumber: --format progress --no-profile
|
2
6
|
feature_path: cuke/features
|
3
7
|
step_path: cuke/steps
|
@@ -5,3 +9,6 @@ step_path: cuke/steps
|
|
5
9
|
# nested_in: step_definitions
|
6
10
|
requires:
|
7
11
|
- cuke/support
|
12
|
+
- cuke/steps/shared
|
13
|
+
shared: false # turn off auto-loading of step files named shared_steps.rb
|
14
|
+
# shared: global # auto-load shared steps in files named global_steps.rb
|
data/README.textile
CHANGED
@@ -57,11 +57,11 @@ Location of your step definitions. Defaults to @features/step_definitions@. It c
|
|
57
57
|
# nested in each feature directory
|
58
58
|
|
59
59
|
*Examples*
|
60
|
-
|
61
|
-
|
60
|
+
<pre><code>
|
61
|
+
step_path: cuke/steps
|
62
62
|
step_path:
|
63
63
|
nested_in: step_definition
|
64
|
-
</pre>
|
64
|
+
</code></pre>
|
65
65
|
|
66
66
|
*Notes*
|
67
67
|
Use the first method if your step defitions follow the structure of your features. For example:
|
@@ -110,6 +110,71 @@ my_project
|
|
110
110
|
- etc, etc
|
111
111
|
</pre>
|
112
112
|
|
113
|
+
*Directive*
|
114
|
+
@shared@
|
115
|
+
|
116
|
+
*Explanation*
|
117
|
+
Automatically load steps named shared_steps.rb in all directories that comprise the step path for the current feature file. Defaults to true. This option allows you to share steps among features while keeping them organized according to scope.
|
118
|
+
|
119
|
+
*Examples*
|
120
|
+
@shared: global@ # instead of looking for shared_steps.rb, look for global_steps.rb
|
121
|
+
@shared: false@ # don't automatically require shared steps
|
122
|
+
|
123
|
+
*Notes*
|
124
|
+
Consider the following project structure:
|
125
|
+
|
126
|
+
<pre>
|
127
|
+
my_project
|
128
|
+
- app
|
129
|
+
- config
|
130
|
+
- cuke
|
131
|
+
- features
|
132
|
+
- admin
|
133
|
+
- reports
|
134
|
+
- user_maintenance
|
135
|
+
- user
|
136
|
+
- communication
|
137
|
+
- profile
|
138
|
+
- steps
|
139
|
+
- admin
|
140
|
+
- reports
|
141
|
+
- user_maintenance
|
142
|
+
- user
|
143
|
+
- communication
|
144
|
+
- profile
|
145
|
+
- support
|
146
|
+
- db
|
147
|
+
- lib
|
148
|
+
- etc, etc
|
149
|
+
</pre>
|
150
|
+
|
151
|
+
When you run a feature in @features/admin/reports/weekly.feature@, Cellophane will automatically require shared steps found in the following locations:
|
152
|
+
|
153
|
+
@steps/admin/reports/shared_steps.rb@ # steps specific to admin reports
|
154
|
+
@steps/admin/shared_steps.rb@ # steps specific to admin
|
155
|
+
@steps/shared_steps.rb@ # steps used by the whole application
|
156
|
+
|
157
|
+
If your steps are nested, Cellophane will look for shared steps *only* in the nested step location. For example, if your project looks like
|
158
|
+
|
159
|
+
<pre>
|
160
|
+
my_project
|
161
|
+
- app
|
162
|
+
- config
|
163
|
+
- features
|
164
|
+
- admin
|
165
|
+
- step_definitions
|
166
|
+
- user
|
167
|
+
- step_definitions
|
168
|
+
- visitor
|
169
|
+
- step_definitions
|
170
|
+
- support
|
171
|
+
- db
|
172
|
+
- lib
|
173
|
+
- etc, etc
|
174
|
+
</pre>
|
175
|
+
|
176
|
+
and you run a feature in @features/admin/email.feature@, Cellophane will look for @features/admin/step_definitions/shared_steps.rb@.
|
177
|
+
|
113
178
|
*Directive*
|
114
179
|
@requires@
|
115
180
|
|
@@ -248,13 +313,13 @@ cellophane -r email
|
|
248
313
|
|
249
314
|
h4. Step Definitions
|
250
315
|
|
251
|
-
Cellophane does assume that your steps are defined in files that follow the naming of your features. For each feature file that is found, Cellophane will look for a step file with the same name and automatically require it. To require shared step definitions, put them in a folder and include that folder in the @requires@ section of @.cellophane.yaml@.
|
316
|
+
Cellophane does assume that your steps are defined in files that follow the naming of your features. For each feature file that is found, Cellophane will look for a step file with the same name and automatically require it. To require shared step definitions, put them in a folder and include that folder in the @requires@ section of @.cellophane.yaml@. Also look into the @shared@ directive of the configuration file, which allows more fine-grained control of shared steps.
|
252
317
|
|
253
318
|
For example, if you have a feature defined in @<feature path>/admin/user/account_maintenance.feature@, Cellophane will automatically require a step definition file located in @<step path>/admin/user/account_maintenance_steps.rb@. Unless you are using nested step definitions in @.cellophane.yaml@ (@step_path: {nested_in: steps }@, in which case Cellophane will automatically require @<feature path>/admin/user/steps/account_maintenance_steps.rb@ if it exists.
|
254
319
|
|
255
320
|
h4. Tags
|
256
321
|
|
257
|
-
You don't need to use @. You can you want, but it's not necessary.
|
322
|
+
You don't need to use @. You can if you want, but it's not necessary.
|
258
323
|
|
259
324
|
Cellophane supports OR, AND, and NOT tags. Examples will probably illustrate better than words.
|
260
325
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/cellophane.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cellophane}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Phillip Koebbe"]
|
12
|
-
s.date = %q{2011-01-
|
12
|
+
s.date = %q{2011-01-12}
|
13
13
|
s.default_executable = %q{cellophane}
|
14
14
|
s.description = %q{Cellophane is a thin wrapper around Cucumber, making it easier to be creative when running features.}
|
15
15
|
s.email = %q{phillip@livingdoor.net}
|
@@ -45,3 +45,105 @@ And a project options file with the following options
|
|
45
45
|
When Cellophane is called with "admin/one"
|
46
46
|
Then the command should include "features/admin/one.feature"
|
47
47
|
And the command should include "-r features/admin/step_definitions/one_steps.rb"
|
48
|
+
|
49
|
+
@4
|
50
|
+
Scenario: Automatically loading shared_steps.rb in simple project
|
51
|
+
|
52
|
+
Given a project directory with the following structure
|
53
|
+
| type | path |
|
54
|
+
| directory | features |
|
55
|
+
| directory | features/step_definitions |
|
56
|
+
| file | features/one.feature |
|
57
|
+
| file | features/two.feature |
|
58
|
+
| file | features/step_definitions/one_steps.rb |
|
59
|
+
| file | features/step_definitions/shared_steps.rb |
|
60
|
+
When Cellophane is called with "one"
|
61
|
+
Then the command should include "features/one.feature"
|
62
|
+
And the command should include "-r features/step_definitions/one_steps.rb"
|
63
|
+
And the command should include "-r features/step_definitions/shared_steps.rb"
|
64
|
+
|
65
|
+
@5
|
66
|
+
Scenario: Automatically loading shared_steps.rb in complex project
|
67
|
+
|
68
|
+
Given a project directory with the following structure
|
69
|
+
| type | path |
|
70
|
+
| directory | features |
|
71
|
+
| directory | features/admin |
|
72
|
+
| directory | features/user |
|
73
|
+
| directory | features/step_definitions |
|
74
|
+
| directory | features/step_definitions/admin |
|
75
|
+
| directory | features/step_definitions/user |
|
76
|
+
| file | features/admin/one.feature |
|
77
|
+
| file | features/admin/two.feature |
|
78
|
+
| file | features/user/one.feature |
|
79
|
+
| file | features/user/two.feature |
|
80
|
+
| file | features/step_definitions/shared_steps.rb |
|
81
|
+
| file | features/step_definitions/admin/one_steps.rb |
|
82
|
+
| file | features/step_definitions/admin/shared_steps.rb |
|
83
|
+
| file | features/step_definitions/user/one_steps.rb |
|
84
|
+
| file | features/step_definitions/user/shared_steps.rb |
|
85
|
+
When Cellophane is called with "admin/one"
|
86
|
+
Then the command should include "features/admin/one.feature"
|
87
|
+
And the command should include "-r features/step_definitions/admin/one_steps.rb"
|
88
|
+
And the command should include "-r features/step_definitions/shared_steps.rb"
|
89
|
+
And the command should include "-r features/step_definitions/admin/shared_steps.rb"
|
90
|
+
And the command should not include "-r features/step_definitions/user/one_steps.rb"
|
91
|
+
And the command should not include "-r features/step_definitions/user/shared_steps.rb"
|
92
|
+
|
93
|
+
@6
|
94
|
+
Scenario: Automatically loading shared_steps.rb when steps are nested
|
95
|
+
|
96
|
+
Given a project directory with the following structure
|
97
|
+
| type | path |
|
98
|
+
| directory | features |
|
99
|
+
| directory | features/admin |
|
100
|
+
| directory | features/admin/step_definitions |
|
101
|
+
| file | features/admin/one.feature |
|
102
|
+
| file | features/admin/two.feature |
|
103
|
+
| file | features/admin/step_definitions/one_steps.rb |
|
104
|
+
| file | features/admin/step_definitions/shared_steps.rb |
|
105
|
+
And a project options file with the following options
|
106
|
+
| option |
|
107
|
+
| step_path: {nested_in: step_definitions} |
|
108
|
+
When Cellophane is called with "admin/one"
|
109
|
+
Then the command should include "features/admin/one.feature"
|
110
|
+
And the command should include "-r features/admin/step_definitions/one_steps.rb"
|
111
|
+
And the command should include "-r features/admin/step_definitions/shared_steps.rb"
|
112
|
+
|
113
|
+
@7
|
114
|
+
Scenario: Automatically loading shared steps in files named differently
|
115
|
+
|
116
|
+
Given a project directory with the following structure
|
117
|
+
| type | path |
|
118
|
+
| directory | features |
|
119
|
+
| directory | features/step_definitions |
|
120
|
+
| file | features/one.feature |
|
121
|
+
| file | features/two.feature |
|
122
|
+
| file | features/step_definitions/one_steps.rb |
|
123
|
+
| file | features/step_definitions/global_steps.rb |
|
124
|
+
And a project options file with the following options
|
125
|
+
| option |
|
126
|
+
| shared: global |
|
127
|
+
When Cellophane is called with "one"
|
128
|
+
Then the command should include "features/one.feature"
|
129
|
+
And the command should include "-r features/step_definitions/one_steps.rb"
|
130
|
+
And the command should include "-r features/step_definitions/global_steps.rb"
|
131
|
+
|
132
|
+
@8
|
133
|
+
Scenario: Turning off automatically loading shared steps
|
134
|
+
|
135
|
+
Given a project directory with the following structure
|
136
|
+
| type | path |
|
137
|
+
| directory | features |
|
138
|
+
| directory | features/step_definitions |
|
139
|
+
| file | features/one.feature |
|
140
|
+
| file | features/two.feature |
|
141
|
+
| file | features/step_definitions/one_steps.rb |
|
142
|
+
| file | features/step_definitions/shared_steps.rb |
|
143
|
+
And a project options file with the following options
|
144
|
+
| option |
|
145
|
+
| shared: false |
|
146
|
+
When Cellophane is called with "one"
|
147
|
+
Then the command should include "features/one.feature"
|
148
|
+
And the command should include "-r features/step_definitions/one_steps.rb"
|
149
|
+
And the command should not include "-r features/step_definitions/shared_steps.rb"
|
data/lib/cellophane/main.rb
CHANGED
@@ -4,7 +4,7 @@ require 'cellophane/options'
|
|
4
4
|
|
5
5
|
module Cellophane
|
6
6
|
|
7
|
-
VERSION = '0.1.
|
7
|
+
VERSION = '0.1.3'
|
8
8
|
PROJECT_OPTIONS_FILE = '.cellophane.yaml'
|
9
9
|
|
10
10
|
class Main
|
@@ -46,9 +46,8 @@ module Cellophane
|
|
46
46
|
@features.each do |file|
|
47
47
|
file_parts = split_feature(file)
|
48
48
|
features << construct_feature_file(file_parts[:path], file_parts[:name])
|
49
|
-
steps
|
49
|
+
steps += search_for_step_files(file_parts[:path], file_parts[:name])
|
50
50
|
end
|
51
|
-
|
52
51
|
else
|
53
52
|
# if there are no features explicitly identified, then cucumber will run all. However,
|
54
53
|
# if we are using non-standard locations for features or step definitions, we must tell
|
@@ -67,11 +66,50 @@ module Cellophane
|
|
67
66
|
"#{@options[:feature_path]}/#{path}/#{file}.feature".gsub('//', '/')
|
68
67
|
end
|
69
68
|
|
70
|
-
def
|
71
|
-
|
69
|
+
def search_for_step_files(path, file)
|
70
|
+
steps = []
|
71
|
+
|
72
|
+
steps_nested = @options[:step_path].is_a?(Hash)
|
73
|
+
nested_path = "#{@options[:feature_path]}/#{path}/#{@options[:step_path][:nested_in]}" if steps_nested
|
74
|
+
non_nested_path = "#{@options[:step_path]}/#{path}" unless steps_nested
|
75
|
+
|
76
|
+
step_path = steps_nested ? nested_path : non_nested_path
|
72
77
|
step_file = "#{step_path}/#{file}_steps.rb".gsub('//', '/')
|
73
|
-
|
74
|
-
|
78
|
+
steps << step_file if File.exist?(step_file)
|
79
|
+
|
80
|
+
# now lets see if we need to load shared step files
|
81
|
+
|
82
|
+
if @options[:shared]
|
83
|
+
if steps_nested
|
84
|
+
step_file = "#{step_path}/#{@options[:shared]}_steps.rb".gsub('//', '/')
|
85
|
+
steps << step_file if File.exist?(step_file)
|
86
|
+
else
|
87
|
+
# don't want to look in the directories that make up the step root
|
88
|
+
step_path.sub!(@options[:step_path_regexp], '')
|
89
|
+
|
90
|
+
# make an array of the parts of the path that remain
|
91
|
+
step_path_parts = step_path.split('/')
|
92
|
+
|
93
|
+
# if there are any unnecessary slashes, step_path_parts will have empty elements...get rid of them
|
94
|
+
step_path_parts.delete_if { |part| (part || '').strip.empty? }
|
95
|
+
|
96
|
+
# for each path, look for a shared step file
|
97
|
+
while step_path_parts.any? do
|
98
|
+
step_file = "#{@options[:step_path]}/#{step_path_parts.join('/')}/#{@options[:shared]}_steps.rb"
|
99
|
+
steps << step_file if File.exist?(step_file)
|
100
|
+
|
101
|
+
# get rid of the last path part
|
102
|
+
step_path_parts.pop
|
103
|
+
end
|
104
|
+
|
105
|
+
# now look in the step path root
|
106
|
+
step_file = "#{@options[:step_path]}/#{@options[:shared]}_steps.rb"
|
107
|
+
steps << step_file if File.exist?(step_file)
|
108
|
+
end # steps are not netsted
|
109
|
+
end # if @options[:shared]
|
110
|
+
|
111
|
+
return steps
|
112
|
+
end # search_for_step_files
|
75
113
|
|
76
114
|
def split_feature(file)
|
77
115
|
name = File.basename(file, '.feature')
|
data/lib/cellophane/options.rb
CHANGED
@@ -70,7 +70,7 @@ module Cellophane
|
|
70
70
|
if File.exist?(Cellophane::PROJECT_OPTIONS_FILE)
|
71
71
|
yaml_options = YAML.load_file(Cellophane::PROJECT_OPTIONS_FILE)
|
72
72
|
|
73
|
-
['
|
73
|
+
['cuke_command', 'cucumber', 'feature_path', 'feature_path_regexp', 'step_path', 'shared', 'requires'].each do |key|
|
74
74
|
project_options[key.to_sym] = yaml_options[key] if yaml_options.has_key?(key)
|
75
75
|
end
|
76
76
|
end
|
@@ -87,6 +87,8 @@ module Cellophane
|
|
87
87
|
:feature_path => 'features',
|
88
88
|
:feature_path_regexp => nil,
|
89
89
|
:step_path => 'features/step_definitions',
|
90
|
+
:step_path_regexp => nil,
|
91
|
+
:shared => 'shared',
|
90
92
|
:requires => []
|
91
93
|
}
|
92
94
|
end
|
@@ -125,6 +127,11 @@ module Cellophane
|
|
125
127
|
# make a regexp out of the features path if there isn't one already. we need to escape slashes so the
|
126
128
|
# regexp can be made
|
127
129
|
tmp_options[:feature_path_regexp] = Regexp.new(tmp_options[:feature_path].gsub('/', '\/')) unless tmp_options[:feature_path_regexp]
|
130
|
+
|
131
|
+
# need to make a regexp out of the step path for use when looking for shared steps
|
132
|
+
if !tmp_options[:step_path].is_a?(Hash)
|
133
|
+
tmp_options[:step_path_regexp] = Regexp.new(tmp_options[:step_path].gsub('/', '\/')) unless tmp_options[:step_path_regexp]
|
134
|
+
end
|
128
135
|
|
129
136
|
# just in case someone sets necessary values to nil, let's go back to defaults
|
130
137
|
tmp_options[:regexp] ||= defaults[:regexp]
|
@@ -133,6 +140,19 @@ module Cellophane
|
|
133
140
|
tmp_options[:requires] ||= defaults[:requires]
|
134
141
|
tmp_options[:cuke_command] ||= defaults[:cuke_command]
|
135
142
|
|
143
|
+
# let's make sure :shared is something we can work with
|
144
|
+
shared = tmp_options[:shared].nil? ? 'shared' : tmp_options[:shared].to_s.strip
|
145
|
+
shared = 'shared' if shared.strip == ''
|
146
|
+
|
147
|
+
if ['true', ''].include?(shared.downcase)
|
148
|
+
shared == 'shared'
|
149
|
+
elsif shared.downcase == 'false'
|
150
|
+
shared = false
|
151
|
+
end
|
152
|
+
# anything else, just leave it as is
|
153
|
+
|
154
|
+
tmp_options[:shared] = shared
|
155
|
+
|
136
156
|
# do what needs to be done on the pattern
|
137
157
|
unless tmp_options[:pattern].nil?
|
138
158
|
tmp_options[:pattern] = tmp_options[:pattern].strip
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 3
|
9
|
+
version: 0.1.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Phillip Koebbe
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-12 00:00:00 -06:00
|
18
18
|
default_executable: cellophane
|
19
19
|
dependencies: []
|
20
20
|
|