cukedep 0.1.11 → 0.2.00
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 +6 -14
- data/.ruby-version +1 -1
- data/.travis.yml +10 -10
- data/CHANGELOG.md +6 -0
- data/Gemfile +5 -5
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/Rakefile +30 -30
- data/bin/cukedep +15 -15
- data/lib/cukedep/application.rb +105 -112
- data/lib/cukedep/cli/cmd-line.rb +11 -13
- data/lib/cukedep/config.rb +85 -89
- data/lib/cukedep/constants.rb +5 -5
- data/lib/cukedep/cuke-runner.rb +191 -198
- data/lib/cukedep/customization.rb +30 -30
- data/lib/cukedep/feature-model.rb +43 -46
- data/lib/cukedep/feature-rep.rb +9 -11
- data/lib/cukedep/file-action.rb +11 -18
- data/lib/cukedep/gherkin-facade.rb +11 -6
- data/lib/cukedep/gherkin-listener.rb +12 -42
- data/lib/cukedep/hook-dsl.rb +78 -78
- data/lib/cukedep/sandbox.rb +15 -16
- data/lib/cukedep.rb +1 -2
- data/sample/features/step_definitions/steps.rb +2 -2
- data/sample/model/model.rb +19 -20
- data/spec/cukedep/application_spec.rb +80 -80
- data/spec/cukedep/cli/cmd-line_spec.rb +88 -88
- data/spec/cukedep/cuke-runner_spec.rb +74 -74
- data/spec/cukedep/customization_spec.rb +31 -31
- data/spec/cukedep/debug-file-action.rb +29 -29
- data/spec/cukedep/feature-model_spec.rb +100 -100
- data/spec/cukedep/feature-rep_spec.rb +2 -1
- data/spec/cukedep/file-action_spec.rb +365 -366
- data/spec/cukedep/file-parsing.rb +39 -41
- data/spec/cukedep/gherkin-facade_spec.rb +48 -49
- data/spec/cukedep/gherkin-listener_spec.rb +55 -57
- data/spec/cukedep/hook-dsl_spec.rb +182 -182
- data/spec/cukedep/sample_features/cukedep_hooks.rb +30 -30
- data/spec/cukedep/sample_features/standalone.feature +1 -1
- data/templates/rake.erb +12 -21
- metadata +80 -58
- data/sample/result.html +0 -472
- data/spec/cukedep/sample_features/cukedep.rake +0 -215
- data/spec/cukedep/sample_features/dependencies.dot +0 -38
- data/spec/cukedep/sample_features/feature2id.csv +0 -7
data/lib/cukedep/constants.rb
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
module Cukedep # Module used as a namespace
|
|
5
5
|
# The version number of the gem.
|
|
6
|
-
Version = '0.
|
|
6
|
+
Version = '0.2.00'.freeze
|
|
7
7
|
|
|
8
8
|
# Brief description of the gem.
|
|
9
|
-
Description = 'Manage dependencies between Cucumber feature files'
|
|
9
|
+
Description = 'Manage dependencies between Cucumber feature files'.freeze
|
|
10
10
|
|
|
11
11
|
# Constant Cukedep::RootDir contains the absolute path of Rodent's
|
|
12
12
|
# root directory. Note: it also ends with a slash character.
|
|
@@ -22,11 +22,11 @@ module Cukedep # Module used as a namespace
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# The file name for the user's settings
|
|
25
|
-
YMLFilename = '.cukedep.yml'
|
|
26
|
-
|
|
25
|
+
YMLFilename = '.cukedep.yml'.freeze
|
|
26
|
+
|
|
27
27
|
# The file name for the custom block codes associated
|
|
28
28
|
# with before/after events.
|
|
29
|
-
HookFilename = 'cukedep_hooks.rb'
|
|
29
|
+
HookFilename = 'cukedep_hooks.rb'.freeze
|
|
30
30
|
end
|
|
31
31
|
end # module
|
|
32
32
|
|
data/lib/cukedep/cuke-runner.rb
CHANGED
|
@@ -1,198 +1,191 @@
|
|
|
1
|
-
# File: cuke-runner.rb
|
|
2
|
-
|
|
3
|
-
require 'pathname'
|
|
4
|
-
require 'rake'
|
|
5
|
-
|
|
6
|
-
# Run Cucumber via specialized Rake task
|
|
7
|
-
require 'cucumber/rake/task'
|
|
8
|
-
|
|
9
|
-
require_relative 'file-action'
|
|
10
|
-
require_relative 'customization'
|
|
11
|
-
|
|
12
|
-
# UGLY workaround for bug in Cucumber's rake task
|
|
13
|
-
if Gem::VERSION[0].to_i >= 2 && Cucumber::VERSION <= '1.3.2'
|
|
14
|
-
# Monkey-patch a buggy method
|
|
15
|
-
module Cucumber
|
|
16
|
-
module Rake
|
|
17
|
-
class Task
|
|
18
|
-
class ForkedCucumberRunner
|
|
19
|
-
def gem_available?(gemname)
|
|
20
|
-
if Gem::VERSION[0].to_i >= 2
|
|
21
|
-
gem_available_new_rubygems?(gemname)
|
|
22
|
-
else
|
|
23
|
-
gem_available_old_rubygems?(gemname)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end # class
|
|
27
|
-
end # class
|
|
28
|
-
end # module
|
|
29
|
-
end # module
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
module Cukedep # This module is used as a namespace
|
|
35
|
-
# Purpose: to launch Cucumber in the appropriate directory
|
|
36
|
-
# and pass it command-line arguments.
|
|
37
|
-
# Responsibilities:
|
|
38
|
-
# Know how to invoke Cucumber
|
|
39
|
-
# Know the base directory
|
|
40
|
-
# Know the project's root dir
|
|
41
|
-
class CukeRunner
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
return if kode.nil?
|
|
193
|
-
safe_args = args.map { |one_arg| one_arg.dup.freeze }
|
|
194
|
-
kode.call(*safe_args)
|
|
195
|
-
end
|
|
196
|
-
end # class
|
|
197
|
-
end # module
|
|
198
|
-
# End of file
|
|
1
|
+
# File: cuke-runner.rb
|
|
2
|
+
|
|
3
|
+
require 'pathname'
|
|
4
|
+
require 'rake'
|
|
5
|
+
|
|
6
|
+
# Run Cucumber via specialized Rake task
|
|
7
|
+
require 'cucumber/rake/task'
|
|
8
|
+
|
|
9
|
+
require_relative 'file-action'
|
|
10
|
+
require_relative 'customization'
|
|
11
|
+
|
|
12
|
+
# UGLY workaround for bug in Cucumber's rake task
|
|
13
|
+
if Gem::VERSION[0].to_i >= 2 && Cucumber::VERSION <= '1.3.2'
|
|
14
|
+
# Monkey-patch a buggy method
|
|
15
|
+
module Cucumber
|
|
16
|
+
module Rake
|
|
17
|
+
class Task
|
|
18
|
+
class ForkedCucumberRunner
|
|
19
|
+
def gem_available?(gemname)
|
|
20
|
+
if Gem::VERSION[0].to_i >= 2
|
|
21
|
+
gem_available_new_rubygems?(gemname)
|
|
22
|
+
else
|
|
23
|
+
gem_available_old_rubygems?(gemname)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end # class
|
|
27
|
+
end # class
|
|
28
|
+
end # module
|
|
29
|
+
end # module
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
module Cukedep # This module is used as a namespace
|
|
35
|
+
# Purpose: to launch Cucumber in the appropriate directory
|
|
36
|
+
# and pass it command-line arguments.
|
|
37
|
+
# Responsibilities:
|
|
38
|
+
# Know how to invoke Cucumber
|
|
39
|
+
# Know the base directory
|
|
40
|
+
# Know the project's root dir
|
|
41
|
+
class CukeRunner
|
|
42
|
+
# The current state of the runner.
|
|
43
|
+
attr_reader(:state)
|
|
44
|
+
|
|
45
|
+
# The absolute path of the root's project directory
|
|
46
|
+
attr_reader(:proj_dir)
|
|
47
|
+
attr_reader(:base_dir)
|
|
48
|
+
attr_reader(:config)
|
|
49
|
+
attr_reader(:handlers)
|
|
50
|
+
|
|
51
|
+
attr_accessor(:cucumber_opts)
|
|
52
|
+
|
|
53
|
+
# Constructor
|
|
54
|
+
def initialize(baseDir, projectDir, aConfig)
|
|
55
|
+
@base_dir = baseDir
|
|
56
|
+
@proj_dir = validated_proj_dir(projectDir)
|
|
57
|
+
@config = aConfig
|
|
58
|
+
@handlers = Customization.new.build_handlers(baseDir)
|
|
59
|
+
|
|
60
|
+
@state = :Initialized
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Launch Cucumber in the project directory.
|
|
64
|
+
def invoke
|
|
65
|
+
options = [] # TODO: retrieve Cucumber options
|
|
66
|
+
orig_dir = Dir.getwd
|
|
67
|
+
Dir.chdir(proj_dir)
|
|
68
|
+
|
|
69
|
+
begin
|
|
70
|
+
cuke_task = Cucumber::Rake::Task.new do |t|
|
|
71
|
+
t.cucumber_opts = options
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
cuke_task.runner.run
|
|
75
|
+
rescue SystemExit => exc # Cucumber reports a failure.
|
|
76
|
+
raise StandardError, "Cucumber exited with status #{exc.status}"
|
|
77
|
+
ensure
|
|
78
|
+
Dir.chdir(orig_dir)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Event handler that is triggered
|
|
83
|
+
# before any other event.
|
|
84
|
+
# It executes the before all hook first.
|
|
85
|
+
# Then it executes in the following order:
|
|
86
|
+
# Built-in save action, Custom save action
|
|
87
|
+
# Built-in delete action, Custom delete action
|
|
88
|
+
# Built-in copy action, Custom copy action
|
|
89
|
+
def before_all
|
|
90
|
+
expected_state(:Initialized)
|
|
91
|
+
|
|
92
|
+
# Execute before all hook code
|
|
93
|
+
run_code_block
|
|
94
|
+
|
|
95
|
+
# Execute file actions
|
|
96
|
+
builtin_actions = ActionTriplet.builtin(:before_all)
|
|
97
|
+
custom_actions = ActionTriplet.new(config.before_all_f_actions)
|
|
98
|
+
run_triplets([builtin_actions, custom_actions])
|
|
99
|
+
@state = :ReadyToRun
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Event handler that is triggered
|
|
103
|
+
# after any other event.
|
|
104
|
+
# It executes first actions in the following order:
|
|
105
|
+
# Built-in save action, Custom save action
|
|
106
|
+
# Built-in delete action, Custom delete action
|
|
107
|
+
# Built-in copy action, Custom copy action
|
|
108
|
+
# Then it executes the after all hook last.
|
|
109
|
+
def after_all
|
|
110
|
+
expected_state(:ReadyToRun)
|
|
111
|
+
|
|
112
|
+
builtin_actions = ActionTriplet.builtin(:after_all)
|
|
113
|
+
custom_actions = ActionTriplet.new(config.after_all_f_actions)
|
|
114
|
+
run_triplets([builtin_actions, custom_actions])
|
|
115
|
+
|
|
116
|
+
# Execute before all hook code
|
|
117
|
+
run_code_block
|
|
118
|
+
@state = :Complete
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def run!(fileNames)
|
|
122
|
+
expected_state(:ReadyToRun)
|
|
123
|
+
before_each(fileNames)
|
|
124
|
+
invoke
|
|
125
|
+
after_each
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private
|
|
129
|
+
|
|
130
|
+
def validated_proj_dir(projectDir)
|
|
131
|
+
path = Pathname.new(projectDir)
|
|
132
|
+
path = path.expand_path if path.relative?
|
|
133
|
+
raise StandardError, "No such project path: '#{path}'" unless path.exist?
|
|
134
|
+
|
|
135
|
+
return path.to_s
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def expected_state(aState)
|
|
139
|
+
return if state == aState
|
|
140
|
+
msg = "expected state was '#{aState}' instead of '#{state}'."
|
|
141
|
+
raise StandardError, msg
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def before_each(fileNames)
|
|
145
|
+
# Execute before each hook code
|
|
146
|
+
run_code_block(fileNames)
|
|
147
|
+
|
|
148
|
+
builtins = ActionTriplet.builtin(:before_each).dup
|
|
149
|
+
builtins.copy_action.patterns = fileNames unless builtins.nil?
|
|
150
|
+
|
|
151
|
+
custom_actions = ActionTriplet.new(config.before_each_f_actions)
|
|
152
|
+
run_triplets([builtins, custom_actions])
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def after_each
|
|
156
|
+
builtin_actions = ActionTriplet.builtin(:after_each)
|
|
157
|
+
|
|
158
|
+
custom_actions = ActionTriplet.new(config.after_each_f_actions)
|
|
159
|
+
run_triplets([builtin_actions, custom_actions])
|
|
160
|
+
|
|
161
|
+
# Execute after each hook code
|
|
162
|
+
run_code_block
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def run_triplets(theTriplets)
|
|
166
|
+
all_triplets = theTriplets.compact # Remove nil elements
|
|
167
|
+
|
|
168
|
+
# Do all save actions...
|
|
169
|
+
all_triplets.each { |t| t.save_action.run!(proj_dir, base_dir) }
|
|
170
|
+
|
|
171
|
+
# Do all delete actions...
|
|
172
|
+
all_triplets.each { |t| t.delete_action.run!(proj_dir) }
|
|
173
|
+
|
|
174
|
+
# Do all copy actions...
|
|
175
|
+
all_triplets.each { |t| t.copy_action.run!(base_dir, proj_dir) }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def run_code_block(*args)
|
|
179
|
+
# Retrieve the name of the parent method.
|
|
180
|
+
parent_mth = (caller[0].sub(/^(.+):in (.+)$/, '\2'))[1..-2]
|
|
181
|
+
kind, scope = parent_mth.split('_')
|
|
182
|
+
hook_kind = (kind + '_hooks')
|
|
183
|
+
|
|
184
|
+
kode = handlers[hook_kind.to_sym][scope.to_sym]
|
|
185
|
+
return if kode.nil?
|
|
186
|
+
safe_args = args.map { |one_arg| one_arg.dup.freeze }
|
|
187
|
+
kode.call(*safe_args)
|
|
188
|
+
end
|
|
189
|
+
end # class
|
|
190
|
+
end # module
|
|
191
|
+
# End of file
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
# File: customization.rb
|
|
2
|
-
|
|
3
|
-
require_relative 'constants'
|
|
4
|
-
require_relative 'hook-dsl'
|
|
5
|
-
|
|
6
|
-
module Cukedep # This module is used as a namespace
|
|
7
|
-
class Customization
|
|
8
|
-
# Retrieve before/after handlers from file
|
|
9
|
-
# Handlers are put in a Hash with keys :before_hooks, :after_hooks.
|
|
10
|
-
def build_handlers(directory)
|
|
11
|
-
handlers = nil
|
|
12
|
-
|
|
13
|
-
filepath = directory + '/' + Cukedep::HookFilename
|
|
14
|
-
if File.exist? filepath
|
|
15
|
-
obj = Object.new
|
|
16
|
-
obj.extend(HookDSL)
|
|
17
|
-
hook_source = File.read(filepath)
|
|
18
|
-
obj.instance_eval(hook_source)
|
|
19
|
-
handlers =
|
|
20
|
-
before_hooks: obj.before_hooks,
|
|
21
|
-
after_hooks: obj.after_hooks
|
|
22
|
-
}
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
return handlers
|
|
26
|
-
end
|
|
27
|
-
end # class
|
|
28
|
-
end # module
|
|
29
|
-
|
|
30
|
-
# End of file
|
|
1
|
+
# File: customization.rb
|
|
2
|
+
|
|
3
|
+
require_relative 'constants'
|
|
4
|
+
require_relative 'hook-dsl'
|
|
5
|
+
|
|
6
|
+
module Cukedep # This module is used as a namespace
|
|
7
|
+
class Customization
|
|
8
|
+
# Retrieve before/after handlers from file
|
|
9
|
+
# Handlers are put in a Hash with keys :before_hooks, :after_hooks.
|
|
10
|
+
def build_handlers(directory)
|
|
11
|
+
handlers = nil
|
|
12
|
+
|
|
13
|
+
filepath = directory + '/' + Cukedep::HookFilename
|
|
14
|
+
if File.exist? filepath
|
|
15
|
+
obj = Object.new
|
|
16
|
+
obj.extend(HookDSL)
|
|
17
|
+
hook_source = File.read(filepath)
|
|
18
|
+
obj.instance_eval(hook_source)
|
|
19
|
+
handlers = {
|
|
20
|
+
before_hooks: obj.before_hooks,
|
|
21
|
+
after_hooks: obj.after_hooks
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
return handlers
|
|
26
|
+
end
|
|
27
|
+
end # class
|
|
28
|
+
end # module
|
|
29
|
+
|
|
30
|
+
# End of file
|