cukedep 0.0.8 → 0.1.03
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 +8 -8
- data/CHANGELOG.md +26 -0
- data/bin/cukedep +1 -1
- data/lib/cukedep/application.rb +7 -7
- data/lib/cukedep/config.rb +64 -7
- data/lib/cukedep/constants.rb +5 -1
- data/lib/cukedep/cuke-runner.rb +202 -0
- data/lib/cukedep/customization.rb +35 -0
- data/lib/cukedep/feature-rep.rb +2 -2
- data/lib/cukedep/file-action.rb +211 -0
- data/lib/cukedep/hook-dsl.rb +80 -0
- data/lib/cukedep/sandbox.rb +21 -0
- data/sample/cucumber.yml +4 -0
- data/sample/model/catalogue.yml +13 -0
- data/sample/model/members.yml +13 -0
- data/sample/model/model.rb +2 -2
- data/sample/model/rentals.yml +4 -0
- data/sample/model/users.yml +7 -0
- data/sample/result.html +472 -0
- data/spec/cukedep/application_spec.rb +8 -8
- data/spec/cukedep/cuke-runner_spec.rb +80 -0
- data/spec/cukedep/customization_spec.rb +36 -0
- data/spec/cukedep/file-action_spec.rb +374 -0
- data/spec/cukedep/gherkin-facade_spec.rb +54 -0
- data/spec/cukedep/hook-dsl_spec.rb +185 -0
- data/spec/cukedep/sample_features/cukedep.rake +204 -0
- data/spec/cukedep/sample_features/cukedep_hooks.rb +30 -0
- data/spec/cukedep/sample_features/dependencies.dot +38 -0
- data/spec/cukedep/sample_features/feature2id.csv +7 -0
- data/spec/cukedep/sample_features/files_to_copy/README.md +12 -0
- data/spec/cukedep/sample_features/files_to_copy/file1.txt +5 -0
- data/spec/cukedep/sample_features/files_to_copy/file2.txt +5 -0
- data/spec/cukedep/sample_features/files_to_copy/file3.txt +9 -0
- data/spec/spec_helper.rb +1 -0
- data/templates/rake.erb +184 -160
- metadata +26 -2
@@ -0,0 +1,54 @@
|
|
1
|
+
# File: file-actions_spec.rb
|
2
|
+
|
3
|
+
require_relative '../spec_helper'
|
4
|
+
|
5
|
+
# Load the class under testing
|
6
|
+
require_relative '../../lib/cukedep/gherkin-facade'
|
7
|
+
require_relative '../../lib/cukedep/gherkin-listener'
|
8
|
+
|
9
|
+
module Cukedep # Open module to get rid of long qualified names
|
10
|
+
|
11
|
+
describe GherkinFacade do
|
12
|
+
subject { GherkinFacade.new(false, 'UTF-8') }
|
13
|
+
|
14
|
+
context 'Creation & initialization:' do
|
15
|
+
it 'should be created with two arguments' do
|
16
|
+
expect { GherkinFacade.new(true, 'UTF-8') }.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should whether it is verbose or not' do
|
20
|
+
# Case 1: instance is verbose
|
21
|
+
expect(subject.verbose).to be_false
|
22
|
+
|
23
|
+
# Case 2: instance is silent
|
24
|
+
instance = GherkinFacade.new(true, 'UTF-8')
|
25
|
+
expect(instance.verbose).to be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should know the feature file external encoding' do
|
29
|
+
expect(subject.external_encoding).to eq('UTF-8')
|
30
|
+
end
|
31
|
+
|
32
|
+
end # context
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
context 'Provided services:' do
|
37
|
+
let(:listener) { GherkinListener.new }
|
38
|
+
it 'should parse ASCII feature files' do
|
39
|
+
instance = GherkinFacade.new(false, 'US-ASCII')
|
40
|
+
patterns = [ 'sample_features/a_few_tests.feature' ]
|
41
|
+
expect {instance.parse_features(listener, patterns)}.not_to raise_error
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should parse feature files with other external encoding' do
|
45
|
+
patterns = [ 'sample_features/standalone.feature' ]
|
46
|
+
expect {subject.parse_features(listener, patterns)}.not_to raise_error
|
47
|
+
end
|
48
|
+
end # context
|
49
|
+
|
50
|
+
end # describe
|
51
|
+
|
52
|
+
end # module
|
53
|
+
|
54
|
+
# End of file
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# File: file-action_spec.rb
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require_relative '../spec_helper'
|
5
|
+
|
6
|
+
# Load the class under testing
|
7
|
+
require_relative '../../lib/cukedep/hook-dsl'
|
8
|
+
|
9
|
+
module Cukedep # Open module to get rid of long qualified names
|
10
|
+
|
11
|
+
# Let's specify the behaviour of the mix-in module
|
12
|
+
describe HookDSL do
|
13
|
+
|
14
|
+
subject do
|
15
|
+
obj = Object.new
|
16
|
+
obj.extend(HookDSL)
|
17
|
+
obj
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'Hook definitions:' do
|
21
|
+
let(:code_block) do
|
22
|
+
-> { ; }
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should accept the before all hook' do
|
26
|
+
# Case 1: before all with block code
|
27
|
+
expect { subject.before_cuke(:all, &code_block) }.not_to raise_error
|
28
|
+
|
29
|
+
# Case 2: before all without block code
|
30
|
+
expect { subject.before_cuke(:all) }.not_to raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should accept the before each hook' do
|
34
|
+
# Case 1: before each with block code
|
35
|
+
expect { subject.before_cuke(:each, &code_block) }.not_to raise_error
|
36
|
+
|
37
|
+
# Case 2: before each without block code
|
38
|
+
expect { subject.before_cuke(:each) }.not_to raise_error
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
it 'should accept the after all hook' do
|
43
|
+
# Case 1: after all with block code
|
44
|
+
expect { subject.after_cuke(:all, &code_block) }.not_to raise_error
|
45
|
+
|
46
|
+
# Case 2: before all without block code
|
47
|
+
expect { subject.after_cuke(:all) }.not_to raise_error
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should accept the after each hook' do
|
51
|
+
# Case 1: after each with block code
|
52
|
+
expect { subject.after_cuke(:each, &code_block) }.not_to raise_error
|
53
|
+
|
54
|
+
# Case 2: after each without block code
|
55
|
+
expect { subject.after_cuke(:each) }.not_to raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should reject invalid scope argument' do
|
59
|
+
# Case 1: before invalid with block code
|
60
|
+
msg = "Unknown scope 'invalid' for before_cuke hook."
|
61
|
+
error = StandardError
|
62
|
+
expect { subject.before_cuke(:invalid, &code_block) }.to raise_error(error, msg)
|
63
|
+
|
64
|
+
# Case 2: after invalid with block code
|
65
|
+
msg = "Unknown scope 'invalid' for after_cuke hook."
|
66
|
+
expect { subject.after_cuke(:invalid, &code_block) }.to raise_error(error, msg)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
it 'should register the block code with the event' do
|
71
|
+
# No block code registered yet.
|
72
|
+
expect(subject.instance_variables).not_to include(:@before_hooks)
|
73
|
+
|
74
|
+
# Case 1: No before all handler provided
|
75
|
+
subject.before_cuke(:all)
|
76
|
+
expect(subject.instance_variables).not_to include(:@before_hooks)
|
77
|
+
|
78
|
+
# Case 1: Add before all handler
|
79
|
+
subject.before_cuke(:all, &code_block)
|
80
|
+
|
81
|
+
# Check that handler code is stored in instance variable
|
82
|
+
expect(subject.instance_variables).to include(:@before_hooks)
|
83
|
+
expect(subject.before_hooks.keys).to eq([:all])
|
84
|
+
expect(subject.before_hooks[:all]).to eq(code_block)
|
85
|
+
|
86
|
+
# Case 2: No before each handler provided
|
87
|
+
subject.before_cuke(:each)
|
88
|
+
expect(subject.before_hooks.keys).to eq([:all])
|
89
|
+
|
90
|
+
# Case 3: Add before each handler
|
91
|
+
subject.before_cuke(:each, &code_block)
|
92
|
+
|
93
|
+
# Check that handler code is stored in instance variable
|
94
|
+
expect(subject.before_hooks.keys).to eq([:all, :each])
|
95
|
+
expect(subject.before_hooks[:each]).to eq(code_block)
|
96
|
+
|
97
|
+
|
98
|
+
# Case 4: No after all handler provided
|
99
|
+
subject.after_cuke(:all)
|
100
|
+
expect(subject.instance_variables).not_to include(:@after_hooks)
|
101
|
+
|
102
|
+
# Case 5: Add after all handler
|
103
|
+
subject.after_cuke(:all, &code_block)
|
104
|
+
|
105
|
+
# Check that handler code is stored in instance variable
|
106
|
+
expect(subject.instance_variables).to include(:@after_hooks)
|
107
|
+
expect(subject.after_hooks.keys).to eq([:all])
|
108
|
+
expect(subject.after_hooks[:all]).to eq(code_block)
|
109
|
+
|
110
|
+
# Case 6: No after each handler provided
|
111
|
+
subject.after_cuke(:each)
|
112
|
+
expect(subject.after_hooks.keys).to eq([:all])
|
113
|
+
|
114
|
+
# Case 7: Add after each handler
|
115
|
+
subject.after_cuke(:each, &code_block)
|
116
|
+
|
117
|
+
# Check that handler code is stored in instance variable
|
118
|
+
expect(subject.after_hooks.keys).to eq([:all, :each])
|
119
|
+
expect(subject.after_hooks[:each]).to eq(code_block)
|
120
|
+
end
|
121
|
+
|
122
|
+
end # context
|
123
|
+
=begin
|
124
|
+
context 'Executing handler code:' do
|
125
|
+
let(:ostream) { StringIO.new('', 'w') }
|
126
|
+
|
127
|
+
it 'should ignore missing handler' do
|
128
|
+
expect { subject.execute_hook(:before, :all) }.not_to raise_error
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should execute the before all handler' do
|
132
|
+
text = 'before all'
|
133
|
+
# Let's create the hook
|
134
|
+
subject.before_cuke(:all) { ostream.print text }
|
135
|
+
|
136
|
+
# Let's execute it...
|
137
|
+
subject.execute_hook(:before, :all)
|
138
|
+
|
139
|
+
expect(ostream.string).to eq(text)
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
it 'should execute the before all handler' do
|
144
|
+
text = 'before each'
|
145
|
+
# Let's create the hook
|
146
|
+
subject.before_cuke(:each) { ostream.print text }
|
147
|
+
|
148
|
+
# Let's execute it...
|
149
|
+
subject.execute_hook(:before, :each)
|
150
|
+
|
151
|
+
expect(ostream.string).to eq(text)
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
it 'should execute the after all handler' do
|
156
|
+
text = 'after all'
|
157
|
+
# Let's create the hook
|
158
|
+
subject.after_cuke(:all) { ostream.print text }
|
159
|
+
|
160
|
+
# Let's execute it...
|
161
|
+
subject.execute_hook(:after, :all)
|
162
|
+
|
163
|
+
expect(ostream.string).to eq(text)
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
it 'should execute the after each handler' do
|
168
|
+
text = 'after each'
|
169
|
+
# Let's create the hook
|
170
|
+
subject.after_cuke(:each) { ostream.print text }
|
171
|
+
|
172
|
+
# Let's execute it...
|
173
|
+
subject.execute_hook(:after, :each)
|
174
|
+
|
175
|
+
expect(ostream.string).to eq(text)
|
176
|
+
end
|
177
|
+
|
178
|
+
end # context
|
179
|
+
=end
|
180
|
+
|
181
|
+
end # describe
|
182
|
+
|
183
|
+
end # module
|
184
|
+
|
185
|
+
# End of file
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# File: cukedep.rake
|
2
|
+
# Generated by Cukedep 0.1.01 on 27/11/2013 23:12:50
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
require 'cukedep/file-action'
|
6
|
+
|
7
|
+
# Run Cucumber via specialized Rake task
|
8
|
+
require 'cucumber/rake/task'
|
9
|
+
# UGLY workaround for bug in Cucumber's rake task
|
10
|
+
if Gem::VERSION[0].to_i >= 2 && Cucumber::VERSION <= '1.3.2'
|
11
|
+
# Monkey-patch a buggy method
|
12
|
+
class Cucumber::Rake::Task::ForkedCucumberRunner
|
13
|
+
def gem_available?(gemname)
|
14
|
+
if Gem::VERSION[0].to_i >= 2
|
15
|
+
gem_available_new_rubygems?(gemname)
|
16
|
+
else
|
17
|
+
gem_available_old_rubygems?(gemname)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end # class
|
21
|
+
end
|
22
|
+
|
23
|
+
# Create a task called cucumber
|
24
|
+
Cucumber::Rake::Task.new do |t|
|
25
|
+
end
|
26
|
+
|
27
|
+
#######################################
|
28
|
+
# Retrieving state at end of Cukedep::Application#run! method
|
29
|
+
#######################################
|
30
|
+
|
31
|
+
# Constant holding the location of the original feature files
|
32
|
+
SOURCE_DIR = 'C:/Ruby193/lib/ruby/site_ruby/Cukedep/spec/cukedep/sample_features'
|
33
|
+
|
34
|
+
# Constant holding the location of the Cucumber project
|
35
|
+
CUKE_PROJECT = 'C:/Ruby193/lib/ruby/site_ruby/Cukedep/sample'
|
36
|
+
|
37
|
+
# The list of all "legacy" feature file (feature files without the @feature: tag)
|
38
|
+
AllUnidentifiedFeatures = [
|
39
|
+
'standalone.feature'
|
40
|
+
]
|
41
|
+
|
42
|
+
# The list of all encountered feature ids
|
43
|
+
AllFeatureIdentifiers = [
|
44
|
+
:qux,
|
45
|
+
:quux,
|
46
|
+
:corge,
|
47
|
+
:foo,
|
48
|
+
:baz,
|
49
|
+
:bar
|
50
|
+
]
|
51
|
+
|
52
|
+
|
53
|
+
def run_builtin_actions(anEvent)
|
54
|
+
actions = Cukedep::ActionTriplet.builtin(anEvent)
|
55
|
+
actions.run!(SOURCE_DIR, CUKE_PROJECT) unless actions.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Helper method. Calculate the filepath of a file with given name
|
59
|
+
# if it is located in the source dir.
|
60
|
+
def source_path_of(aFilename)
|
61
|
+
SOURCE_DIR + '/' + aFilename
|
62
|
+
end
|
63
|
+
|
64
|
+
# Helper method. Calculate the filepath of a file with given name
|
65
|
+
# if it is located in the project features dir.
|
66
|
+
def project_path_of(aFilename)
|
67
|
+
CUKE_PROJECT + '/features/' + aFilename
|
68
|
+
end
|
69
|
+
|
70
|
+
# Helper method. Given the name of files in the source dir, copy them
|
71
|
+
# into the project dir.
|
72
|
+
def copy_to_project(filenames)
|
73
|
+
filenames.each do |fname|
|
74
|
+
source_path = source_path_of(fname)
|
75
|
+
dest_path = project_path_of(fname)
|
76
|
+
FileUtils.copy_file(source_path, dest_path)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Helper method. Given the name of files in the features dir of the project,
|
82
|
+
# copy them into the source dir.
|
83
|
+
def copy_from_project(*filenames)
|
84
|
+
filenames.each do |fname|
|
85
|
+
source_path = project_path_of(fname)
|
86
|
+
dest_path = source_path_of(fname)
|
87
|
+
FileUtils.copy_file(source_path, dest_path)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Helper method. Delete all the files in the
|
92
|
+
# the project's features dir that match one of
|
93
|
+
# the file name pattern
|
94
|
+
def clean_project_dir(fname_patterns)
|
95
|
+
curr_dir = Dir.getwd()
|
96
|
+
begin
|
97
|
+
Dir.chdir(CUKE_PROJECT + '/features')
|
98
|
+
fname_patterns.each do |patt|
|
99
|
+
filenames = Dir.glob(patt)
|
100
|
+
filenames.each { |fn| FileUtils.remove_file(fn) }
|
101
|
+
end
|
102
|
+
ensure #Always restore previous working dir.
|
103
|
+
Dir.chdir(curr_dir)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
# Helper method. Invoke Cucumber with the given project root dir.
|
109
|
+
# Assumption: all features files to execute are placed
|
110
|
+
# in the appropriate folder.
|
111
|
+
def invoke_cuke(projectDir)
|
112
|
+
curr_dir = Dir.getwd()
|
113
|
+
Dir.chdir(projectDir)
|
114
|
+
begin
|
115
|
+
do_cuke = Rake::Task[:cucumber]
|
116
|
+
do_cuke.reenable
|
117
|
+
do_cuke.invoke
|
118
|
+
ensure
|
119
|
+
Dir.chdir(curr_dir)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
def process_files(filenames)
|
125
|
+
run_builtin_actions(:before_each)
|
126
|
+
copy_to_project(filenames)
|
127
|
+
invoke_cuke(CUKE_PROJECT)
|
128
|
+
run_builtin_actions(:after_each)
|
129
|
+
#del_from_project(filenames)
|
130
|
+
end
|
131
|
+
|
132
|
+
def process_a_feature(filename)
|
133
|
+
process_files([filename])
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
# Default rake task is also top-level task
|
138
|
+
task :default => :run_all_features
|
139
|
+
|
140
|
+
|
141
|
+
desc 'Run all features'
|
142
|
+
task :run_all_features => [:before_all, :all_features, :after_all] do
|
143
|
+
; # Do nothing
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
desc 'Before all'
|
148
|
+
task :before_all do
|
149
|
+
run_builtin_actions(:before_all)
|
150
|
+
end
|
151
|
+
|
152
|
+
desc 'After_all'
|
153
|
+
task :after_all do
|
154
|
+
run_builtin_actions(:after_all)
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
task :unidentified do
|
159
|
+
process_files(AllUnidentifiedFeatures)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Tasks for feature files involved in dependencies
|
163
|
+
|
164
|
+
|
165
|
+
desc "qux: run a_few_tests.feature"
|
166
|
+
task :qux do
|
167
|
+
process_a_feature('a_few_tests.feature')
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
desc "quux: run more_tests.feature"
|
172
|
+
task :quux do
|
173
|
+
process_a_feature('more_tests.feature')
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
desc "corge: run other_tests.feature"
|
178
|
+
task :corge => [:foo] do
|
179
|
+
process_a_feature('other_tests.feature')
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
desc "foo: run some_tests.feature"
|
184
|
+
task :foo => [:bar, :qux] do
|
185
|
+
process_a_feature('some_tests.feature')
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
desc "baz: run still_other_tests.feature"
|
190
|
+
task :baz do
|
191
|
+
process_a_feature('still_other_tests.feature')
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
desc "bar: run yet_other_tests.feature"
|
196
|
+
task :bar => [:baz, :qux, :quux] do
|
197
|
+
process_a_feature('yet_other_tests.feature')
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
task :all_features => ([:unidentified] + AllFeatureIdentifiers) do
|
202
|
+
end
|
203
|
+
|
204
|
+
# End of file
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# File: cukedep_hooks.rb
|
2
|
+
# This Ruby file specifies the custom code
|
3
|
+
# associated with Cukedep hooks.
|
4
|
+
|
5
|
+
# The code block will be executed before
|
6
|
+
# the very first Cucumber invocation.
|
7
|
+
before_cuke(:all) do
|
8
|
+
puts 'before all'
|
9
|
+
end
|
10
|
+
|
11
|
+
# The code block will be executed just before
|
12
|
+
# a Cucumber invocation.
|
13
|
+
# The argument is a frozen Array of feature file names
|
14
|
+
before_cuke(:each) do |filenames|
|
15
|
+
puts 'before each'
|
16
|
+
end
|
17
|
+
|
18
|
+
# The code block will be executed just after
|
19
|
+
# a Cucumber invocation.
|
20
|
+
after_cuke(:each) do
|
21
|
+
puts 'after each'
|
22
|
+
end
|
23
|
+
|
24
|
+
# The code block will be executed just after
|
25
|
+
# the last Cucumber invocation.
|
26
|
+
after_cuke(:all) do
|
27
|
+
puts 'after all'
|
28
|
+
end
|
29
|
+
|
30
|
+
# End of file
|