spectre-core 1.15.2 → 2.0.1
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/exe/spectre +271 -463
- data/lib/spectre/assertion.rb +118 -250
- data/lib/spectre/expectation.rb +89 -0
- data/lib/spectre/helpers.rb +56 -59
- data/lib/spectre/version.rb +3 -0
- data/lib/spectre.rb +1510 -334
- metadata +57 -32
- data/lib/spectre/async.rb +0 -31
- data/lib/spectre/bag.rb +0 -17
- data/lib/spectre/curl.rb +0 -398
- data/lib/spectre/diagnostic.rb +0 -39
- data/lib/spectre/environment.rb +0 -30
- data/lib/spectre/http/basic_auth.rb +0 -25
- data/lib/spectre/http/keystone.rb +0 -99
- data/lib/spectre/http.rb +0 -394
- data/lib/spectre/logging/console.rb +0 -156
- data/lib/spectre/logging/file.rb +0 -106
- data/lib/spectre/logging.rb +0 -183
- data/lib/spectre/mixin.rb +0 -61
- data/lib/spectre/reporter/console.rb +0 -104
- data/lib/spectre/reporter.rb +0 -17
- data/lib/spectre/resources.rb +0 -53
data/exe/spectre
CHANGED
@@ -1,536 +1,344 @@
|
|
1
|
-
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'yaml'
|
5
|
-
require 'ostruct'
|
6
|
-
require 'optparse'
|
7
|
-
require 'fileutils'
|
8
|
-
require 'ectoplasm'
|
1
|
+
#!/usr/bin/ruby
|
9
2
|
|
10
3
|
require_relative '../lib/spectre'
|
11
|
-
require_relative '../lib/spectre/
|
4
|
+
require_relative '../lib/spectre/expectation'
|
12
5
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
6
|
+
FAILED_FILENAME = '.failed'
|
7
|
+
|
8
|
+
config_overrides = {}
|
17
9
|
|
10
|
+
cleanup = false
|
11
|
+
run_failed = false
|
18
12
|
|
19
|
-
|
20
|
-
'project' => nil,
|
21
|
-
'config_file' => './spectre.yml',
|
22
|
-
'environment' => 'default',
|
23
|
-
'specs' => [],
|
24
|
-
'tags' => [],
|
25
|
-
'verbose' => false,
|
26
|
-
'log_file' => './logs/spectre_<date>.log',
|
27
|
-
'log_format' => {
|
28
|
-
'console' => {
|
29
|
-
'indent' => 2,
|
30
|
-
'width' => 80,
|
31
|
-
'end_context' => nil,
|
32
|
-
'separator' => '<indent><desc>',
|
33
|
-
},
|
34
|
-
'file' => {
|
35
|
-
'separator' => '-- <desc>',
|
36
|
-
'start_group' => "-- Start '<desc>'",
|
37
|
-
'end_group' => "-- End '<desc>'",
|
38
|
-
},
|
39
|
-
},
|
40
|
-
'debug' => false,
|
41
|
-
'out_path' => './reports',
|
42
|
-
'secure_keys' => ['password', 'secret', 'token', 'secure', 'authorization'],
|
43
|
-
'spec_patterns' => ['./specs/**/*.spec.rb'],
|
44
|
-
'mixin_patterns' => ['../common/mixins/**/*.mixin.rb', './mixins/**/*.mixin.rb'],
|
45
|
-
'env_patterns' => ['./environments/**/*.env.yml'],
|
46
|
-
'env_partial_patterns' => ['./environments/**/*.env.secret.yml'],
|
47
|
-
'resource_paths' => ['../common/resources', './resources'],
|
48
|
-
'default_modules' => [
|
49
|
-
'spectre/helpers',
|
50
|
-
'spectre/reporter/console',
|
51
|
-
'spectre/logging/console',
|
52
|
-
'spectre/logging/file',
|
53
|
-
'spectre/assertion',
|
54
|
-
'spectre/diagnostic',
|
55
|
-
'spectre/environment',
|
56
|
-
'spectre/mixin',
|
57
|
-
'spectre/bag',
|
58
|
-
'spectre/http',
|
59
|
-
'spectre/http/basic_auth',
|
60
|
-
'spectre/http/keystone',
|
61
|
-
'spectre/resources',
|
62
|
-
'spectre/async',
|
63
|
-
],
|
64
|
-
'include' => [
|
65
|
-
|
66
|
-
],
|
67
|
-
'exclude' => [
|
68
|
-
|
69
|
-
],
|
70
|
-
}
|
71
|
-
|
72
|
-
|
73
|
-
cmd_options = {}
|
74
|
-
property_overrides = {}
|
75
|
-
|
76
|
-
$COMMAND = ['spectre'].concat(ARGV.clone).join(' ')
|
77
|
-
|
78
|
-
OptionParser.new do |opts|
|
13
|
+
options = OptionParser.new do |opts|
|
79
14
|
opts.banner = <<~BANNER
|
80
15
|
Spectre #{Spectre::VERSION}
|
81
16
|
|
82
17
|
Usage: spectre [command] [options]
|
83
18
|
|
84
19
|
Commands:
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
20
|
+
run, ru Run specs (default)
|
21
|
+
list, li List specs
|
22
|
+
describe, de Print all subject descriptions
|
23
|
+
specs, sp Print detailed information about specs
|
24
|
+
mixins, mi List all mixin names
|
25
|
+
collections, co List the loaded collections
|
26
|
+
env, en Print current environment settings
|
27
|
+
cleanup, cl Will remove all generated files (e.g. logs and reports)
|
28
|
+
init, in Initialize a new spectre project
|
91
29
|
|
92
30
|
Specific options:
|
93
31
|
BANNER
|
94
32
|
|
95
33
|
opts.on('-s SPEC,SPEC', '--specs SPEC,SPEC', Array, 'The specs to run') do |specs|
|
96
|
-
|
34
|
+
config_overrides['specs'] = specs
|
97
35
|
end
|
98
36
|
|
99
37
|
opts.on('-t TAG,TAG', '--tags TAG,TAG', Array, 'Run only specs with given tags') do |tags|
|
100
|
-
|
38
|
+
config_overrides['tags'] = tags
|
101
39
|
end
|
102
40
|
|
103
41
|
opts.on('-e NAME', '--env NAME', 'Name of the environment to load') do |env_name|
|
104
|
-
|
42
|
+
config_overrides['selected_env'] = env_name
|
105
43
|
end
|
106
44
|
|
107
45
|
opts.on('-c FILE', '--config FILE', 'Config file to load') do |file_path|
|
108
|
-
|
46
|
+
config_overrides['config_file'] = file_path
|
109
47
|
end
|
110
48
|
|
111
|
-
opts.on('
|
112
|
-
|
49
|
+
opts.on('-C', '--collection NAME', 'Run or list specs of a specific collection') do |name|
|
50
|
+
config_overrides['collection'] = name
|
113
51
|
end
|
114
52
|
|
115
|
-
opts.on('--
|
116
|
-
|
53
|
+
opts.on('--work-dir PATH', 'Path of the working directory') do |path|
|
54
|
+
config_overrides['work_dir'] = path
|
117
55
|
end
|
118
56
|
|
119
|
-
opts.on('--
|
120
|
-
|
57
|
+
opts.on('--spec-patterns PATTERN', Array, 'File pattern for spec files') do |spec_pattern|
|
58
|
+
config_overrides['spec_patterns'] = spec_pattern
|
121
59
|
end
|
122
60
|
|
123
|
-
opts.on('-
|
124
|
-
|
61
|
+
opts.on('--env-patterns PATTERN', Array, 'File pattern for environment files') do |env_patterns|
|
62
|
+
config_overrides['env_patterns'] = env_patterns
|
125
63
|
end
|
126
64
|
|
127
|
-
opts.on('-
|
128
|
-
|
129
|
-
require mod
|
130
|
-
end
|
65
|
+
opts.on('--ignore-failure', 'Always exit with code 0') do
|
66
|
+
config_overrides['ignore_failure'] = true
|
131
67
|
end
|
132
68
|
|
133
|
-
opts.on('
|
134
|
-
|
69
|
+
opts.on('--formatter NAME', 'Use specified formatter') do |class_name|
|
70
|
+
config_overrides['formatter'] = class_name
|
135
71
|
end
|
136
72
|
|
137
|
-
opts.on('
|
138
|
-
|
139
|
-
val = val.split(',') if DEFAULT_CONFIG[key].is_a? Array
|
140
|
-
val = ['true', '1'].include? val if [true, false].include?(DEFAULT_CONFIG[key])
|
141
|
-
val = val.to_i if DEFAULT_CONFIG[key].is_a? Integer
|
142
|
-
|
143
|
-
opt_path = key.split('.')
|
144
|
-
|
145
|
-
curr_opt = property_overrides
|
146
|
-
|
147
|
-
opt_path.each_with_index do |part, i|
|
148
|
-
if i == opt_path.count-1
|
149
|
-
curr_opt[part] = val
|
150
|
-
break
|
151
|
-
end
|
152
|
-
|
153
|
-
curr_opt[part] = {} unless curr_opt.key?(part)
|
154
|
-
curr_opt = curr_opt[part]
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
opts.separator "\n Common options:"
|
159
|
-
|
160
|
-
opts.on_tail('-v', '--version', 'Print current installed version') do
|
161
|
-
puts Spectre::VERSION
|
162
|
-
exit
|
73
|
+
opts.on('--reporter NAME', 'Use specified reporter') do |class_name|
|
74
|
+
config_overrides['reporter'] = class_name
|
163
75
|
end
|
164
76
|
|
165
|
-
opts.
|
166
|
-
|
167
|
-
|
77
|
+
opts.on('--json', 'Use JSON formatter') do
|
78
|
+
Spectre::CONFIG['formatter'] = 'Spectre::JsonFormatter'
|
79
|
+
Spectre::CONFIG['reporters'] = ['Spectre::JsonReporter']
|
168
80
|
end
|
169
|
-
end.parse!
|
170
|
-
|
171
|
-
|
172
|
-
action = ARGV[0] || 'run'
|
173
|
-
|
174
|
-
|
175
|
-
###########################################
|
176
|
-
# Load Config
|
177
|
-
###########################################
|
178
81
|
|
82
|
+
opts.on('--failed', 'Run previously failed specs') do
|
83
|
+
run_failed = true
|
179
84
|
|
180
|
-
|
181
|
-
|
85
|
+
next if config_overrides.key? 'specs' or
|
86
|
+
config_overrides.key? 'tags' or
|
87
|
+
config_overrides.key? 'collection'
|
182
88
|
|
183
|
-
|
184
|
-
|
89
|
+
if File.exist?(FAILED_FILENAME)
|
90
|
+
config_overrides['specs'] = File
|
91
|
+
.readlines(FAILED_FILENAME)
|
92
|
+
.map(&:strip)
|
185
93
|
|
186
|
-
|
187
|
-
global_options = load_yaml(global_config_file)
|
188
|
-
cfg.deep_merge! global_options if global_options
|
189
|
-
end
|
190
|
-
|
191
|
-
# Then load local config file
|
192
|
-
config_file = cmd_options['config_file'] || cfg['config_file']
|
193
|
-
|
194
|
-
if File.exist? config_file
|
195
|
-
file_options = load_yaml(config_file)
|
196
|
-
cfg.deep_merge! file_options
|
197
|
-
Dir.chdir File.dirname(config_file)
|
198
|
-
end
|
199
|
-
|
200
|
-
# Set config options, which are only allowed to be overriden by command options
|
201
|
-
cfg['debug'] = DEFAULT_CONFIG['debug']
|
202
|
-
|
203
|
-
# Set project name
|
204
|
-
cfg['project'] = File.basename(Dir.pwd) unless cfg['project']
|
205
|
-
|
206
|
-
# And merge the command line arguments last
|
207
|
-
cfg.deep_merge! cmd_options
|
208
|
-
|
209
|
-
|
210
|
-
###########################################
|
211
|
-
# Load Environment
|
212
|
-
###########################################
|
213
|
-
|
214
|
-
envs = {}
|
215
|
-
read_env_files = {}
|
216
|
-
cfg['env_patterns'].each do |pattern|
|
217
|
-
Dir.glob(pattern).each do|f|
|
218
|
-
spec_env = load_yaml(f) || {}
|
219
|
-
|
220
|
-
name = spec_env['name'] || 'default'
|
221
|
-
|
222
|
-
if envs.key? name
|
223
|
-
existing_env_file = read_env_files[name]
|
224
|
-
puts "Duplicate environment definition detected with name #{name} in '#{f}'. Previously defined in '#{existing_env_file}'"
|
225
|
-
exit 1
|
94
|
+
File.delete(FAILED_FILENAME)
|
226
95
|
end
|
227
|
-
|
228
|
-
read_env_files[name] = f
|
229
|
-
envs[name] = spec_env
|
230
96
|
end
|
231
|
-
end
|
232
|
-
|
233
|
-
# Merge partial environment configs with existing environments
|
234
|
-
cfg['env_partial_patterns'].each do |pattern|
|
235
|
-
Dir.glob(pattern).each do|f|
|
236
|
-
partial_env = load_yaml(f)
|
237
|
-
name = partial_env.delete('name') || 'default'
|
238
|
-
next unless envs.key? name
|
239
97
|
|
240
|
-
|
98
|
+
opts.on('--no-log', 'Disable file logging') do
|
99
|
+
config_overrides['log_file'] = StringIO.new
|
241
100
|
end
|
242
|
-
end
|
243
|
-
|
244
|
-
env = envs[cfg['environment']]
|
245
|
-
cfg.deep_merge! env if env
|
246
101
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
# Load environment exlicitly before loading specs to make it available in spec definition
|
252
|
-
require_relative '../lib/spectre/environment' unless cfg['exclude'].include? 'spectre/environment'
|
253
|
-
Spectre.configure(cfg)
|
254
|
-
|
255
|
-
|
256
|
-
# Load specs only, when listing or running specs
|
257
|
-
if ['list', 'run'].include? action
|
258
|
-
|
259
|
-
###########################################
|
260
|
-
# Load Specs
|
261
|
-
###########################################
|
262
|
-
|
263
|
-
|
264
|
-
cfg['spec_patterns'].each do |pattern|
|
265
|
-
Dir.glob(pattern).each do|f|
|
266
|
-
require_relative File.join(Dir.pwd, f)
|
267
|
-
end
|
102
|
+
opts.on('--cleanup', 'Remove generated file before running specs') do
|
103
|
+
cleanup = true
|
268
104
|
end
|
269
105
|
|
270
|
-
|
271
|
-
|
272
|
-
# List specs
|
273
|
-
###########################################
|
274
|
-
|
275
|
-
|
276
|
-
if 'list' == action
|
277
|
-
colors = [:blue, :magenta, :yellow, :green]
|
278
|
-
specs = Spectre.specs(cfg['specs'], cfg['tags'])
|
279
|
-
|
280
|
-
exit 1 unless specs.any?
|
281
|
-
|
282
|
-
counter = 0
|
283
|
-
|
284
|
-
specs.group_by { |x| x.subject }.each do |subject, spec_group|
|
285
|
-
spec_group.each do |spec|
|
286
|
-
tags = spec.tags.map { |x| '#' + x.to_s }.join ' '
|
287
|
-
desc = subject.desc
|
288
|
-
desc += ' - ' + spec.context.__desc + ' -' if spec.context.__desc
|
289
|
-
desc += ' ' + spec.desc
|
290
|
-
puts "[#{spec.name}]".send(colors[counter % colors.length]) + " #{desc} #{tags.cyan}"
|
291
|
-
end
|
292
|
-
|
293
|
-
counter += 1
|
294
|
-
end
|
295
|
-
|
296
|
-
exit 0
|
106
|
+
opts.on('-o PATH', '--out PATH', 'Output directory path') do |path|
|
107
|
+
config_overrides['out_path'] = File.absolute_path(path)
|
297
108
|
end
|
298
109
|
|
110
|
+
opts.on('-m MODULE,MODULE', '--modules MODULE,MODULE', Array, 'Load the given modules') do |modules|
|
111
|
+
config_overrides['modules'] += modules
|
112
|
+
end
|
299
113
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
if 'run' == action
|
306
|
-
# Initialize logger
|
307
|
-
now = Time.now
|
308
|
-
|
309
|
-
cfg['log_file'] = cfg['log_file'].frmt({
|
310
|
-
shortdate: now.strftime('%Y-%m-%d'),
|
311
|
-
date: now.strftime('%Y-%m-%d_%H%M%S'),
|
312
|
-
timestamp: now.strftime('%s'),
|
313
|
-
subject: 'spectre',
|
314
|
-
})
|
315
|
-
|
316
|
-
log_dir = File.dirname(cfg['log_file'])
|
317
|
-
FileUtils.makedirs(log_dir)
|
114
|
+
opts.on('-d', '--debug', 'Run in debug mode. Do not use in production!') do
|
115
|
+
require 'debug'
|
116
|
+
config_overrides['debug'] = true
|
117
|
+
end
|
318
118
|
|
319
|
-
|
119
|
+
opts.on('-p KEY=VAL',
|
120
|
+
'--property KEY=VAL',
|
121
|
+
'Override config option. Use `spectre show` to get list of available options') do |option|
|
122
|
+
index = option.index('=')
|
123
|
+
key = option[0...index]
|
124
|
+
val = option[index + 1..]
|
320
125
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
.select { |mod| !cfg['exclude'].include? mod }
|
325
|
-
.each do |mod|
|
326
|
-
begin
|
327
|
-
mod_file = mod + '.rb'
|
328
|
-
spectre_lib_mod = File.join(File.dirname(__dir__), 'lib', mod_file)
|
126
|
+
val = val.split(',') if Spectre::CONFIG[key].is_a? Array
|
127
|
+
val = ['true', '1'].include? val if [true, false].include?(Spectre::CONFIG[key])
|
128
|
+
val = val.to_i if Spectre::CONFIG[key].is_a? Integer
|
329
129
|
|
330
|
-
|
331
|
-
require_relative mod_file
|
130
|
+
opt_path = key.split('.')
|
332
131
|
|
333
|
-
|
334
|
-
require_relative spectre_lib_mod
|
132
|
+
curr_opt = config_overrides
|
335
133
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
puts "Unable to load module #{mod}. Check if the module exists or remove it from your spectre config:\n#{e.message}"
|
341
|
-
exit 1
|
342
|
-
end
|
134
|
+
opt_path.each_with_index do |part, i|
|
135
|
+
if i == opt_path.count - 1
|
136
|
+
curr_opt[part] = val
|
137
|
+
break
|
343
138
|
end
|
344
139
|
|
345
|
-
|
346
|
-
|
347
|
-
cfg['mixin_patterns'].each do |pattern|
|
348
|
-
Dir.glob(pattern).each do|f|
|
349
|
-
require_relative File.join(Dir.pwd, f)
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
|
-
Spectre.configure(cfg)
|
354
|
-
|
355
|
-
Spectre::Logging.debug! if cfg['debug']
|
356
|
-
|
357
|
-
specs = Spectre.specs(cfg['specs'], cfg['tags'])
|
358
|
-
|
359
|
-
unless specs.any?
|
360
|
-
puts "No specs found in #{Dir.pwd}"
|
361
|
-
exit 1
|
140
|
+
curr_opt[part] = {} unless curr_opt.key?(part)
|
141
|
+
curr_opt = curr_opt[part]
|
362
142
|
end
|
363
|
-
|
364
|
-
run_infos = Spectre::Runner.new.run(specs)
|
365
|
-
|
366
|
-
Spectre::Reporter.report(run_infos)
|
367
|
-
|
368
|
-
errors = run_infos.select { |x| x.error? or x.failed? }
|
369
|
-
|
370
|
-
exit 0 if cfg['ignore_failure'] or not errors.any?
|
371
|
-
|
372
|
-
exit 1
|
373
143
|
end
|
374
|
-
end
|
375
144
|
|
145
|
+
opts.separator "\n Common options:"
|
376
146
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
if 'envs' == action
|
383
|
-
exit 1 unless envs.any?
|
384
|
-
puts envs.pretty
|
385
|
-
exit 0
|
386
|
-
end
|
387
|
-
|
388
|
-
|
389
|
-
###########################################
|
390
|
-
# Show
|
391
|
-
###########################################
|
392
|
-
|
393
|
-
|
394
|
-
if 'show' == action
|
395
|
-
puts cfg.pretty
|
396
|
-
exit 0
|
397
|
-
end
|
398
|
-
|
399
|
-
|
400
|
-
###########################################
|
401
|
-
# Dump
|
402
|
-
###########################################
|
403
|
-
|
404
|
-
|
405
|
-
if 'dump' == action
|
406
|
-
puts YAML.dump(cfg)
|
407
|
-
end
|
408
|
-
|
409
|
-
|
410
|
-
###########################################
|
411
|
-
# Cleanup
|
412
|
-
###########################################
|
413
|
-
|
414
|
-
|
415
|
-
if 'cleanup' == action
|
416
|
-
log_file_pattern = cfg['log_file'].gsub('<date>', '*')
|
417
|
-
|
418
|
-
Dir.glob(log_file_pattern).each do |log_file|
|
419
|
-
File.delete(log_file)
|
420
|
-
puts "#{log_file} deleted"
|
147
|
+
opts.on_tail('-v', '--version', 'Print current installed version') do
|
148
|
+
puts Spectre::VERSION
|
149
|
+
exit
|
421
150
|
end
|
422
151
|
|
423
|
-
|
424
|
-
|
425
|
-
|
152
|
+
opts.on_tail('-h', '--help', 'Print this help') do
|
153
|
+
puts opts
|
154
|
+
exit
|
426
155
|
end
|
427
156
|
end
|
428
157
|
|
158
|
+
# Parse options and get action
|
159
|
+
action = options.parse!.shift || 'run'
|
160
|
+
|
161
|
+
# Setup spectre
|
162
|
+
engine = Spectre::Engine.new(config_overrides)
|
163
|
+
|
164
|
+
case action
|
165
|
+
when 'list', 'li', 'ls'
|
166
|
+
engine.formatter.list(engine.list)
|
167
|
+
when 'specs', 'sp'
|
168
|
+
engine.formatter.details(engine.list)
|
169
|
+
when 'describe', 'de'
|
170
|
+
engine.formatter.describe(engine.contexts)
|
171
|
+
when 'run', 'ru'
|
172
|
+
engine.cleanup if cleanup
|
173
|
+
runs = engine.run
|
174
|
+
exit if runs.nil?
|
175
|
+
|
176
|
+
if run_failed and runs.any? { |x| x.status != :success }
|
177
|
+
File.write('.failed', runs
|
178
|
+
.select do |x|
|
179
|
+
x.type == :spec and
|
180
|
+
x.status != :success
|
181
|
+
end
|
182
|
+
.map(&:name)
|
183
|
+
.join("\n"))
|
184
|
+
end
|
429
185
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
#
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
#
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
#
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
186
|
+
puts
|
187
|
+
engine.report(runs)
|
188
|
+
when 'env', 'en'
|
189
|
+
engine.formatter.environment(engine.env)
|
190
|
+
when 'mixins', 'mi', 'mx'
|
191
|
+
search = ARGV.first
|
192
|
+
mixins = engine.mixins.select { |x| search.nil? or x.include? search }
|
193
|
+
engine.formatter.mixins(mixins)
|
194
|
+
when 'collections', 'co'
|
195
|
+
engine.formatter.collections(engine)
|
196
|
+
when 'cleanup', 'cl'
|
197
|
+
engine.cleanup
|
198
|
+
when 'init', 'in'
|
199
|
+
DEFAULT_SPECTRE_CFG = <<~CONTENT
|
200
|
+
log_file: ./logs/spectre_<date>.log
|
201
|
+
env_patterns:
|
202
|
+
- './environments/**/*.env.yml'
|
203
|
+
env_partial_patterns:
|
204
|
+
- './environments/**/*.env.secret.yml'
|
205
|
+
spec_patterns:
|
206
|
+
- './specs/**/*.spec.rb'
|
207
|
+
mixin_patterns:
|
208
|
+
- '../common/**/*.mixin.rb'
|
209
|
+
- './mixins/**/*.mixin.rb'
|
210
|
+
resource_paths:
|
211
|
+
- '../common/resources'
|
212
|
+
- './resources'
|
213
|
+
CONTENT
|
214
|
+
|
215
|
+
DEFAULT_ENV_CFG = <<~CONTENT
|
216
|
+
# Set the environment name.
|
217
|
+
# This property is optional. If not set, the environment name is "default"
|
218
|
+
name: default
|
219
|
+
|
220
|
+
# Define reusable variables
|
221
|
+
# See https://yaml.org/spec/1.2.2/#anchors-and-aliases
|
222
|
+
cert: &cert ./resources/<root_cert>.cer
|
223
|
+
|
224
|
+
# Define HTTP client configs used by the `http` module
|
225
|
+
http:
|
226
|
+
<http_client_name>:
|
227
|
+
# Set the base URL of the API for the client to use
|
228
|
+
base_url: http://localhost:5000/api/v1/
|
229
|
+
|
230
|
+
# Set a custom CA certificate for server cert validation
|
231
|
+
cert: *cert
|
232
|
+
|
233
|
+
# You can set a path to an OpenAPI spec.
|
234
|
+
# This can be a file or a URL.
|
235
|
+
# Request options can then be set by the `endpoint` method
|
236
|
+
# which refers to the operation ID of the OpenAPI endpoint
|
237
|
+
# openapi: [https://localhost:5000]/doc/openapi.json
|
238
|
+
|
239
|
+
# Define basicauth authentication here
|
240
|
+
# Do NOT put credentials in this file.
|
241
|
+
# Use the `*.env.secret.yml` files instead
|
242
|
+
# basic_auth:
|
243
|
+
# username: <username>
|
244
|
+
# password:
|
245
|
+
CONTENT
|
246
|
+
|
247
|
+
DEFAULT_ENV_SECRET_CFG = <<~CONTENT
|
248
|
+
# Define sensitive data here and do NOT commit this file in version control
|
249
|
+
some_secret: thisissensitivedata
|
250
|
+
|
251
|
+
http:
|
252
|
+
<http_client_name>:
|
253
|
+
# basic_auth:
|
254
|
+
# username: <username>
|
255
|
+
# password: <password>
|
256
|
+
CONTENT
|
257
|
+
|
258
|
+
SAMPLE_SPEC = <<~CONTENT
|
259
|
+
# Define a test subject. This can be the name of the component
|
260
|
+
# or the name of a specific feature or requirement.
|
261
|
+
describe '<subject>' do
|
262
|
+
it 'does some http requests', tags: [:sample] do
|
263
|
+
# Use log messages to describe processes
|
264
|
+
log 'doing some http request'
|
265
|
+
|
266
|
+
# Use external or custom module
|
267
|
+
http '<http_client_name>' do
|
268
|
+
# To request a specific endpoint, predefined endpoints
|
269
|
+
# or openapi operations can be used...
|
270
|
+
# endpoint 'getSomeResource'
|
271
|
+
|
272
|
+
# ... or define a request in short form...
|
273
|
+
get 'api/v1/some-resource/{resourceId}'
|
274
|
+
|
275
|
+
# ... or use explicit method and path settings
|
276
|
+
# method 'GET'
|
277
|
+
# path 'api/v1/some-resource/{resourceId}'
|
278
|
+
|
279
|
+
# Set route parameter
|
280
|
+
with resourceId: 42
|
281
|
+
|
282
|
+
# Set query parameters. This method can
|
283
|
+
# be called multiple times.
|
284
|
+
query id: 4295118773,
|
285
|
+
foo: 'bar'
|
286
|
+
|
287
|
+
# Set request headers
|
288
|
+
header 'X-Correlation-Id', '4c2367b1-bfee-4cc2-bdc5-ed17a6a9dd4b'
|
289
|
+
header 'Range', 'bytes=500-999'
|
290
|
+
|
291
|
+
# Set request body as JSON.
|
292
|
+
# This call also sets `application/json` content type.
|
293
|
+
json({
|
294
|
+
"message": "Hello Spectre!"
|
295
|
+
})
|
296
|
+
end
|
502
297
|
|
503
|
-
|
504
|
-
|
298
|
+
# Expect conditions in a single line
|
299
|
+
# If the check fails, the run will continue
|
300
|
+
expect(response.headers['X-Correlation-Id']).not to be empty
|
301
|
+
|
302
|
+
# Assert conditions in a single line...
|
303
|
+
# If an assertion fails, the run will be aborted
|
304
|
+
assert response.code.to be 200
|
305
|
+
|
306
|
+
# ...or assert multiple conditions in a block
|
307
|
+
# All conditions within this block will be evaluated.
|
308
|
+
# After the block finishes and a failure was reported,
|
309
|
+
# the run will be aborted.
|
310
|
+
# When using `expect` instead of `assert` the run will continue.
|
311
|
+
assert 'the correct data to be returned' do
|
312
|
+
report failure 'message not correct' unless respone.json.message == 'Hello World!'
|
313
|
+
report failure 'incorrect number' unless respone.json.number == 42
|
314
|
+
end
|
315
|
+
end
|
505
316
|
end
|
317
|
+
CONTENT
|
318
|
+
|
319
|
+
DEFAULT_GITIGNORE = <<~CONTENT
|
320
|
+
*.code-workspace
|
321
|
+
logs/
|
322
|
+
reports/
|
323
|
+
**/environments/*.env.secret.yml
|
324
|
+
CONTENT
|
325
|
+
|
326
|
+
DEFAULT_GEMFILE = <<~CONTENT
|
327
|
+
source 'https://rubygems.org'
|
328
|
+
|
329
|
+
gem 'spectre-core'
|
330
|
+
gem 'spectre-http'
|
331
|
+
# gem 'spectre-mysql'
|
332
|
+
# gem 'spectre-ssh'
|
333
|
+
# gem 'spectre-ftp'
|
334
|
+
# gem 'spectre-curl'
|
335
|
+
# gem 'spectre-git'
|
336
|
+
# gem 'spectre-rabbitmq'
|
337
|
+
# gem 'spectre-reporter-junit'
|
338
|
+
# gem 'spectre-reporter-vstest'
|
339
|
+
# gem 'spectre-reporter-html'
|
340
|
+
CONTENT
|
506
341
|
|
507
|
-
expect 'a message to exist' do
|
508
|
-
response.json.message.should_not_be_empty
|
509
|
-
end
|
510
|
-
end
|
511
|
-
end
|
512
|
-
]
|
513
|
-
|
514
|
-
DEFAULT_GITIGNORE = %[*.code-workspace
|
515
|
-
logs/
|
516
|
-
reports/
|
517
|
-
**/environments/*.env.secret.yml
|
518
|
-
]
|
519
|
-
|
520
|
-
DEFAULT_GEMFILE = %[source 'https://rubygems.org'
|
521
|
-
|
522
|
-
gem 'spectre-core', '>= #{Spectre::VERSION}'
|
523
|
-
# gem 'spectre-mysql', '>= 1.0.0'
|
524
|
-
# gem 'spectre-ssh', '>= 1.0.2'
|
525
|
-
# gem 'spectre-ftp', '>= 1.0.0'
|
526
|
-
# gem 'spectre-curl', '>= 1.0.0'
|
527
|
-
# gem 'spectre-git', '>= 0.2.1'
|
528
|
-
# gem 'spectre-reporter-junit', '>= 1.0.0'
|
529
|
-
# gem 'spectre-reporter-vstest', '>= 1.0.1'
|
530
|
-
# gem 'spectre-reporter-html', '>= 1.0.0'
|
531
|
-
]
|
532
|
-
|
533
|
-
if 'init' == action
|
534
342
|
DEFAULT_FILES = [
|
535
343
|
['./environments/default.env.yml', DEFAULT_ENV_CFG],
|
536
344
|
['./environments/default.env.secret.yml', DEFAULT_ENV_SECRET_CFG],
|
@@ -540,15 +348,15 @@ if 'init' == action
|
|
540
348
|
['./Gemfile', DEFAULT_GEMFILE],
|
541
349
|
]
|
542
350
|
|
543
|
-
%w
|
351
|
+
%w[environments logs modules reports resources specs].each do |dir_name|
|
544
352
|
Dir.mkdir(dir_name) unless File.directory? dir_name
|
545
353
|
end
|
546
354
|
|
547
355
|
DEFAULT_FILES.each do |file, content|
|
548
|
-
unless File.exist? file
|
549
|
-
File.write(file, content)
|
550
|
-
end
|
356
|
+
File.write(file, content) unless File.exist? file
|
551
357
|
end
|
552
|
-
|
553
|
-
|
358
|
+
else
|
359
|
+
puts "unknown action #{action.inspect}\n".red
|
360
|
+
puts options
|
361
|
+
exit 1
|
554
362
|
end
|