spectre-core 1.12.1 → 1.12.4

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 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