spectre-core 1.12.1 → 1.12.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77d4435f515a88fa60eef0a6c43b90975fb6ae1168a60294ee2847536ff51a67
4
- data.tar.gz: 1366a0d67961a565bf2020d9fa9e6724f5df4b4add1ac58712ed2cdfe992e74d
3
+ metadata.gz: 9d2cb2622682713c0fc37e7c0e679aa0d93f01ac9af389c8430496a272608038
4
+ data.tar.gz: 8b313cd7952c0b9e4baf9e8f0cec0af397d1f8cf8fc25760204714f687718df8
5
5
  SHA512:
6
- metadata.gz: 7699c3e1433edc8b7b0c7886f28ef90ad3f6438b2189ebbbe8bfc40c6386f7b142bd8848809af13e9c893d8efcffc6598c595fea8bdea9ff67899a84c5394e27
7
- data.tar.gz: 1b5da1f3b490dbcf2510e8a58306efe3a0924891c5004fe9862854f0700e502d81b46e8353e85b77be43f4c4aea9e67b7c4db276501f971046d47e4488c5d07f
6
+ metadata.gz: c3e939b9e9851ece96d27e31d19fa7f4c5b26bd9141e28e2e5964b5f20ed1f9c9b0f4a77800b87c411d1c271d0b4acf1afa1f50359e832842e241a1ba536b811
7
+ data.tar.gz: d105a5a9924cba80b028790a538945087ef0e19a30763e619b712c1d7b31b54259a03504a5a52d1f1cc24be6a03f1e8185d499ed9e7343a17655c4336f22dd40
data/exe/spectre CHANGED
@@ -9,6 +9,11 @@ require 'ectoplasm'
9
9
 
10
10
  require_relative '../lib/spectre'
11
11
 
12
+ def load_yaml file_path
13
+ yaml = File.read(file_path)
14
+ YAML.safe_load(yaml, aliases: true)
15
+ end
16
+
12
17
 
13
18
  DEFAULT_CONFIG = {
14
19
  'config_file' => './spectre.yml',
@@ -72,9 +77,10 @@ DEFAULT_CONFIG = {
72
77
 
73
78
 
74
79
  cmd_options = {}
80
+ property_overrides = {}
75
81
 
76
82
  opt_parser = OptionParser.new do |opts|
77
- opts.banner = %{Spectre #{Spectre::VERSION}
83
+ opts.banner = %{Spectre #{Spectre::VERSION}
78
84
 
79
85
  Usage: spectre [command] [options]
80
86
 
@@ -83,6 +89,7 @@ Commands:
83
89
  run Run specs (default)
84
90
  show Print current environment settings
85
91
  dump Dumps the given environment in YAML format to console
92
+ cleanup Will remove all generated files (e.g. logs and reports)
86
93
  init Initializes a new spectre project
87
94
 
88
95
  Specific options:}
@@ -132,17 +139,24 @@ Specific options:}
132
139
  end
133
140
 
134
141
  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]
142
+ key, val = option.split('=')
143
+ val = val.split(',') if DEFAULT_CONFIG[key].is_a? Array
144
+ val = ['true', '1'].include? val if [true, false].include?(DEFAULT_CONFIG[key])
138
145
  val = val.to_i if DEFAULT_CONFIG[key].is_a? Integer
139
- cmd_options[key] = val
140
146
 
141
- curr_opt = cmd_options
142
- (key.split '.').each do |k|
143
- curr_opt[k] = {} unless curr_opt.key? k
147
+ opt_path = key.split('.')
148
+
149
+ curr_opt = property_overrides
150
+
151
+ opt_path.each_with_index do |part, i|
152
+ if i == opt_path.count-1
153
+ curr_opt[part] = val
154
+ break
155
+ end
156
+
157
+ curr_opt[part] = {} unless curr_opt.key?(part)
158
+ curr_opt = curr_opt[part]
144
159
  end
145
- curr_opt = val
146
160
  end
147
161
 
148
162
  opts.separator "\nCommon options:"
@@ -173,21 +187,20 @@ cfg.deep_merge! DEFAULT_CONFIG
173
187
  global_config_file = File.join File.expand_path('~'), '.spectre'
174
188
 
175
189
  if File.exists? global_config_file
176
- global_options = YAML.load_file(global_config_file)
190
+ global_options = load_yaml(global_config_file)
177
191
  cfg.deep_merge! global_options if global_options
178
192
  end
179
193
 
180
194
  config_file = cmd_options['config_file'] || cfg['config_file']
181
195
 
182
196
  if File.exists? config_file
183
- file_options = YAML.load_file(config_file)
197
+ file_options = load_yaml(config_file)
184
198
  cfg.deep_merge! file_options
185
199
  Dir.chdir File.dirname(config_file)
186
200
  end
187
201
 
188
202
  cfg.deep_merge! cmd_options
189
203
 
190
-
191
204
  ###########################################
192
205
  # Load Environment
193
206
  ###########################################
@@ -197,7 +210,7 @@ envs = {}
197
210
  read_env_files = {}
198
211
  cfg['env_patterns'].each do |pattern|
199
212
  Dir.glob(pattern).each do|f|
200
- spec_env = YAML.load_file(f) || {}
213
+ spec_env = load_yaml(f) || {}
201
214
 
202
215
  name = spec_env['name'] || 'default'
203
216
 
@@ -215,7 +228,7 @@ end
215
228
  # Merge partial environment configs with existing environments
216
229
  cfg['env_partial_patterns'].each do |pattern|
217
230
  Dir.glob(pattern).each do|f|
218
- partial_env = YAML.load_file(f)
231
+ partial_env = load_yaml(f)
219
232
  name = partial_env.delete('name') || 'default'
220
233
  next unless envs.key? name
221
234
 
@@ -224,7 +237,10 @@ cfg['env_partial_patterns'].each do |pattern|
224
237
  end
225
238
 
226
239
  env = envs[cfg['environment']]
227
- cfg.merge! env if env
240
+ cfg.deep_merge! env if env
241
+
242
+ # Merge property overrides after environment load to give it higher priority
243
+ cfg.deep_merge! property_overrides
228
244
 
229
245
 
230
246
  String.colored! if cfg['colored']
@@ -392,6 +408,24 @@ if 'dump' == action
392
408
  end
393
409
 
394
410
 
411
+ ###########################################
412
+ # Cleanup
413
+ ###########################################
414
+
415
+
416
+ if 'cleanup' == action
417
+ log_file_pattern = cfg['log_file'].gsub('<date>', '*')
418
+
419
+ Dir.glob(log_file_pattern).each do |log_file|
420
+ File.delete(log_file)
421
+ end
422
+
423
+ Dir.glob(File.join cfg['out_path'], '/*').each do |out_file|
424
+ File.delete(out_file)
425
+ end
426
+ end
427
+
428
+
395
429
  ###########################################
396
430
  # Init
397
431
  ###########################################
@@ -52,7 +52,7 @@ module Spectre
52
52
  end
53
53
 
54
54
  def should_not_be_empty
55
- raise AssertionFailure.new('The list is empty', 'nil')
55
+ raise AssertionFailure.new('The value does not exist', 'nil')
56
56
  end
57
57
  end
58
58
 
@@ -247,7 +247,7 @@ module Spectre
247
247
  raise AssertionFailure.new(e.message, e.expected, e.actual, desc), cause: nil
248
248
  rescue Exception => e
249
249
  Logger.log_status(desc, Logger::Status::ERROR)
250
- raise AssertionFailure.new("An unexpected error occured during expectation: #{e.message}", nil, nil, desc), cause: e
250
+ raise AssertionFailure.new("An unexpected error occurred during expectation: #{e.message}", nil, nil, desc), cause: e
251
251
  end
252
252
  end
253
253
 
data/lib/spectre/curl.rb CHANGED
@@ -301,7 +301,10 @@ module Spectre::Curl
301
301
 
302
302
  req_log = "[>] #{req_id} #{req['method']} #{uri}\n"
303
303
  req_log += header_to_s(req['headers'])
304
- req_log += try_format_json(req['body'], pretty: true)
304
+
305
+ if req[:body] != nil and not req[:body].empty?
306
+ req_log += try_format_json(req['body'], pretty: true)
307
+ end
305
308
 
306
309
  @@logger.info(req_log)
307
310
 
@@ -329,7 +332,7 @@ module Spectre::Curl
329
332
 
330
333
  exit_code = wait_thr.value.exitstatus
331
334
 
332
- raise Exception.new "An error occured while executing curl:\n#{debug_log.lines.map { |x| not x.empty? }}" unless exit_code == 0
335
+ raise Exception.new "An error occurred while executing curl:\n#{debug_log.lines.map { |x| not x.empty? }}" unless exit_code == 0
333
336
 
334
337
  # Parse protocol, version, status code and status message from response
335
338
  match = /^(?<protocol>[A-Za-z0-9]+)\/(?<version>\d+\.?\d*) (?<code>\d+) (?<message>.*)/.match result
data/lib/spectre/http.rb CHANGED
@@ -21,7 +21,8 @@ module Spectre
21
21
  'query' => nil,
22
22
  'content_type' => '',
23
23
  'timeout' => 180,
24
- }.freeze
24
+ 'retries' => 0,
25
+ }
25
26
 
26
27
  @@modules = []
27
28
 
@@ -57,6 +58,10 @@ module Spectre
57
58
  @__req['timeout'] = seconds
58
59
  end
59
60
 
61
+ def retries count
62
+ @__req['retries'] = count
63
+ end
64
+
60
65
  def header name, value
61
66
  @__req['headers'] ||= []
62
67
  @__req['headers'].append [name, value.to_s.strip]
@@ -173,7 +178,7 @@ module Spectre
173
178
  end
174
179
 
175
180
  def http name, secure: false, &block
176
- req = {}
181
+ req = DEFAULT_HTTP_CONFIG.clone
177
182
 
178
183
  if @@http_cfg.key? name
179
184
  req.deep_merge! @@http_cfg[name].deep_clone
@@ -270,11 +275,12 @@ module Spectre
270
275
 
271
276
  net_http = Net::HTTP.new(uri.host, uri.port)
272
277
  net_http.read_timeout = req['timeout']
278
+ net_http.max_retries = req['retries']
273
279
 
274
280
  if uri.scheme == 'https'
275
281
  net_http.use_ssl = true
276
282
 
277
- if req.key? 'cert'
283
+ if req['cert']
278
284
  raise HttpError.new("Certificate '#{req['cert']}' does not exist") unless File.exists? req['cert']
279
285
 
280
286
  net_http.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -113,8 +113,14 @@ module Spectre
113
113
  print_line('', txt)
114
114
  end
115
115
 
116
- def log_skipped _spec
117
- print_line('', Status::SKIPPED.grey)
116
+ def log_skipped _spec, message=nil
117
+ txt = Status::SKIPPED
118
+
119
+ unless message.nil?
120
+ txt += ' - ' + message
121
+ end
122
+
123
+ print_line('', txt.grey)
118
124
  end
119
125
 
120
126
  private
@@ -79,11 +79,17 @@ module Spectre
79
79
 
80
80
  def log_error spec, exception
81
81
  file, line = exception.backtrace[0].match(/(.*\.rb):(\d+)/).captures
82
- @file_log.error "An unexpected error occured at '#{file}:#{line}' while running spec '#{spec.name}': [#{exception.class}] #{exception.message}\n#{exception.backtrace.join "\n"}"
82
+ @file_log.error "An unexpected error occurred at '#{file}:#{line}' while running spec '#{spec.name}': [#{exception.class}] #{exception.message}\n#{exception.backtrace.join "\n"}"
83
83
  end
84
84
 
85
- def log_skipped spec
86
- @file_log.warn "spec '#{spec.desc}' canceled by user"
85
+ def log_skipped spec, message=nil
86
+ txt = "spec '#{spec.desc}' skipped"
87
+
88
+ unless message.nil?
89
+ txt += ': ' + message
90
+ end
91
+
92
+ @file_log.warn txt
87
93
  end
88
94
 
89
95
  def log_status desc, status, annotation=nil
@@ -109,8 +109,8 @@ module Spectre
109
109
  delegate(:log_error, spec, exception)
110
110
  end
111
111
 
112
- def log_skipped spec
113
- delegate(:log_skipped, spec)
112
+ def log_skipped spec, message=nil
113
+ delegate(:log_skipped, spec, message)
114
114
  end
115
115
 
116
116
  def log_status desc, status, annotation=nil
@@ -21,7 +21,6 @@ module Spectre::Reporter
21
21
  if run_info.failure
22
22
  report_str += " Expected #{run_info.failure.expectation}"
23
23
  report_str += " with #{run_info.data}" if run_info.data
24
- report_str += " during #{spec.context.__desc}" if spec.context.__desc
25
24
 
26
25
  report_str += " but it failed"
27
26
 
@@ -40,7 +39,7 @@ module Spectre::Reporter
40
39
  failures += 1
41
40
 
42
41
  else
43
- report_str += " but an unexpected error occured during run\n"
42
+ report_str += " but an unexpected error occurred during run\n"
44
43
  report_str += format_exception(run_info.error)
45
44
  errors += 1
46
45
  end
@@ -68,6 +67,7 @@ module Spectre::Reporter
68
67
 
69
68
  def format_title run_info
70
69
  title = run_info.spec.subject.desc
70
+ title += " #{run_info.spec.context.__desc}" if run_info.spec.context.__desc
71
71
  title += ' ' + run_info.spec.desc
72
72
  title += " (#{'%.3f' % run_info.duration}s)"
73
73
  title += " [#{run_info.spec.name}]"
@@ -1,3 +1,5 @@
1
+ require 'cgi'
2
+
1
3
  # https://llg.cubic.org/docs/junit/
2
4
  # Azure mappings: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/test/publish-test-results?view=azure-devops&tabs=junit%2Cyaml
3
5
 
@@ -22,11 +24,11 @@ module Spectre::Reporter
22
24
  errors = run_infos.select { |x| x.error != nil }
23
25
  skipped = run_infos.select { |x| x.skipped? }
24
26
 
25
- xml_str += '<testsuite package="' + subject.desc + '" id="' + suite_id.to_s + '" name="' + subject.desc + '" timestamp="' + datetime + '" tests="' + run_infos.count.to_s + '" failures="' + failures.count.to_s + '" errors="' + errors.count.to_s + '" skipped="' + skipped.count.to_s + '">'
27
+ xml_str += '<testsuite package="' + CGI::escapeHTML(subject.desc) + '" id="' + CGI::escapeHTML(suite_id.to_s) + '" name="' + CGI::escapeHTML(subject.desc) + '" timestamp="' + datetime + '" tests="' + run_infos.count.to_s + '" failures="' + failures.count.to_s + '" errors="' + errors.count.to_s + '" skipped="' + skipped.count.to_s + '">'
26
28
  suite_id += 1
27
29
 
28
30
  run_infos.each do |run_info|
29
- xml_str += '<testcase classname="' + run_info.spec.file.to_s + '" name="' + run_info.spec.desc + '" timestamp="' + run_info.started.to_s + '" time="' + ('%.3f' % run_info.duration) + '">'
31
+ xml_str += '<testcase classname="' + CGI::escapeHTML(run_info.spec.file.to_s) + '" name="' + CGI::escapeHTML(run_info.spec.desc) + '" timestamp="' + run_info.started.to_s + '" time="' + ('%.3f' % run_info.duration) + '">'
30
32
 
31
33
  if run_info.failure and !run_info.failure.cause
32
34
  failure_message = "Expected #{run_info.failure.expectation}"
@@ -38,7 +40,7 @@ module Spectre::Reporter
38
40
  failure_message += " but it failed"
39
41
  end
40
42
 
41
- xml_str += '<failure message="' + failure_message.gsub('"', '`') + '"></failure>'
43
+ xml_str += '<failure message="' + CGI::escapeHTML(failure_message.gsub('"', '`')) + '"></failure>'
42
44
  end
43
45
 
44
46
 
@@ -49,7 +51,7 @@ module Spectre::Reporter
49
51
  failure_message = error.message
50
52
  text = error.backtrace.join "\n"
51
53
 
52
- xml_str += '<error message="' + failure_message.gsub('"', '`') + '" type="' + type + '">'
54
+ xml_str += '<error message="' + CGI::escapeHTML(failure_message.gsub('"', '`')) + '" type="' + type + '">'
53
55
  xml_str += '<![CDATA[' + text + ']]>'
54
56
  xml_str += '</error>'
55
57
  end
data/lib/spectre.rb CHANGED
@@ -2,7 +2,7 @@ module Spectre
2
2
  module Version
3
3
  MAJOR = 1
4
4
  MINOR = 12
5
- TINY = 1
5
+ TINY = 4
6
6
  end
7
7
 
8
8
  VERSION = [Version::MAJOR, Version::MINOR, Version::TINY].compact * '.'
@@ -48,6 +48,12 @@ module Spectre
48
48
  end
49
49
  end
50
50
 
51
+ class SpectreSkip < Interrupt
52
+ def initialize message
53
+ super message
54
+ end
55
+ end
56
+
51
57
 
52
58
  ###########################################
53
59
  # Internal Classes
@@ -252,9 +258,12 @@ module Spectre
252
258
  spec.block.call(data)
253
259
  rescue ExpectationFailure => e
254
260
  run_info.failure = e
261
+ rescue SpectreSkip => e
262
+ run_info.skipped = true
263
+ Logger.log_skipped spec, e.message
255
264
  rescue Interrupt
256
265
  run_info.skipped = true
257
- Logger.log_skipped spec
266
+ Logger.log_skipped spec, 'canceled by user'
258
267
  rescue Exception => e
259
268
  run_info.error = e
260
269
  Logger.log_error spec, e
@@ -438,9 +447,13 @@ module Spectre
438
447
  def property key, val
439
448
  Spectre::Runner.current.properties[key] = val
440
449
  end
450
+
451
+ def skip message=nil
452
+ raise SpectreSkip.new(message)
453
+ end
441
454
  end
442
455
 
443
- delegate :describe, :property, to: Spectre
456
+ delegate :describe, :property, :skip, to: Spectre
444
457
  end
445
458
 
446
459
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spectre-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.1
4
+ version: 1.12.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Neubauer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-13 00:00:00.000000000 Z
11
+ date: 2022-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ectoplasm
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.2.0
19
+ version: 1.2.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.2.0
26
+ version: 1.2.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: jsonpath
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,14 +80,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
- version: 2.5.0
83
+ version: 3.0.0
84
84
  required_rubygems_version: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - ">="
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
89
  requirements: []
90
- rubygems_version: 3.2.3
90
+ rubygems_version: 3.3.7
91
91
  signing_key:
92
92
  specification_version: 4
93
93
  summary: Describe and run automated tests