spectre-core 1.12.4 → 1.14.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.
- checksums.yaml +4 -4
- data/exe/spectre +125 -103
- data/lib/spectre/assertion.rb +88 -70
- 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 +1 -1
- data/lib/spectre/logger/file.rb +19 -19
- data/lib/spectre/logger.rb +37 -10
- data/lib/spectre/mixin.rb +3 -3
- data/lib/spectre/reporter/console.rb +19 -22
- data/lib/spectre.rb +78 -61
- metadata +8 -9
- 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,19 +118,19 @@ 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
|
|
@@ -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 = 1
|
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
|
@@ -49,9 +46,6 @@ module Spectre
|
|
49
46
|
end
|
50
47
|
|
51
48
|
class SpectreSkip < Interrupt
|
52
|
-
def initialize message
|
53
|
-
super message
|
54
|
-
end
|
55
49
|
end
|
56
50
|
|
57
51
|
|
@@ -117,7 +111,7 @@ module Spectre
|
|
117
111
|
|
118
112
|
class RunInfo
|
119
113
|
attr_accessor :spec, :data, :started, :finished, :error, :failure, :skipped
|
120
|
-
attr_reader :log, :properties
|
114
|
+
attr_reader :expectations, :log, :properties
|
121
115
|
|
122
116
|
def initialize spec, data=nil
|
123
117
|
@spec = spec
|
@@ -128,6 +122,7 @@ module Spectre
|
|
128
122
|
@failure = nil
|
129
123
|
@skipped = false
|
130
124
|
@log = []
|
125
|
+
@expectations = []
|
131
126
|
@properties = {}
|
132
127
|
end
|
133
128
|
|
@@ -140,12 +135,24 @@ module Spectre
|
|
140
135
|
end
|
141
136
|
|
142
137
|
def failed?
|
138
|
+
@failure != nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def error?
|
143
142
|
@error != nil
|
144
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
|
145
152
|
end
|
146
153
|
|
147
154
|
class Runner
|
148
|
-
@@current
|
155
|
+
@@current = nil
|
149
156
|
|
150
157
|
def self.current
|
151
158
|
@@current
|
@@ -154,11 +161,11 @@ module Spectre
|
|
154
161
|
def run specs
|
155
162
|
runs = []
|
156
163
|
|
157
|
-
specs.group_by { |x| x.subject }.each do |subject,
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
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)
|
162
169
|
end
|
163
170
|
end
|
164
171
|
end
|
@@ -172,8 +179,8 @@ module Spectre
|
|
172
179
|
def run_context context, specs
|
173
180
|
runs = []
|
174
181
|
|
175
|
-
|
176
|
-
setup_run =
|
182
|
+
context.__setup_blocks.each do |setup_spec|
|
183
|
+
setup_run = run_setup(setup_spec)
|
177
184
|
runs << setup_run
|
178
185
|
return runs if setup_run.error or setup_run.failure
|
179
186
|
end
|
@@ -186,47 +193,42 @@ module Spectre
|
|
186
193
|
spec.data
|
187
194
|
.map { |x| x.is_a?(Hash) ? OpenStruct.new(x) : x }
|
188
195
|
.each do |data|
|
189
|
-
|
196
|
+
Logging.log_spec(spec, data) do
|
190
197
|
runs << run_spec(spec, data)
|
191
198
|
end
|
192
199
|
end
|
193
200
|
else
|
194
|
-
|
201
|
+
Logging.log_spec(spec) do
|
195
202
|
runs << run_spec(spec)
|
196
203
|
end
|
197
204
|
end
|
198
205
|
end
|
199
206
|
ensure
|
200
|
-
|
201
|
-
runs <<
|
207
|
+
context.__teardown_blocks.each do |teardown_spec|
|
208
|
+
runs << run_setup(teardown_spec)
|
202
209
|
end
|
203
210
|
end
|
204
211
|
|
205
212
|
runs
|
206
213
|
end
|
207
214
|
|
208
|
-
def
|
209
|
-
|
210
|
-
spec = Spec.new name, context.__subject, name, [], nil, nil, ctx, nil
|
211
|
-
|
212
|
-
run_info = RunInfo.new spec
|
215
|
+
def run_setup spec
|
216
|
+
run_info = RunInfo.new(spec)
|
213
217
|
|
214
218
|
@@current = run_info
|
215
219
|
|
216
220
|
run_info.started = Time.now
|
217
221
|
|
218
|
-
|
222
|
+
Logging.log_context(spec.context) do
|
219
223
|
begin
|
220
|
-
|
221
|
-
block.call
|
222
|
-
end
|
224
|
+
spec.block.call()
|
223
225
|
|
224
226
|
run_info.finished = Time.now
|
225
227
|
rescue ExpectationFailure => e
|
226
228
|
run_info.failure = e
|
227
229
|
rescue Exception => e
|
228
230
|
run_info.error = e
|
229
|
-
|
231
|
+
Logging.log_error(spec, e)
|
230
232
|
end
|
231
233
|
end
|
232
234
|
|
@@ -246,9 +248,9 @@ module Spectre
|
|
246
248
|
|
247
249
|
begin
|
248
250
|
if spec.context.__before_blocks.count > 0
|
249
|
-
before_ctx = SpecContext.new(spec.subject, 'before')
|
251
|
+
before_ctx = SpecContext.new(spec.subject, 'before', spec.context)
|
250
252
|
|
251
|
-
|
253
|
+
Logging.log_context before_ctx do
|
252
254
|
spec.context.__before_blocks.each do |block|
|
253
255
|
block.call(data)
|
254
256
|
end
|
@@ -260,18 +262,18 @@ module Spectre
|
|
260
262
|
run_info.failure = e
|
261
263
|
rescue SpectreSkip => e
|
262
264
|
run_info.skipped = true
|
263
|
-
|
265
|
+
Logging.log_skipped(spec, e.message)
|
264
266
|
rescue Interrupt
|
265
267
|
run_info.skipped = true
|
266
|
-
|
268
|
+
Logging.log_skipped(spec, 'canceled by user')
|
267
269
|
rescue Exception => e
|
268
270
|
run_info.error = e
|
269
|
-
|
271
|
+
Logging.log_error(spec, e)
|
270
272
|
ensure
|
271
273
|
if spec.context.__after_blocks.count > 0
|
272
|
-
after_ctx = SpecContext.new(spec.subject, 'after')
|
274
|
+
after_ctx = SpecContext.new(spec.subject, 'after', spec.context)
|
273
275
|
|
274
|
-
|
276
|
+
Logging.log_context after_ctx do
|
275
277
|
begin
|
276
278
|
spec.context.__after_blocks.each do |block|
|
277
279
|
block.call
|
@@ -282,7 +284,7 @@ module Spectre
|
|
282
284
|
run_info.failure = e
|
283
285
|
rescue Exception => e
|
284
286
|
run_info.error = e
|
285
|
-
|
287
|
+
Logging.log_error(spec, e)
|
286
288
|
end
|
287
289
|
end
|
288
290
|
end
|
@@ -303,11 +305,12 @@ module Spectre
|
|
303
305
|
|
304
306
|
|
305
307
|
class SpecContext < DslClass
|
306
|
-
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
|
307
309
|
|
308
|
-
def initialize subject, desc=nil
|
310
|
+
def initialize subject, desc=nil, parent=nil
|
309
311
|
@__subject = subject
|
310
312
|
@__desc = desc
|
313
|
+
@__parent = parent
|
311
314
|
|
312
315
|
@__before_blocks = []
|
313
316
|
@__after_blocks = []
|
@@ -316,20 +319,7 @@ module Spectre
|
|
316
319
|
end
|
317
320
|
|
318
321
|
def it desc, tags: [], with: [], &block
|
319
|
-
|
320
|
-
# Nasty, but it works
|
321
|
-
# Maybe there is another way, but this works for now
|
322
|
-
spec_file = nil
|
323
|
-
begin
|
324
|
-
raise
|
325
|
-
rescue => e
|
326
|
-
spec_file = e.backtrace
|
327
|
-
.select { |file| !file.include? 'lib/spectre' }
|
328
|
-
.first
|
329
|
-
.match(/(.*\.rb):\d+/)
|
330
|
-
.captures
|
331
|
-
.first
|
332
|
-
end
|
322
|
+
spec_file = get_file()
|
333
323
|
|
334
324
|
@__subject.add_spec(desc, tags, with, block, self, spec_file)
|
335
325
|
end
|
@@ -343,17 +333,44 @@ module Spectre
|
|
343
333
|
end
|
344
334
|
|
345
335
|
def setup &block
|
346
|
-
|
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)
|
347
341
|
end
|
348
342
|
|
349
343
|
def teardown &block
|
350
|
-
|
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)
|
351
349
|
end
|
352
350
|
|
353
351
|
def context desc=nil, &block
|
354
|
-
ctx = SpecContext.new(@__subject, desc)
|
352
|
+
ctx = SpecContext.new(@__subject, desc, self)
|
355
353
|
ctx._evaluate &block
|
356
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
|
357
374
|
end
|
358
375
|
|
359
376
|
|
@@ -406,14 +423,14 @@ module Spectre
|
|
406
423
|
|
407
424
|
def tag? tags, tag_exp
|
408
425
|
tags = tags.map { |x| x.to_s }
|
409
|
-
all_tags = tag_exp.split
|
426
|
+
all_tags = tag_exp.split('+')
|
410
427
|
included_tags = all_tags.select { |x| !x.start_with? '!' }
|
411
428
|
excluded_tags = all_tags.select { |x| x.start_with? '!' }.map { |x| x[1..-1] }
|
412
429
|
included_tags & tags == included_tags and excluded_tags & tags == []
|
413
430
|
end
|
414
431
|
|
415
432
|
def delegate *method_names, to: nil
|
416
|
-
Spectre::Delegator.delegate
|
433
|
+
Spectre::Delegator.delegate(*method_names, to)
|
417
434
|
end
|
418
435
|
|
419
436
|
def register &block
|
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.1
|
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
|
@@ -88,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
87
|
version: '0'
|
89
88
|
requirements: []
|
90
89
|
rubygems_version: 3.3.7
|
91
|
-
signing_key:
|
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
|