spectre-core 1.12.0 → 1.12.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.
data/exe/spectre CHANGED
@@ -1,516 +1,516 @@
1
- #! /usr/bin/ruby
2
- # frozen_string_literal: true
3
-
4
- require 'yaml'
5
- require 'ostruct'
6
- require 'optparse'
7
- require 'fileutils'
8
- require 'ectoplasm'
9
-
10
- require_relative '../lib/spectre'
11
-
12
-
13
- DEFAULT_CONFIG = {
14
- 'config_file' => './spectre.yml',
15
- 'environment' => 'default',
16
- 'specs' => [],
17
- 'tags' => [],
18
- 'colored' => true,
19
- 'verbose' => false,
20
- 'reporters' => [
21
- 'Spectre::Reporter::Console',
22
- ],
23
- 'loggers' => [
24
- 'Spectre::Logger::Console',
25
- 'Spectre::Logger::File',
26
- ],
27
- 'log_file' => './logs/spectre_<date>.log',
28
- 'log_format' => {
29
- 'console' => {
30
- 'indent' => 2,
31
- 'width' => 80,
32
- 'end_context' => nil,
33
- 'separator' => '<indent><desc>',
34
- },
35
- 'file' => {
36
- 'separator' => '-- <desc>',
37
- 'start_group' => "-- Start '<desc>'",
38
- 'end_group' => "-- End '<desc>'",
39
- },
40
- },
41
- 'debug' => false,
42
- 'out_path' => './reports',
43
- 'secure_keys' => ['password', 'secret', 'token', 'secure', 'authorization'],
44
- 'spec_patterns' => ['./specs/**/*.spec.rb'],
45
- 'mixin_patterns' => ['../common/mixins/**/*.mixin.rb', './mixins/**/*.mixin.rb'],
46
- 'env_patterns' => ['./environments/**/*.env.yml'],
47
- 'env_partial_patterns' => ['./environments/**/*.env.secret.yml'],
48
- 'resource_paths' => ['../common/resources', './resources'],
49
- 'modules' => [
50
- 'spectre/helpers',
51
- 'spectre/reporter/console',
52
- 'spectre/reporter/junit',
53
- 'spectre/logger/console',
54
- 'spectre/logger/file',
55
- 'spectre/assertion',
56
- 'spectre/diagnostic',
57
- 'spectre/environment',
58
- 'spectre/mixin',
59
- 'spectre/bag',
60
- 'spectre/http',
61
- 'spectre/http/basic_auth',
62
- 'spectre/http/keystone',
63
- 'spectre/resources',
64
- ],
65
- 'include' => [
66
-
67
- ],
68
- 'exclude' => [
69
-
70
- ],
71
- }
72
-
73
-
74
- cmd_options = {}
75
-
76
- opt_parser = OptionParser.new do |opts|
77
- opts.banner = %{Spectre #{Spectre::VERSION}
78
-
79
- Usage: spectre [command] [options]
80
-
81
- Commands:
82
- list List specs
83
- run Run specs (default)
84
- show Print current environment settings
85
- dump Dumps the given environment in YAML format to console
86
- init Initializes a new spectre project
87
-
88
- Specific options:}
89
-
90
- opts.on('-s SPEC,SPEC', '--specs SPEC,SPEC', Array, 'The specs to run') do |specs|
91
- cmd_options['specs'] = specs
92
- end
93
-
94
- opts.on('-t TAG,TAG', '--tags TAG,TAG', Array, 'Run only specs with given tags') do |tags|
95
- cmd_options['tags'] = tags
96
- end
97
-
98
- opts.on('-e NAME', '--env NAME', 'Name of the environment to load') do |env_name|
99
- cmd_options['environment'] = env_name
100
- end
101
-
102
- opts.on('-c FILE', '--config FILE', 'Config file to load') do |file_path|
103
- cmd_options['config_file'] = file_path
104
- end
105
-
106
- opts.on('--spec-pattern PATTERN', Array, 'File pattern for spec files') do |spec_pattern|
107
- cmd_options['spec_patterns'] = spec_pattern
108
- end
109
-
110
- opts.on('--env-pattern PATTERN', Array, 'File pattern for environment files') do |env_patterns|
111
- cmd_options['env_patterns'] = env_patterns
112
- end
113
-
114
- opts.on('--no-color', 'Disable colored output') do
115
- cmd_options['colored'] = false
116
- end
117
-
118
- opts.on('--ignore-failure', 'Always exit with code 0') do
119
- cmd_options['ignore_failure'] = true
120
- end
121
-
122
- opts.on('-o PATH', '--out PATH', 'Output directory path') do |path|
123
- cmd_options['out_path'] = File.absolute_path(path)
124
- end
125
-
126
- opts.on('-r NAME', '--reporters NAME', Array, "A list of reporters to use") do |reporters|
127
- cmd_options['reporters'] = reporters
128
- end
129
-
130
- opts.on('-d', '--debug', "Run in debug mode") do
131
- cmd_options['debug'] = true
132
- end
133
-
134
- opts.on('-p KEY=VAL', '--property KEY=VAL', "Override config option. Use `spectre show` to get list of available options") do |option|
135
- key, val = option.split '='
136
- val = val.split ',' if DEFAULT_CONFIG[key].is_a? Array
137
- val = ['true', '1'].include? val if [true, false].include? DEFAULT_CONFIG[key]
138
- val = val.to_i if DEFAULT_CONFIG[key].is_a? Integer
139
- cmd_options[key] = val
140
-
141
- curr_opt = cmd_options
142
- (key.split '.').each do |k|
143
- curr_opt[k] = {} unless curr_opt.key? k
144
- end
145
- curr_opt = val
146
- end
147
-
148
- opts.separator "\nCommon options:"
149
-
150
- opts.on_tail('--version', 'Print current installed version') do
151
- puts Spectre::VERSION
152
- exit
153
- end
154
-
155
- opts.on_tail('-h', '--help', 'Print this help') do
156
- puts opts
157
- exit
158
- end
159
- end.parse!
160
-
161
-
162
- action = ARGV[0] || 'run'
163
-
164
-
165
- ###########################################
166
- # Load Config
167
- ###########################################
168
-
169
-
170
- cfg = {}
171
- cfg.deep_merge! DEFAULT_CONFIG
172
-
173
- global_config_file = File.join File.expand_path('~'), '.spectre'
174
-
175
- if File.exists? global_config_file
176
- global_options = YAML.load_file(global_config_file)
177
- cfg.deep_merge! global_options if global_options
178
- end
179
-
180
- config_file = cmd_options['config_file'] || cfg['config_file']
181
-
182
- if File.exists? config_file
183
- file_options = YAML.load_file(config_file)
184
- cfg.deep_merge! file_options
185
- Dir.chdir File.dirname(config_file)
186
- end
187
-
188
- cfg.deep_merge! cmd_options
189
-
190
-
191
- ###########################################
192
- # Load Environment
193
- ###########################################
194
-
195
-
196
- envs = {}
197
- read_env_files = {}
198
- cfg['env_patterns'].each do |pattern|
199
- Dir.glob(pattern).each do|f|
200
- spec_env = YAML.load_file(f) || {}
201
-
202
- name = spec_env['name'] || 'default'
203
-
204
- if envs.key? name
205
- existing_env_file = read_env_files[name]
206
- puts "Duplicate environment definition detected with name #{name} in '#{f}'. Previously defined in '#{existing_env_file}'"
207
- exit 1
208
- end
209
-
210
- read_env_files[name] = f
211
- envs[name] = spec_env
212
- end
213
- end
214
-
215
- # Merge partial environment configs with existing environments
216
- cfg['env_partial_patterns'].each do |pattern|
217
- Dir.glob(pattern).each do|f|
218
- partial_env = YAML.load_file(f)
219
- name = partial_env.delete('name') || 'default'
220
- next unless envs.key? name
221
-
222
- envs[name].deep_merge! partial_env
223
- end
224
- end
225
-
226
- env = envs[cfg['environment']]
227
- cfg.merge! env if env
228
-
229
-
230
- String.colored! if cfg['colored']
231
-
232
- # Load environment exlicitly before loading specs to make it available in spec definition
233
- require_relative '../lib/spectre/environment' unless cfg['exclude'].include? 'spectre/environment'
234
- Spectre.configure(cfg)
235
-
236
-
237
- ###########################################
238
- # Load Specs
239
- ###########################################
240
-
241
-
242
- cfg['spec_patterns'].each do |pattern|
243
- Dir.glob(pattern).each do|f|
244
- require_relative File.join(Dir.pwd, f)
245
- end
246
- end
247
-
248
-
249
- ###########################################
250
- # List specs
251
- ###########################################
252
-
253
-
254
- if 'list' == action
255
- colors = [:blue, :magenta, :yellow, :green]
256
- specs = Spectre.specs(cfg['specs'], cfg['tags'])
257
-
258
- exit 1 unless specs.any?
259
-
260
- counter = 0
261
-
262
- specs.group_by { |x| x.subject }.each do |subject, spec_group|
263
- spec_group.each do |spec|
264
- tags = spec.tags.map { |x| '#' + x.to_s }.join ' '
265
- desc = subject.desc
266
- desc += ' - ' + spec.context.__desc + ' -' if spec.context.__desc
267
- desc += ' ' + spec.desc
268
- puts "[#{spec.name}]".send(colors[counter % colors.length]) + " #{desc} #{tags.cyan}"
269
- end
270
-
271
- counter += 1
272
- end
273
-
274
- exit 0
275
- end
276
-
277
-
278
- ###########################################
279
- # Run
280
- ###########################################
281
-
282
-
283
- if 'run' == action
284
- # Initialize logger
285
- now = Time.now
286
-
287
- cfg['log_file'] = cfg['log_file'].frmt(
288
- {
289
- shortdate: now.strftime('%Y-%m-%d'),
290
- date: now.strftime('%Y-%m-%d_%H%M%S'),
291
- timestamp: now.strftime('%s'),
292
- subject: 'spectre',
293
- })
294
-
295
- log_dir = File.dirname cfg['log_file']
296
- FileUtils.makedirs log_dir unless Dir.exists? log_dir
297
-
298
- # Load Modules
299
-
300
- cfg['modules']
301
- .concat(cfg['include'])
302
- .select { |mod| !cfg['exclude'].include? mod }
303
- .each do |mod|
304
- begin
305
- mod_file = mod + '.rb'
306
- spectre_lib_mod = File.join(File.dirname(__dir__), 'lib', mod_file)
307
-
308
- if File.exists? mod_file
309
- require_relative mod_file
310
-
311
- elsif File.exists? spectre_lib_mod
312
- require_relative spectre_lib_mod
313
-
314
- else
315
- require mod
316
- end
317
- rescue LoadError => e
318
- puts "Unable to load module #{mod}. Check if the module exists or remove it from your spectre config:\n#{e.message}"
319
- exit 1
320
- end
321
- end
322
-
323
- # Load mixins
324
-
325
- cfg['mixin_patterns'].each do |pattern|
326
- Dir.glob(pattern).each do|f|
327
- require_relative File.join(Dir.pwd, f)
328
- end
329
- end
330
-
331
- Spectre.configure(cfg)
332
-
333
- Spectre::Logger.debug! if cfg['debug']
334
-
335
- cfg['loggers'].each do |logger_name|
336
- logger = Kernel.const_get(logger_name).new(cfg)
337
- Spectre::Logger.add(logger)
338
- end if cfg['loggers']
339
-
340
- specs = Spectre.specs(cfg['specs'], cfg['tags'])
341
-
342
- unless specs.any?
343
- puts "No specs found in #{Dir.pwd}"
344
- exit 1
345
- end
346
-
347
- run_infos = Spectre::Runner.new.run(specs)
348
-
349
- cfg['reporters'].each do |reporter|
350
- reporter = Kernel.const_get(reporter).new(cfg)
351
- reporter.report(run_infos)
352
- end
353
-
354
- errors = run_infos.select { |x| nil != x.error or nil != x.failure }
355
-
356
- exit 0 if cfg['ignore_failure'] or not errors.any?
357
-
358
- exit 1
359
- end
360
-
361
-
362
- ###########################################
363
- # Envs
364
- ###########################################
365
-
366
-
367
- if 'envs' == action
368
- exit 1 unless envs.any?
369
- puts envs.pretty
370
- exit 0
371
- end
372
-
373
-
374
- ###########################################
375
- # Show
376
- ###########################################
377
-
378
-
379
- if 'show' == action
380
- puts cfg.pretty
381
- exit 0
382
- end
383
-
384
-
385
- ###########################################
386
- # Dump
387
- ###########################################
388
-
389
-
390
- if 'dump' == action
391
- puts YAML.dump(cfg)
392
- end
393
-
394
-
395
- ###########################################
396
- # Init
397
- ###########################################
398
-
399
- DEFAULT_SPECTRE_CFG = %{log_file: ./logs/spectre_<date>.log
400
- env_patterns:
401
- - './environments/**/*.env.yml'
402
- env_partial_patterns:
403
- - './environments/**/*.env.secret.yml'
404
- spec_patterns:
405
- - './specs/**/*.spec.rb'
406
- mixin_patterns:
407
- - '../common/**/*.mixin.rb'
408
- - './mixins/**/*.mixin.rb'
409
- resource_paths:
410
- - '../common/resources'
411
- - './resources'
412
- }
413
-
414
-
415
- DEFAULT_ENV_CFG = %{cert: &cert ./resources/<root_cert>.cer
416
- http:
417
- <http_client_name>:
418
- base_url: http://localhost:5000/api/v1/
419
- # basic_auth:
420
- # username: <username>
421
- # password: <password>
422
- # keystone:
423
- # url: https://<keystone_url>/main/v3/
424
- # username: <username>
425
- # password: <password>
426
- # project: <project>
427
- # domain: <domain>
428
- # cert: *cert
429
- # ssh:
430
- # <ssh_client_name>:
431
- # host: <hostname>
432
- # username: <username>
433
- # password: <password>
434
- }
435
-
436
- DEFAULT_ENV_SECRET_CFG = %{http:
437
- <http_client_name>:
438
- # basic_auth:
439
- # username: <username>
440
- # password: <password>
441
- # keystone:
442
- # username: <username>
443
- # password: <password>
444
- # ssh:
445
- # <ssh_client_name>:
446
- # username: <username>
447
- # password: <password>
448
- }
449
-
450
- SAMPLE_SPEC = %[describe '<subject>' do
451
- it 'does some http requests', tags: [:sample] do
452
- log 'doing some http request'
453
-
454
- http '<http_client_name>' do
455
- auth 'basic'
456
- # auth 'keystone'
457
- method 'GET'
458
- path 'path/to/resource'
459
- param 'id', 4295118773
460
- param 'foo', 'bar'
461
- header 'X-Correlation-Id', '4c2367b1-bfee-4cc2-bdc5-ed17a6a9dd4b'
462
- header 'Range', 'bytes=500-999'
463
- json({
464
- "message": "Hello Spectre!"
465
- })
466
- end
467
-
468
- expect 'the response code to be 200' do
469
- response.code.should_be 200
470
- end
471
-
472
- expect 'a message to exist' do
473
- response.json.message.should_not_be nil
474
- end
475
- end
476
- end
477
- ]
478
-
479
- DEFAULT_GITIGNORE = %[*.code-workspace
480
- logs/
481
- reports/
482
- **/environments/*.env.secret.yml
483
- ]
484
-
485
- DEFAULT_GEMFILE = %[source 'https://rubygems.org'
486
-
487
- gem 'spectre-core', '>= #{Spectre::VERSION}'
488
- # gem 'spectre-mysql', '>= 1.0.0'
489
- # gem 'spectre-ssh', '>= 1.0.0'
490
- # gem 'spectre-ftp', '>= 1.0.0'
491
- # gem 'spectre-curl', '>= 1.0.0'
492
- # gem 'spectre-git', '>= 0.1.0'
493
- ]
494
-
495
- if 'init' == action
496
- DEFAULT_FILES = [
497
- ['./environments/default.env.yml', DEFAULT_ENV_CFG],
498
- ['./environments/default.env.secret.yml', DEFAULT_ENV_SECRET_CFG],
499
- ['./specs/sample.spec.rb', SAMPLE_SPEC],
500
- ['./spectre.yml', DEFAULT_SPECTRE_CFG],
501
- ['./.gitignore', DEFAULT_GITIGNORE],
502
- ['./Gemfile', DEFAULT_GEMFILE],
503
- ]
504
-
505
- %w(environments logs specs).each do |dir_name|
506
- Dir.mkdir(dir_name) unless File.directory? dir_name
507
- end
508
-
509
- DEFAULT_FILES.each do |file, content|
510
- unless File.exists? file
511
- File.write(file, content)
512
- end
513
- end
514
-
515
- exit 0
516
- end
1
+ #! /usr/bin/ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml'
5
+ require 'ostruct'
6
+ require 'optparse'
7
+ require 'fileutils'
8
+ require 'ectoplasm'
9
+
10
+ require_relative '../lib/spectre'
11
+
12
+
13
+ DEFAULT_CONFIG = {
14
+ 'config_file' => './spectre.yml',
15
+ 'environment' => 'default',
16
+ 'specs' => [],
17
+ 'tags' => [],
18
+ 'colored' => true,
19
+ 'verbose' => false,
20
+ 'reporters' => [
21
+ 'Spectre::Reporter::Console',
22
+ ],
23
+ 'loggers' => [
24
+ 'Spectre::Logger::Console',
25
+ 'Spectre::Logger::File',
26
+ ],
27
+ 'log_file' => './logs/spectre_<date>.log',
28
+ 'log_format' => {
29
+ 'console' => {
30
+ 'indent' => 2,
31
+ 'width' => 80,
32
+ 'end_context' => nil,
33
+ 'separator' => '<indent><desc>',
34
+ },
35
+ 'file' => {
36
+ 'separator' => '-- <desc>',
37
+ 'start_group' => "-- Start '<desc>'",
38
+ 'end_group' => "-- End '<desc>'",
39
+ },
40
+ },
41
+ 'debug' => false,
42
+ 'out_path' => './reports',
43
+ 'secure_keys' => ['password', 'secret', 'token', 'secure', 'authorization'],
44
+ 'spec_patterns' => ['./specs/**/*.spec.rb'],
45
+ 'mixin_patterns' => ['../common/mixins/**/*.mixin.rb', './mixins/**/*.mixin.rb'],
46
+ 'env_patterns' => ['./environments/**/*.env.yml'],
47
+ 'env_partial_patterns' => ['./environments/**/*.env.secret.yml'],
48
+ 'resource_paths' => ['../common/resources', './resources'],
49
+ 'modules' => [
50
+ 'spectre/helpers',
51
+ 'spectre/reporter/console',
52
+ 'spectre/reporter/junit',
53
+ 'spectre/logger/console',
54
+ 'spectre/logger/file',
55
+ 'spectre/assertion',
56
+ 'spectre/diagnostic',
57
+ 'spectre/environment',
58
+ 'spectre/mixin',
59
+ 'spectre/bag',
60
+ 'spectre/http',
61
+ 'spectre/http/basic_auth',
62
+ 'spectre/http/keystone',
63
+ 'spectre/resources',
64
+ ],
65
+ 'include' => [
66
+
67
+ ],
68
+ 'exclude' => [
69
+
70
+ ],
71
+ }
72
+
73
+
74
+ cmd_options = {}
75
+
76
+ opt_parser = OptionParser.new do |opts|
77
+ opts.banner = %{Spectre #{Spectre::VERSION}
78
+
79
+ Usage: spectre [command] [options]
80
+
81
+ Commands:
82
+ list List specs
83
+ run Run specs (default)
84
+ show Print current environment settings
85
+ dump Dumps the given environment in YAML format to console
86
+ init Initializes a new spectre project
87
+
88
+ Specific options:}
89
+
90
+ opts.on('-s SPEC,SPEC', '--specs SPEC,SPEC', Array, 'The specs to run') do |specs|
91
+ cmd_options['specs'] = specs
92
+ end
93
+
94
+ opts.on('-t TAG,TAG', '--tags TAG,TAG', Array, 'Run only specs with given tags') do |tags|
95
+ cmd_options['tags'] = tags
96
+ end
97
+
98
+ opts.on('-e NAME', '--env NAME', 'Name of the environment to load') do |env_name|
99
+ cmd_options['environment'] = env_name
100
+ end
101
+
102
+ opts.on('-c FILE', '--config FILE', 'Config file to load') do |file_path|
103
+ cmd_options['config_file'] = file_path
104
+ end
105
+
106
+ opts.on('--spec-pattern PATTERN', Array, 'File pattern for spec files') do |spec_pattern|
107
+ cmd_options['spec_patterns'] = spec_pattern
108
+ end
109
+
110
+ opts.on('--env-pattern PATTERN', Array, 'File pattern for environment files') do |env_patterns|
111
+ cmd_options['env_patterns'] = env_patterns
112
+ end
113
+
114
+ opts.on('--no-color', 'Disable colored output') do
115
+ cmd_options['colored'] = false
116
+ end
117
+
118
+ opts.on('--ignore-failure', 'Always exit with code 0') do
119
+ cmd_options['ignore_failure'] = true
120
+ end
121
+
122
+ opts.on('-o PATH', '--out PATH', 'Output directory path') do |path|
123
+ cmd_options['out_path'] = File.absolute_path(path)
124
+ end
125
+
126
+ opts.on('-r NAME', '--reporters NAME', Array, "A list of reporters to use") do |reporters|
127
+ cmd_options['reporters'] = reporters
128
+ end
129
+
130
+ opts.on('-d', '--debug', "Run in debug mode") do
131
+ cmd_options['debug'] = true
132
+ end
133
+
134
+ opts.on('-p KEY=VAL', '--property KEY=VAL', "Override config option. Use `spectre show` to get list of available options") do |option|
135
+ key, val = option.split '='
136
+ val = val.split ',' if DEFAULT_CONFIG[key].is_a? Array
137
+ val = ['true', '1'].include? val if [true, false].include? DEFAULT_CONFIG[key]
138
+ val = val.to_i if DEFAULT_CONFIG[key].is_a? Integer
139
+ cmd_options[key] = val
140
+
141
+ curr_opt = cmd_options
142
+ (key.split '.').each do |k|
143
+ curr_opt[k] = {} unless curr_opt.key? k
144
+ end
145
+ curr_opt = val
146
+ end
147
+
148
+ opts.separator "\nCommon options:"
149
+
150
+ opts.on_tail('--version', 'Print current installed version') do
151
+ puts Spectre::VERSION
152
+ exit
153
+ end
154
+
155
+ opts.on_tail('-h', '--help', 'Print this help') do
156
+ puts opts
157
+ exit
158
+ end
159
+ end.parse!
160
+
161
+
162
+ action = ARGV[0] || 'run'
163
+
164
+
165
+ ###########################################
166
+ # Load Config
167
+ ###########################################
168
+
169
+
170
+ cfg = {}
171
+ cfg.deep_merge! DEFAULT_CONFIG
172
+
173
+ global_config_file = File.join File.expand_path('~'), '.spectre'
174
+
175
+ if File.exists? global_config_file
176
+ global_options = YAML.load_file(global_config_file)
177
+ cfg.deep_merge! global_options if global_options
178
+ end
179
+
180
+ config_file = cmd_options['config_file'] || cfg['config_file']
181
+
182
+ if File.exists? config_file
183
+ file_options = YAML.load_file(config_file)
184
+ cfg.deep_merge! file_options
185
+ Dir.chdir File.dirname(config_file)
186
+ end
187
+
188
+ cfg.deep_merge! cmd_options
189
+
190
+
191
+ ###########################################
192
+ # Load Environment
193
+ ###########################################
194
+
195
+
196
+ envs = {}
197
+ read_env_files = {}
198
+ cfg['env_patterns'].each do |pattern|
199
+ Dir.glob(pattern).each do|f|
200
+ spec_env = YAML.load_file(f) || {}
201
+
202
+ name = spec_env['name'] || 'default'
203
+
204
+ if envs.key? name
205
+ existing_env_file = read_env_files[name]
206
+ puts "Duplicate environment definition detected with name #{name} in '#{f}'. Previously defined in '#{existing_env_file}'"
207
+ exit 1
208
+ end
209
+
210
+ read_env_files[name] = f
211
+ envs[name] = spec_env
212
+ end
213
+ end
214
+
215
+ # Merge partial environment configs with existing environments
216
+ cfg['env_partial_patterns'].each do |pattern|
217
+ Dir.glob(pattern).each do|f|
218
+ partial_env = YAML.load_file(f)
219
+ name = partial_env.delete('name') || 'default'
220
+ next unless envs.key? name
221
+
222
+ envs[name].deep_merge! partial_env
223
+ end
224
+ end
225
+
226
+ env = envs[cfg['environment']]
227
+ cfg.merge! env if env
228
+
229
+
230
+ String.colored! if cfg['colored']
231
+
232
+ # Load environment exlicitly before loading specs to make it available in spec definition
233
+ require_relative '../lib/spectre/environment' unless cfg['exclude'].include? 'spectre/environment'
234
+ Spectre.configure(cfg)
235
+
236
+
237
+ ###########################################
238
+ # Load Specs
239
+ ###########################################
240
+
241
+
242
+ cfg['spec_patterns'].each do |pattern|
243
+ Dir.glob(pattern).each do|f|
244
+ require_relative File.join(Dir.pwd, f)
245
+ end
246
+ end
247
+
248
+
249
+ ###########################################
250
+ # List specs
251
+ ###########################################
252
+
253
+
254
+ if 'list' == action
255
+ colors = [:blue, :magenta, :yellow, :green]
256
+ specs = Spectre.specs(cfg['specs'], cfg['tags'])
257
+
258
+ exit 1 unless specs.any?
259
+
260
+ counter = 0
261
+
262
+ specs.group_by { |x| x.subject }.each do |subject, spec_group|
263
+ spec_group.each do |spec|
264
+ tags = spec.tags.map { |x| '#' + x.to_s }.join ' '
265
+ desc = subject.desc
266
+ desc += ' - ' + spec.context.__desc + ' -' if spec.context.__desc
267
+ desc += ' ' + spec.desc
268
+ puts "[#{spec.name}]".send(colors[counter % colors.length]) + " #{desc} #{tags.cyan}"
269
+ end
270
+
271
+ counter += 1
272
+ end
273
+
274
+ exit 0
275
+ end
276
+
277
+
278
+ ###########################################
279
+ # Run
280
+ ###########################################
281
+
282
+
283
+ if 'run' == action
284
+ # Initialize logger
285
+ now = Time.now
286
+
287
+ cfg['log_file'] = cfg['log_file'].frmt(
288
+ {
289
+ shortdate: now.strftime('%Y-%m-%d'),
290
+ date: now.strftime('%Y-%m-%d_%H%M%S'),
291
+ timestamp: now.strftime('%s'),
292
+ subject: 'spectre',
293
+ })
294
+
295
+ log_dir = File.dirname cfg['log_file']
296
+ FileUtils.makedirs log_dir unless Dir.exists? log_dir
297
+
298
+ # Load Modules
299
+
300
+ cfg['modules']
301
+ .concat(cfg['include'])
302
+ .select { |mod| !cfg['exclude'].include? mod }
303
+ .each do |mod|
304
+ begin
305
+ mod_file = mod + '.rb'
306
+ spectre_lib_mod = File.join(File.dirname(__dir__), 'lib', mod_file)
307
+
308
+ if File.exists? mod_file
309
+ require_relative mod_file
310
+
311
+ elsif File.exists? spectre_lib_mod
312
+ require_relative spectre_lib_mod
313
+
314
+ else
315
+ require mod
316
+ end
317
+ rescue LoadError => e
318
+ puts "Unable to load module #{mod}. Check if the module exists or remove it from your spectre config:\n#{e.message}"
319
+ exit 1
320
+ end
321
+ end
322
+
323
+ # Load mixins
324
+
325
+ cfg['mixin_patterns'].each do |pattern|
326
+ Dir.glob(pattern).each do|f|
327
+ require_relative File.join(Dir.pwd, f)
328
+ end
329
+ end
330
+
331
+ Spectre.configure(cfg)
332
+
333
+ Spectre::Logger.debug! if cfg['debug']
334
+
335
+ cfg['loggers'].each do |logger_name|
336
+ logger = Kernel.const_get(logger_name).new(cfg)
337
+ Spectre::Logger.add(logger)
338
+ end if cfg['loggers']
339
+
340
+ specs = Spectre.specs(cfg['specs'], cfg['tags'])
341
+
342
+ unless specs.any?
343
+ puts "No specs found in #{Dir.pwd}"
344
+ exit 1
345
+ end
346
+
347
+ run_infos = Spectre::Runner.new.run(specs)
348
+
349
+ cfg['reporters'].each do |reporter|
350
+ reporter = Kernel.const_get(reporter).new(cfg)
351
+ reporter.report(run_infos)
352
+ end
353
+
354
+ errors = run_infos.select { |x| nil != x.error or nil != x.failure }
355
+
356
+ exit 0 if cfg['ignore_failure'] or not errors.any?
357
+
358
+ exit 1
359
+ end
360
+
361
+
362
+ ###########################################
363
+ # Envs
364
+ ###########################################
365
+
366
+
367
+ if 'envs' == action
368
+ exit 1 unless envs.any?
369
+ puts envs.pretty
370
+ exit 0
371
+ end
372
+
373
+
374
+ ###########################################
375
+ # Show
376
+ ###########################################
377
+
378
+
379
+ if 'show' == action
380
+ puts cfg.pretty
381
+ exit 0
382
+ end
383
+
384
+
385
+ ###########################################
386
+ # Dump
387
+ ###########################################
388
+
389
+
390
+ if 'dump' == action
391
+ puts YAML.dump(cfg)
392
+ end
393
+
394
+
395
+ ###########################################
396
+ # Init
397
+ ###########################################
398
+
399
+ DEFAULT_SPECTRE_CFG = %{log_file: ./logs/spectre_<date>.log
400
+ env_patterns:
401
+ - './environments/**/*.env.yml'
402
+ env_partial_patterns:
403
+ - './environments/**/*.env.secret.yml'
404
+ spec_patterns:
405
+ - './specs/**/*.spec.rb'
406
+ mixin_patterns:
407
+ - '../common/**/*.mixin.rb'
408
+ - './mixins/**/*.mixin.rb'
409
+ resource_paths:
410
+ - '../common/resources'
411
+ - './resources'
412
+ }
413
+
414
+
415
+ DEFAULT_ENV_CFG = %{cert: &cert ./resources/<root_cert>.cer
416
+ http:
417
+ <http_client_name>:
418
+ base_url: http://localhost:5000/api/v1/
419
+ # basic_auth:
420
+ # username: <username>
421
+ # password: <password>
422
+ # keystone:
423
+ # url: https://<keystone_url>/main/v3/
424
+ # username: <username>
425
+ # password: <password>
426
+ # project: <project>
427
+ # domain: <domain>
428
+ # cert: *cert
429
+ # ssh:
430
+ # <ssh_client_name>:
431
+ # host: <hostname>
432
+ # username: <username>
433
+ # password: <password>
434
+ }
435
+
436
+ DEFAULT_ENV_SECRET_CFG = %{http:
437
+ <http_client_name>:
438
+ # basic_auth:
439
+ # username: <username>
440
+ # password: <password>
441
+ # keystone:
442
+ # username: <username>
443
+ # password: <password>
444
+ # ssh:
445
+ # <ssh_client_name>:
446
+ # username: <username>
447
+ # password: <password>
448
+ }
449
+
450
+ SAMPLE_SPEC = %[describe '<subject>' do
451
+ it 'does some http requests', tags: [:sample] do
452
+ log 'doing some http request'
453
+
454
+ http '<http_client_name>' do
455
+ auth 'basic'
456
+ # auth 'keystone'
457
+ method 'GET'
458
+ path 'path/to/resource'
459
+ param 'id', 4295118773
460
+ param 'foo', 'bar'
461
+ header 'X-Correlation-Id', '4c2367b1-bfee-4cc2-bdc5-ed17a6a9dd4b'
462
+ header 'Range', 'bytes=500-999'
463
+ json({
464
+ "message": "Hello Spectre!"
465
+ })
466
+ end
467
+
468
+ expect 'the response code to be 200' do
469
+ response.code.should_be 200
470
+ end
471
+
472
+ expect 'a message to exist' do
473
+ response.json.message.should_not_be nil
474
+ end
475
+ end
476
+ end
477
+ ]
478
+
479
+ DEFAULT_GITIGNORE = %[*.code-workspace
480
+ logs/
481
+ reports/
482
+ **/environments/*.env.secret.yml
483
+ ]
484
+
485
+ DEFAULT_GEMFILE = %[source 'https://rubygems.org'
486
+
487
+ gem 'spectre-core', '>= #{Spectre::VERSION}'
488
+ # gem 'spectre-mysql', '>= 1.0.0'
489
+ # gem 'spectre-ssh', '>= 1.0.0'
490
+ # gem 'spectre-ftp', '>= 1.0.0'
491
+ # gem 'spectre-curl', '>= 1.0.0'
492
+ # gem 'spectre-git', '>= 0.1.0'
493
+ ]
494
+
495
+ if 'init' == action
496
+ DEFAULT_FILES = [
497
+ ['./environments/default.env.yml', DEFAULT_ENV_CFG],
498
+ ['./environments/default.env.secret.yml', DEFAULT_ENV_SECRET_CFG],
499
+ ['./specs/sample.spec.rb', SAMPLE_SPEC],
500
+ ['./spectre.yml', DEFAULT_SPECTRE_CFG],
501
+ ['./.gitignore', DEFAULT_GITIGNORE],
502
+ ['./Gemfile', DEFAULT_GEMFILE],
503
+ ]
504
+
505
+ %w(environments logs specs).each do |dir_name|
506
+ Dir.mkdir(dir_name) unless File.directory? dir_name
507
+ end
508
+
509
+ DEFAULT_FILES.each do |file, content|
510
+ unless File.exists? file
511
+ File.write(file, content)
512
+ end
513
+ end
514
+
515
+ exit 0
516
+ end