spectre-core 1.12.0 → 1.12.1

Sign up to get free protection for your applications and to get access to all the features.
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