spectre-core 1.12.3 → 1.14.0
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 +134 -107
- data/lib/spectre/assertion.rb +77 -69
- data/lib/spectre/async.rb +31 -0
- data/lib/spectre/bag.rb +1 -1
- data/lib/spectre/curl.rb +4 -6
- data/lib/spectre/helpers.rb +4 -0
- data/lib/spectre/http/keystone.rb +0 -2
- data/lib/spectre/http.rb +23 -9
- data/lib/spectre/logger/console.rb +9 -3
- data/lib/spectre/logger/file.rb +26 -20
- data/lib/spectre/logger.rb +39 -12
- data/lib/spectre/mixin.rb +3 -3
- data/lib/spectre/reporter/console.rb +19 -22
- data/lib/spectre.rb +88 -58
- metadata +10 -11
- data/lib/spectre/reporter/junit.rb +0 -102
data/lib/spectre/logger.rb
CHANGED
@@ -2,7 +2,7 @@ require_relative '../spectre'
|
|
2
2
|
require 'date'
|
3
3
|
|
4
4
|
module Spectre
|
5
|
-
module
|
5
|
+
module Logging
|
6
6
|
module Status
|
7
7
|
OK = '[ok]'
|
8
8
|
FAILED = '[failed]'
|
@@ -12,6 +12,31 @@ module Spectre
|
|
12
12
|
DEBUG = '[debug]'
|
13
13
|
end
|
14
14
|
|
15
|
+
class ModuleLogger
|
16
|
+
def initialize config, name
|
17
|
+
@name = name
|
18
|
+
@debug = config['debug']
|
19
|
+
@logger = ::Logger.new(config['log_file'], progname: name)
|
20
|
+
|
21
|
+
@logger.level = @debug ? ::Logger::DEBUG : ::Logger::INFO
|
22
|
+
end
|
23
|
+
|
24
|
+
def info message
|
25
|
+
@logger.info(message)
|
26
|
+
Logging.add_log(message, :info, @name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def debug message
|
30
|
+
@logger.debug(message)
|
31
|
+
Logging.add_log(message, :debug, @name) if @debug
|
32
|
+
end
|
33
|
+
|
34
|
+
def warn message
|
35
|
+
@logger.warn(message)
|
36
|
+
Logging.add_log(message, :warn, @name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
15
40
|
class << self
|
16
41
|
@@debug = false
|
17
42
|
@@logger = []
|
@@ -93,24 +118,24 @@ module Spectre
|
|
93
118
|
end
|
94
119
|
|
95
120
|
def log_info message
|
96
|
-
add_log(message)
|
121
|
+
add_log(message, :info)
|
97
122
|
delegate(:log_info, message)
|
98
123
|
end
|
99
124
|
|
100
125
|
def log_debug message
|
101
126
|
return unless @@debug
|
102
127
|
|
103
|
-
add_log(message)
|
128
|
+
add_log(message, :debug)
|
104
129
|
delegate(:log_debug, message)
|
105
130
|
end
|
106
131
|
|
107
132
|
def log_error spec, exception
|
108
|
-
add_log(exception)
|
133
|
+
add_log(exception, :error)
|
109
134
|
delegate(:log_error, spec, exception)
|
110
135
|
end
|
111
136
|
|
112
|
-
def log_skipped spec
|
113
|
-
delegate(:log_skipped, spec)
|
137
|
+
def log_skipped spec, message=nil
|
138
|
+
delegate(:log_skipped, spec, message)
|
114
139
|
end
|
115
140
|
|
116
141
|
def log_status desc, status, annotation=nil
|
@@ -118,9 +143,15 @@ module Spectre
|
|
118
143
|
end
|
119
144
|
|
120
145
|
def group desc
|
121
|
-
|
146
|
+
Logging.start_group desc
|
122
147
|
yield
|
123
|
-
|
148
|
+
Logging.end_group desc
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_log message, level, logger_name='spectre'
|
152
|
+
return unless Spectre::Runner.current
|
153
|
+
|
154
|
+
Spectre::Runner.current.log.append([DateTime.now, message, level, logger_name])
|
124
155
|
end
|
125
156
|
|
126
157
|
alias_method :info, :log_info
|
@@ -135,10 +166,6 @@ module Spectre
|
|
135
166
|
logger.send(method, *args) if logger.respond_to? method
|
136
167
|
end
|
137
168
|
end
|
138
|
-
|
139
|
-
def add_log message
|
140
|
-
Spectre::Runner.current.log.append([DateTime.now, message])
|
141
|
-
end
|
142
169
|
end
|
143
170
|
|
144
171
|
Spectre.delegate :log, :info, :debug, :group, :separate, to: self
|
data/lib/spectre/mixin.rb
CHANGED
@@ -12,12 +12,12 @@ module Spectre
|
|
12
12
|
|
13
13
|
def required params, *keys
|
14
14
|
missing_keys = keys.select { |x| !params.to_h.key? x }
|
15
|
-
Spectre::
|
15
|
+
Spectre::Logging.log_debug("required parameters for '#{@__desc}': #{keys.join ', '}")
|
16
16
|
raise ArgumentError, "mixin '#{@__desc}' requires #{keys.join ', '}, but only has #{missing_keys.join ', '} given" unless missing_keys.empty?
|
17
17
|
end
|
18
18
|
|
19
19
|
def optional params, *keys
|
20
|
-
Spectre::
|
20
|
+
Spectre::Logging.log_debug("optional parameters for '#{@__desc}': #{keys.join ', '}")
|
21
21
|
params
|
22
22
|
end
|
23
23
|
end
|
@@ -32,7 +32,7 @@ module Spectre
|
|
32
32
|
def run desc, with: []
|
33
33
|
raise "no mixin with desc '#{desc}' defined" unless @@mixins.key? desc
|
34
34
|
|
35
|
-
Spectre::
|
35
|
+
Spectre::Logging.log_debug "running mixin '#{desc}'"
|
36
36
|
|
37
37
|
params = with || {}
|
38
38
|
|
@@ -14,36 +14,34 @@ module Spectre::Reporter
|
|
14
14
|
run_infos
|
15
15
|
.select { |x| x.error != nil or x.failure != nil }
|
16
16
|
.each_with_index do |run_info, index|
|
17
|
-
|
17
|
+
report_str += "\n#{index+1}) #{format_title(run_info)}\n"
|
18
18
|
|
19
|
-
|
19
|
+
if run_info.failure
|
20
|
+
report_str += " Expected #{run_info.failure.expectation}"
|
21
|
+
report_str += " with #{run_info.data}" if run_info.data
|
20
22
|
|
21
|
-
|
22
|
-
report_str += " Expected #{run_info.failure.expectation}"
|
23
|
-
report_str += " with #{run_info.data}" if run_info.data
|
23
|
+
report_str += " but it failed"
|
24
24
|
|
25
|
-
|
25
|
+
if run_info.failure.cause
|
26
|
+
report_str += "\n with an unexpected error:\n"
|
27
|
+
report_str += format_exception(run_info.failure.cause)
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
report_str += format_exception(run_info.failure.cause)
|
29
|
+
elsif run_info.failure.message and not run_info.failure.message.empty?
|
30
|
+
report_str += " with:\n #{run_info.failure.message}"
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
else
|
33
|
+
report_str += '.'
|
34
|
+
end
|
35
|
+
|
36
|
+
report_str += "\n"
|
37
|
+
failures += 1
|
33
38
|
|
34
39
|
else
|
35
|
-
report_str +=
|
40
|
+
report_str += " but an unexpected error occurred during run\n"
|
41
|
+
report_str += format_exception(run_info.error)
|
42
|
+
errors += 1
|
36
43
|
end
|
37
|
-
|
38
|
-
report_str += "\n"
|
39
|
-
failures += 1
|
40
|
-
|
41
|
-
else
|
42
|
-
report_str += " but an unexpected error occurred during run\n"
|
43
|
-
report_str += format_exception(run_info.error)
|
44
|
-
errors += 1
|
45
44
|
end
|
46
|
-
end
|
47
45
|
|
48
46
|
if failures + errors > 0
|
49
47
|
summary = ''
|
@@ -54,7 +52,6 @@ module Spectre::Reporter
|
|
54
52
|
summary += "#{run_infos.length} total"
|
55
53
|
print "\n#{summary}\n".red
|
56
54
|
else
|
57
|
-
summary = ''
|
58
55
|
summary = "\nRun finished successfully"
|
59
56
|
summary += " (#{skipped} skipped)" if skipped > 0
|
60
57
|
print "#{summary}\n".green
|
data/lib/spectre.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Spectre
|
2
2
|
module Version
|
3
3
|
MAJOR = 1
|
4
|
-
MINOR =
|
5
|
-
TINY =
|
4
|
+
MINOR = 14
|
5
|
+
TINY = 0
|
6
6
|
end
|
7
7
|
|
8
8
|
VERSION = [Version::MAJOR, Version::MINOR, Version::TINY].compact * '.'
|
@@ -10,7 +10,7 @@ module Spectre
|
|
10
10
|
|
11
11
|
class ::Hash
|
12
12
|
def deep_merge!(second)
|
13
|
-
merger = proc { |
|
13
|
+
merger = proc { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge!(v2, &merger) : v2 }
|
14
14
|
self.merge!(second, &merger)
|
15
15
|
end
|
16
16
|
|
@@ -34,9 +34,6 @@ module Spectre
|
|
34
34
|
|
35
35
|
|
36
36
|
class SpectreError < Exception
|
37
|
-
def initialize message
|
38
|
-
super message
|
39
|
-
end
|
40
37
|
end
|
41
38
|
|
42
39
|
class ExpectationFailure < Exception
|
@@ -48,6 +45,9 @@ module Spectre
|
|
48
45
|
end
|
49
46
|
end
|
50
47
|
|
48
|
+
class SpectreSkip < Interrupt
|
49
|
+
end
|
50
|
+
|
51
51
|
|
52
52
|
###########################################
|
53
53
|
# Internal Classes
|
@@ -111,7 +111,7 @@ module Spectre
|
|
111
111
|
|
112
112
|
class RunInfo
|
113
113
|
attr_accessor :spec, :data, :started, :finished, :error, :failure, :skipped
|
114
|
-
attr_reader :log, :properties
|
114
|
+
attr_reader :expectations, :log, :properties
|
115
115
|
|
116
116
|
def initialize spec, data=nil
|
117
117
|
@spec = spec
|
@@ -122,6 +122,7 @@ module Spectre
|
|
122
122
|
@failure = nil
|
123
123
|
@skipped = false
|
124
124
|
@log = []
|
125
|
+
@expectations = []
|
125
126
|
@properties = {}
|
126
127
|
end
|
127
128
|
|
@@ -134,12 +135,24 @@ module Spectre
|
|
134
135
|
end
|
135
136
|
|
136
137
|
def failed?
|
138
|
+
@failure != nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def error?
|
137
142
|
@error != nil
|
138
143
|
end
|
144
|
+
|
145
|
+
def status
|
146
|
+
return :error if error?
|
147
|
+
return :failed if failed?
|
148
|
+
return :skipped if skipped?
|
149
|
+
|
150
|
+
return :success
|
151
|
+
end
|
139
152
|
end
|
140
153
|
|
141
154
|
class Runner
|
142
|
-
@@current
|
155
|
+
@@current = nil
|
143
156
|
|
144
157
|
def self.current
|
145
158
|
@@current
|
@@ -148,11 +161,11 @@ module Spectre
|
|
148
161
|
def run specs
|
149
162
|
runs = []
|
150
163
|
|
151
|
-
specs.group_by { |x| x.subject }.each do |subject,
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
runs.concat run_context(context,
|
164
|
+
specs.group_by { |x| x.subject }.each do |subject, subject_specs|
|
165
|
+
Logging.log_subject subject do
|
166
|
+
subject_specs.group_by { |x| x.context }.each do |context, context_specs|
|
167
|
+
Logging.log_context(context) do
|
168
|
+
runs.concat run_context(context, context_specs)
|
156
169
|
end
|
157
170
|
end
|
158
171
|
end
|
@@ -166,8 +179,8 @@ module Spectre
|
|
166
179
|
def run_context context, specs
|
167
180
|
runs = []
|
168
181
|
|
169
|
-
|
170
|
-
setup_run =
|
182
|
+
context.__setup_blocks.each do |setup_spec|
|
183
|
+
setup_run = run_setup(setup_spec)
|
171
184
|
runs << setup_run
|
172
185
|
return runs if setup_run.error or setup_run.failure
|
173
186
|
end
|
@@ -180,47 +193,42 @@ module Spectre
|
|
180
193
|
spec.data
|
181
194
|
.map { |x| x.is_a?(Hash) ? OpenStruct.new(x) : x }
|
182
195
|
.each do |data|
|
183
|
-
|
196
|
+
Logging.log_spec(spec, data) do
|
184
197
|
runs << run_spec(spec, data)
|
185
198
|
end
|
186
199
|
end
|
187
200
|
else
|
188
|
-
|
201
|
+
Logging.log_spec(spec) do
|
189
202
|
runs << run_spec(spec)
|
190
203
|
end
|
191
204
|
end
|
192
205
|
end
|
193
206
|
ensure
|
194
|
-
|
195
|
-
runs <<
|
207
|
+
context.__teardown_blocks.each do |teardown_spec|
|
208
|
+
runs << run_setup(teardown_spec)
|
196
209
|
end
|
197
210
|
end
|
198
211
|
|
199
212
|
runs
|
200
213
|
end
|
201
214
|
|
202
|
-
def
|
203
|
-
|
204
|
-
spec = Spec.new name, context.__subject, name, [], nil, nil, ctx, nil
|
205
|
-
|
206
|
-
run_info = RunInfo.new spec
|
215
|
+
def run_setup spec
|
216
|
+
run_info = RunInfo.new(spec)
|
207
217
|
|
208
218
|
@@current = run_info
|
209
219
|
|
210
220
|
run_info.started = Time.now
|
211
221
|
|
212
|
-
|
222
|
+
Logging.log_context(spec.context) do
|
213
223
|
begin
|
214
|
-
|
215
|
-
block.call
|
216
|
-
end
|
224
|
+
spec.block.call()
|
217
225
|
|
218
226
|
run_info.finished = Time.now
|
219
227
|
rescue ExpectationFailure => e
|
220
228
|
run_info.failure = e
|
221
229
|
rescue Exception => e
|
222
230
|
run_info.error = e
|
223
|
-
|
231
|
+
Logging.log_error(spec, e)
|
224
232
|
end
|
225
233
|
end
|
226
234
|
|
@@ -240,9 +248,9 @@ module Spectre
|
|
240
248
|
|
241
249
|
begin
|
242
250
|
if spec.context.__before_blocks.count > 0
|
243
|
-
before_ctx = SpecContext.new(spec.subject, 'before')
|
251
|
+
before_ctx = SpecContext.new(spec.subject, 'before', spec.context)
|
244
252
|
|
245
|
-
|
253
|
+
Logging.log_context before_ctx do
|
246
254
|
spec.context.__before_blocks.each do |block|
|
247
255
|
block.call(data)
|
248
256
|
end
|
@@ -252,17 +260,20 @@ module Spectre
|
|
252
260
|
spec.block.call(data)
|
253
261
|
rescue ExpectationFailure => e
|
254
262
|
run_info.failure = e
|
263
|
+
rescue SpectreSkip => e
|
264
|
+
run_info.skipped = true
|
265
|
+
Logging.log_skipped(spec, e.message)
|
255
266
|
rescue Interrupt
|
256
267
|
run_info.skipped = true
|
257
|
-
|
268
|
+
Logging.log_skipped(spec, 'canceled by user')
|
258
269
|
rescue Exception => e
|
259
270
|
run_info.error = e
|
260
|
-
|
271
|
+
Logging.log_error(spec, e)
|
261
272
|
ensure
|
262
273
|
if spec.context.__after_blocks.count > 0
|
263
|
-
after_ctx = SpecContext.new(spec.subject, 'after')
|
274
|
+
after_ctx = SpecContext.new(spec.subject, 'after', spec.context)
|
264
275
|
|
265
|
-
|
276
|
+
Logging.log_context after_ctx do
|
266
277
|
begin
|
267
278
|
spec.context.__after_blocks.each do |block|
|
268
279
|
block.call
|
@@ -273,7 +284,7 @@ module Spectre
|
|
273
284
|
run_info.failure = e
|
274
285
|
rescue Exception => e
|
275
286
|
run_info.error = e
|
276
|
-
|
287
|
+
Logging.log_error(spec, e)
|
277
288
|
end
|
278
289
|
end
|
279
290
|
end
|
@@ -294,11 +305,12 @@ module Spectre
|
|
294
305
|
|
295
306
|
|
296
307
|
class SpecContext < DslClass
|
297
|
-
attr_reader :__subject, :__desc, :__before_blocks, :__after_blocks, :__setup_blocks, :__teardown_blocks
|
308
|
+
attr_reader :__subject, :__desc, :__parent, :__before_blocks, :__after_blocks, :__setup_blocks, :__teardown_blocks
|
298
309
|
|
299
|
-
def initialize subject, desc=nil
|
310
|
+
def initialize subject, desc=nil, parent=nil
|
300
311
|
@__subject = subject
|
301
312
|
@__desc = desc
|
313
|
+
@__parent = parent
|
302
314
|
|
303
315
|
@__before_blocks = []
|
304
316
|
@__after_blocks = []
|
@@ -307,20 +319,7 @@ module Spectre
|
|
307
319
|
end
|
308
320
|
|
309
321
|
def it desc, tags: [], with: [], &block
|
310
|
-
|
311
|
-
# Nasty, but it works
|
312
|
-
# Maybe there is another way, but this works for now
|
313
|
-
spec_file = nil
|
314
|
-
begin
|
315
|
-
raise
|
316
|
-
rescue => e
|
317
|
-
spec_file = e.backtrace
|
318
|
-
.select { |file| !file.include? 'lib/spectre' }
|
319
|
-
.first
|
320
|
-
.match(/(.*\.rb):\d+/)
|
321
|
-
.captures
|
322
|
-
.first
|
323
|
-
end
|
322
|
+
spec_file = get_file()
|
324
323
|
|
325
324
|
@__subject.add_spec(desc, tags, with, block, self, spec_file)
|
326
325
|
end
|
@@ -334,17 +333,44 @@ module Spectre
|
|
334
333
|
end
|
335
334
|
|
336
335
|
def setup &block
|
337
|
-
|
336
|
+
name = "#{@__subject.name}-setup"
|
337
|
+
spec_file = get_file()
|
338
|
+
|
339
|
+
setup_ctx = SpecContext.new(@__subject, 'setup', self)
|
340
|
+
@__setup_blocks << Spec.new(name, @__subject, 'setup', [], nil, block, setup_ctx, spec_file)
|
338
341
|
end
|
339
342
|
|
340
343
|
def teardown &block
|
341
|
-
|
344
|
+
name = "#{@__subject.name}-teardown"
|
345
|
+
spec_file = get_file()
|
346
|
+
|
347
|
+
teardown_ctx = SpecContext.new(@__subject, 'teardown', self)
|
348
|
+
@__teardown_blocks << Spec.new(name, @__subject, 'teardown', [], nil, block, teardown_ctx, spec_file)
|
342
349
|
end
|
343
350
|
|
344
351
|
def context desc=nil, &block
|
345
|
-
ctx = SpecContext.new(@__subject, desc)
|
352
|
+
ctx = SpecContext.new(@__subject, desc, self)
|
346
353
|
ctx._evaluate &block
|
347
354
|
end
|
355
|
+
|
356
|
+
private
|
357
|
+
|
358
|
+
def get_file
|
359
|
+
# Get the file, where the spec is defined.
|
360
|
+
# Nasty, but it works
|
361
|
+
# Maybe there is another way, but this works for now
|
362
|
+
|
363
|
+
begin
|
364
|
+
raise
|
365
|
+
rescue => e
|
366
|
+
return e.backtrace
|
367
|
+
.select { |file| !file.include? 'lib/spectre' }
|
368
|
+
.first
|
369
|
+
.match(/(.*\.rb):\d+/)
|
370
|
+
.captures
|
371
|
+
.first
|
372
|
+
end
|
373
|
+
end
|
348
374
|
end
|
349
375
|
|
350
376
|
|
@@ -397,14 +423,14 @@ module Spectre
|
|
397
423
|
|
398
424
|
def tag? tags, tag_exp
|
399
425
|
tags = tags.map { |x| x.to_s }
|
400
|
-
all_tags = tag_exp.split
|
426
|
+
all_tags = tag_exp.split('+')
|
401
427
|
included_tags = all_tags.select { |x| !x.start_with? '!' }
|
402
428
|
excluded_tags = all_tags.select { |x| x.start_with? '!' }.map { |x| x[1..-1] }
|
403
429
|
included_tags & tags == included_tags and excluded_tags & tags == []
|
404
430
|
end
|
405
431
|
|
406
432
|
def delegate *method_names, to: nil
|
407
|
-
Spectre::Delegator.delegate
|
433
|
+
Spectre::Delegator.delegate(*method_names, to)
|
408
434
|
end
|
409
435
|
|
410
436
|
def register &block
|
@@ -438,9 +464,13 @@ module Spectre
|
|
438
464
|
def property key, val
|
439
465
|
Spectre::Runner.current.properties[key] = val
|
440
466
|
end
|
467
|
+
|
468
|
+
def skip message=nil
|
469
|
+
raise SpectreSkip.new(message)
|
470
|
+
end
|
441
471
|
end
|
442
472
|
|
443
|
-
delegate :describe, :property, to: Spectre
|
473
|
+
delegate :describe, :property, :skip, to: Spectre
|
444
474
|
end
|
445
475
|
|
446
476
|
|
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.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Neubauer
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-05 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.
|
19
|
+
version: 1.2.3
|
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.
|
26
|
+
version: 1.2.3
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: jsonpath
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -49,6 +49,7 @@ files:
|
|
49
49
|
- exe/spectre
|
50
50
|
- lib/spectre.rb
|
51
51
|
- lib/spectre/assertion.rb
|
52
|
+
- lib/spectre/async.rb
|
52
53
|
- lib/spectre/bag.rb
|
53
54
|
- lib/spectre/curl.rb
|
54
55
|
- lib/spectre/diagnostic.rb
|
@@ -62,17 +63,15 @@ files:
|
|
62
63
|
- lib/spectre/logger/file.rb
|
63
64
|
- lib/spectre/mixin.rb
|
64
65
|
- lib/spectre/reporter/console.rb
|
65
|
-
- lib/spectre/reporter/junit.rb
|
66
66
|
- lib/spectre/resources.rb
|
67
67
|
homepage: https://github.com/ionos-spectre/spectre-core
|
68
68
|
licenses:
|
69
69
|
- GPL-3.0-or-later
|
70
70
|
metadata:
|
71
|
-
allowed_push_host: https://rubygems.org/
|
72
71
|
homepage_uri: https://github.com/ionos-spectre/spectre-core
|
73
72
|
source_code_uri: https://github.com/ionos-spectre/spectre-core
|
74
73
|
changelog_uri: https://github.com/ionos-spectre/spectre-core/blob/master/CHANGELOG.md
|
75
|
-
post_install_message:
|
74
|
+
post_install_message:
|
76
75
|
rdoc_options: []
|
77
76
|
require_paths:
|
78
77
|
- lib
|
@@ -80,15 +79,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
79
|
requirements:
|
81
80
|
- - ">="
|
82
81
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
82
|
+
version: 3.0.0
|
84
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
84
|
requirements:
|
86
85
|
- - ">="
|
87
86
|
- !ruby/object:Gem::Version
|
88
87
|
version: '0'
|
89
88
|
requirements: []
|
90
|
-
rubygems_version: 3.
|
91
|
-
signing_key:
|
89
|
+
rubygems_version: 3.3.7
|
90
|
+
signing_key:
|
92
91
|
specification_version: 4
|
93
92
|
summary: Describe and run automated tests
|
94
93
|
test_files: []
|
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'CGI'
|
2
|
-
|
3
|
-
# https://llg.cubic.org/docs/junit/
|
4
|
-
# Azure mappings: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/test/publish-test-results?view=azure-devops&tabs=junit%2Cyaml
|
5
|
-
|
6
|
-
module Spectre::Reporter
|
7
|
-
class JUnit
|
8
|
-
def initialize config
|
9
|
-
@config = config
|
10
|
-
end
|
11
|
-
|
12
|
-
def report run_infos
|
13
|
-
now = Time.now.getutc
|
14
|
-
timestamp = now.strftime('%s')
|
15
|
-
datetime = now.strftime('%FT%T%:z')
|
16
|
-
|
17
|
-
xml_str = '<?xml version="1.0" encoding="UTF-8" ?>'
|
18
|
-
xml_str += '<testsuites>'
|
19
|
-
|
20
|
-
suite_id = 0
|
21
|
-
|
22
|
-
run_infos.group_by { |x| x.spec.subject }.each do |subject, run_infos|
|
23
|
-
failures = run_infos.select { |x| x.failure != nil }
|
24
|
-
errors = run_infos.select { |x| x.error != nil }
|
25
|
-
skipped = run_infos.select { |x| x.skipped? }
|
26
|
-
|
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 + '">'
|
28
|
-
suite_id += 1
|
29
|
-
|
30
|
-
run_infos.each do |run_info|
|
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) + '">'
|
32
|
-
|
33
|
-
if run_info.failure and !run_info.failure.cause
|
34
|
-
failure_message = "Expected #{run_info.failure.expectation}"
|
35
|
-
failure_message += " with #{run_info.data}" if run_info.data
|
36
|
-
|
37
|
-
if run_info.failure.message
|
38
|
-
failure_message += " but it failed with #{run_info.failure.message}"
|
39
|
-
else
|
40
|
-
failure_message += " but it failed"
|
41
|
-
end
|
42
|
-
|
43
|
-
xml_str += '<failure message="' + CGI::escapeHTML(failure_message.gsub('"', '`')) + '"></failure>'
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
if run_info.error or (run_info.failure and run_info.failure.cause)
|
48
|
-
error = run_info.error || run_info.failure.cause
|
49
|
-
|
50
|
-
type = error.class.name
|
51
|
-
failure_message = error.message
|
52
|
-
text = error.backtrace.join "\n"
|
53
|
-
|
54
|
-
xml_str += '<error message="' + CGI::escapeHTML(failure_message.gsub('"', '`')) + '" type="' + type + '">'
|
55
|
-
xml_str += '<![CDATA[' + text + ']]>'
|
56
|
-
xml_str += '</error>'
|
57
|
-
end
|
58
|
-
|
59
|
-
|
60
|
-
if run_info.log.count > 0 or run_info.properties.count > 0 or run_info.data
|
61
|
-
xml_str += '<system-out>'
|
62
|
-
xml_str += '<![CDATA['
|
63
|
-
|
64
|
-
if run_info.properties.count > 0
|
65
|
-
run_info.properties.each do |key, val|
|
66
|
-
xml_str += "#{key}: #{val}\n"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
if run_info.data
|
71
|
-
data_str = run_info.data
|
72
|
-
data_str = run_info.data.inspect unless run_info.data.is_a? String or run_info.data.is_a? Integer
|
73
|
-
xml_str += "data: #{data_str}\n"
|
74
|
-
end
|
75
|
-
|
76
|
-
if run_info.log.count > 0
|
77
|
-
messages = run_info.log.map { |x| "[#{x[0].strftime('%F %T')}] #{x[1]}" }
|
78
|
-
xml_str += messages.join("\n")
|
79
|
-
end
|
80
|
-
|
81
|
-
xml_str += ']]>'
|
82
|
-
xml_str += '</system-out>'
|
83
|
-
end
|
84
|
-
|
85
|
-
xml_str += '</testcase>'
|
86
|
-
end
|
87
|
-
|
88
|
-
xml_str += '</testsuite>'
|
89
|
-
end
|
90
|
-
|
91
|
-
xml_str += '</testsuites>'
|
92
|
-
|
93
|
-
Dir.mkdir @config['out_path'] unless Dir.exist? @config['out_path']
|
94
|
-
|
95
|
-
file_path = File.join(@config['out_path'], "spectre-junit_#{timestamp}.xml")
|
96
|
-
|
97
|
-
File.open(file_path, 'w') do |file|
|
98
|
-
file.write(xml_str)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|