cellophane 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
- @step_path: cuke/steps@
61
- <pre>
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.2
1
+ 0.1.3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cellophane}
8
- s.version = "0.1.2"
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-11}
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"
@@ -4,7 +4,7 @@ require 'cellophane/options'
4
4
 
5
5
  module Cellophane
6
6
 
7
- VERSION = '0.1.2'
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 << construct_step_file(file_parts[:path], file_parts[:name])
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 construct_step_file(path, file)
71
- step_path = @options[:step_path].is_a?(Hash) ? "#{@options[:feature_path]}/#{path}/#{@options[:step_path][:nested_in]}" : "#{@options[:step_path]}/#{path}"
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
- return File.exist?(step_file) ? step_file : nil
74
- end
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')
@@ -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
- ['cucumber', 'cuke_command', 'feature_path', 'feature_path_regexp', 'step_path', 'requires'].each do |key|
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
- - 2
9
- version: 0.1.2
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-11 00:00:00 -06:00
17
+ date: 2011-01-12 00:00:00 -06:00
18
18
  default_executable: cellophane
19
19
  dependencies: []
20
20