spectre-core 1.13.0 → 1.14.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/spectre +116 -101
- data/lib/spectre/assertion.rb +66 -48
- data/lib/spectre/helpers.rb +3 -2
- data/lib/spectre/http.rb +2 -7
- data/lib/spectre.rb +2 -2
- metadata +4 -12
- data/lib/spectre/reporter/html.rb +0 -1167
- data/lib/spectre/reporter/junit.rb +0 -105
- data/lib/spectre/reporter/vstest.rb +0 -167
- data/resources/OpenSans-Regular.ttf +0 -0
- data/resources/fa-regular-400.ttf +0 -0
- data/resources/fa-solid-900.ttf +0 -0
- data/resources/spectre_icon.svg +0 -106
- data/resources/vue.global.prod.js +0 -1
@@ -1,105 +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 get_name run_info
|
13
|
-
run_name = "[#{run_info.spec.name}] #{run_info.spec.subject.desc}"
|
14
|
-
run_name += " - #{run_info.spec.context.__desc} -" unless run_info.spec.context.__desc.nil?
|
15
|
-
run_name += " #{run_info.spec.desc}"
|
16
|
-
run_name
|
17
|
-
end
|
18
|
-
|
19
|
-
def report run_infos
|
20
|
-
now = Time.now.getutc
|
21
|
-
timestamp = now.strftime('%s')
|
22
|
-
datetime = now.strftime('%FT%T.%L')
|
23
|
-
|
24
|
-
xml_str = '<?xml version="1.0" encoding="UTF-8" ?>'
|
25
|
-
xml_str += '<testsuites>'
|
26
|
-
|
27
|
-
suite_id = 0
|
28
|
-
|
29
|
-
run_infos.group_by { |x| x.spec.subject }.each do |subject, info_group|
|
30
|
-
failures = info_group.select { |x| x.failure != nil }
|
31
|
-
errors = info_group.select { |x| x.error != nil }
|
32
|
-
skipped = info_group.select { |x| x.skipped? }
|
33
|
-
|
34
|
-
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}" failures="#{failures.count}" errors="#{errors.count}" skipped="#{skipped.count}">}
|
35
|
-
suite_id += 1
|
36
|
-
|
37
|
-
info_group.each do |run_info|
|
38
|
-
started = run_info.started.strftime('%FT%T.%L')
|
39
|
-
|
40
|
-
xml_str += %{<testcase classname="#{CGI::escapeHTML(run_info.spec.file.to_s)}" name="#{get_name(run_info)}" timestamp="#{started}" time="#{('%.3f' % run_info.duration)}">}
|
41
|
-
|
42
|
-
if run_info.failure and !run_info.failure.cause
|
43
|
-
failure_message = "Expected #{run_info.failure.expectation}"
|
44
|
-
failure_message += " with #{run_info.data}" if run_info.data
|
45
|
-
failure_message += " but it failed"
|
46
|
-
failure_message += " with message: #{run_info.failure.message}" if run_info.failure.message
|
47
|
-
|
48
|
-
xml_str += %{<failure message="#{CGI::escapeHTML(failure_message.gsub('"', '`'))}"></failure>}
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
if run_info.error or (run_info.failure and run_info.failure.cause)
|
53
|
-
error = run_info.error || run_info.failure.cause
|
54
|
-
|
55
|
-
type = error.class.name
|
56
|
-
failure_message = error.message
|
57
|
-
text = error.backtrace.join "\n"
|
58
|
-
|
59
|
-
xml_str += %{<error message="#{CGI::escapeHTML(failure_message.gsub('"', '`'))}" type="#{type}">}
|
60
|
-
xml_str += "<![CDATA[#{text}]]>"
|
61
|
-
xml_str += '</error>'
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
if run_info.log.count > 0 or run_info.properties.count > 0 or run_info.data
|
66
|
-
xml_str += '<system-out>'
|
67
|
-
xml_str += '<![CDATA['
|
68
|
-
|
69
|
-
if run_info.properties.count > 0
|
70
|
-
run_info.properties.each do |key, val|
|
71
|
-
xml_str += "#{key}: #{val}\n"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
if run_info.data
|
76
|
-
data_str = run_info.data
|
77
|
-
data_str = run_info.data.to_json unless run_info.data.is_a? String or run_info.data.is_a? Integer
|
78
|
-
xml_str += "data: #{data_str}\n"
|
79
|
-
end
|
80
|
-
|
81
|
-
if run_info.log.count > 0
|
82
|
-
messages = run_info.log.map { |x| "[#{x[0].strftime('%F %T')}] #{x[1]}" }
|
83
|
-
xml_str += messages.join("\n")
|
84
|
-
end
|
85
|
-
|
86
|
-
xml_str += ']]>'
|
87
|
-
xml_str += '</system-out>'
|
88
|
-
end
|
89
|
-
|
90
|
-
xml_str += '</testcase>'
|
91
|
-
end
|
92
|
-
|
93
|
-
xml_str += '</testsuite>'
|
94
|
-
end
|
95
|
-
|
96
|
-
xml_str += '</testsuites>'
|
97
|
-
|
98
|
-
Dir.mkdir @config['out_path'] unless Dir.exist? @config['out_path']
|
99
|
-
|
100
|
-
file_path = File.join(@config['out_path'], "spectre-junit_#{timestamp}.xml")
|
101
|
-
|
102
|
-
File.write(file_path, xml_str)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
@@ -1,167 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
require 'socket'
|
3
|
-
require 'securerandom'
|
4
|
-
|
5
|
-
# Azure mappings: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/test/publish-test-results?view=azure-devops&tabs=trx%2Cyaml
|
6
|
-
|
7
|
-
module Spectre::Reporter
|
8
|
-
class VSTest
|
9
|
-
def initialize config
|
10
|
-
@config = config
|
11
|
-
@date_format = '%FT%T.%L'
|
12
|
-
end
|
13
|
-
|
14
|
-
def report run_infos
|
15
|
-
now = Time.now.getutc
|
16
|
-
|
17
|
-
xml_str = '<?xml version="1.0" encoding="UTF-8" ?>'
|
18
|
-
xml_str += %{<TestRun xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">}
|
19
|
-
|
20
|
-
started = run_infos[0].started
|
21
|
-
finished = run_infos[-1].finished
|
22
|
-
|
23
|
-
computer_name = Socket.gethostname
|
24
|
-
|
25
|
-
xml_str += %{<Times start="#{started.strftime(@date_format)}" finish="#{finished.strftime(@date_format)}" />}
|
26
|
-
|
27
|
-
|
28
|
-
# Write summary with file attachments
|
29
|
-
xml_str += '<ResultSummary>'
|
30
|
-
xml_str += '<ResultFiles>'
|
31
|
-
xml_str += %{<ResultFile path="#{File.absolute_path(@config['log_file'])}"></ResultFile>} if File.exists? @config['log_file']
|
32
|
-
|
33
|
-
report_files = Dir[File.join(@config['out_path'], '*')]
|
34
|
-
|
35
|
-
if report_files.any?
|
36
|
-
report_files.each do |report_file|
|
37
|
-
xml_str += %{<ResultFile path="#{File.absolute_path(report_file)}"></ResultFile>}
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
xml_str += '</ResultFiles>'
|
42
|
-
xml_str += '</ResultSummary>'
|
43
|
-
|
44
|
-
|
45
|
-
# Write test definitions
|
46
|
-
test_definitions = run_infos
|
47
|
-
.sort_by { |x| x.spec.name }
|
48
|
-
.map { |x| [SecureRandom.uuid(), SecureRandom.uuid(), x] }
|
49
|
-
|
50
|
-
xml_str += '<TestDefinitions>'
|
51
|
-
test_definitions.each do |test_id, execution_id, run_info|
|
52
|
-
xml_str += %{<UnitTest name="#{CGI::escapeHTML get_name(run_info)}" storage="#{CGI::escapeHTML(run_info.spec.file.to_s)}" id="#{test_id}">}
|
53
|
-
xml_str += %{<Execution id="#{execution_id}" />}
|
54
|
-
xml_str += '</UnitTest>'
|
55
|
-
end
|
56
|
-
xml_str += '</TestDefinitions>'
|
57
|
-
|
58
|
-
|
59
|
-
# Write test results
|
60
|
-
xml_str += '<Results>'
|
61
|
-
test_definitions.each do |test_id, execution_id, run_info|
|
62
|
-
duration_str = Time.at(run_info.duration).gmtime.strftime('%T.%L')
|
63
|
-
|
64
|
-
if run_info.failed?
|
65
|
-
outcome = 'Failed'
|
66
|
-
elsif run_info.error?
|
67
|
-
outcome = 'Error'
|
68
|
-
elsif run_info.skipped?
|
69
|
-
outcome = 'Skipped'
|
70
|
-
else
|
71
|
-
outcome = 'Passed'
|
72
|
-
end
|
73
|
-
|
74
|
-
xml_str += %{<UnitTestResult executionId="#{execution_id}" testId="#{test_id}" testName="#{CGI::escapeHTML get_name(run_info)}" computerName="#{computer_name}" duration="#{duration_str}" startTime="#{run_info.started.strftime(@date_format)}" endTime="#{run_info.finished.strftime(@date_format)}" outcome="#{outcome}">}
|
75
|
-
|
76
|
-
if run_info.log.any? or run_info.failed? or run_info.error?
|
77
|
-
xml_str += '<Output>'
|
78
|
-
|
79
|
-
# Write log entries
|
80
|
-
xml_str += '<StdOut>'
|
81
|
-
log_str = ''
|
82
|
-
|
83
|
-
if run_info.properties.count > 0
|
84
|
-
run_info.properties.each do |key, val|
|
85
|
-
log_str += "#{key}: #{val}\n"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
if run_info.data
|
90
|
-
data_str = run_info.data
|
91
|
-
data_str = run_info.data.to_json unless run_info.data.is_a? String or run_info.data.is_a? Integer
|
92
|
-
log_str += "data: #{data_str}\n"
|
93
|
-
end
|
94
|
-
|
95
|
-
run_info.log.each do |timestamp, message, level, name|
|
96
|
-
log_str += %{#{timestamp.strftime(@date_format)} #{level.to_s.upcase} -- #{name}: #{CGI::escapeHTML(message.to_s)}\n}
|
97
|
-
end
|
98
|
-
|
99
|
-
xml_str += log_str
|
100
|
-
xml_str += '</StdOut>'
|
101
|
-
|
102
|
-
# Write error information
|
103
|
-
if run_info.failed? or run_info.error?
|
104
|
-
xml_str += '<ErrorInfo>'
|
105
|
-
|
106
|
-
if run_info.failed? and not run_info.failure.cause
|
107
|
-
xml_str += '<Message>'
|
108
|
-
|
109
|
-
failure_message = "Expected #{run_info.failure.expectation}"
|
110
|
-
failure_message += " with #{run_info.data}" if run_info.data
|
111
|
-
failure_message += " but it failed"
|
112
|
-
failure_message += " with message: #{run_info.failure.message}" if run_info.failure.message
|
113
|
-
|
114
|
-
xml_str += CGI::escapeHTML(failure_message)
|
115
|
-
|
116
|
-
xml_str += '</Message>'
|
117
|
-
end
|
118
|
-
|
119
|
-
if run_info.error or (run_info.failed? and run_info.failure.cause)
|
120
|
-
error = run_info.error || run_info.failure.cause
|
121
|
-
|
122
|
-
failure_message = error.message
|
123
|
-
|
124
|
-
xml_str += '<Message>'
|
125
|
-
xml_str += CGI::escapeHTML(failure_message)
|
126
|
-
xml_str += '</Message>'
|
127
|
-
|
128
|
-
stack_trace = error.backtrace.join "\n"
|
129
|
-
|
130
|
-
xml_str += '<StackTrace>'
|
131
|
-
xml_str += CGI::escapeHTML(stack_trace)
|
132
|
-
xml_str += '</StackTrace>'
|
133
|
-
end
|
134
|
-
|
135
|
-
xml_str += '</ErrorInfo>'
|
136
|
-
end
|
137
|
-
|
138
|
-
xml_str += '</Output>'
|
139
|
-
end
|
140
|
-
|
141
|
-
|
142
|
-
xml_str += '</UnitTestResult>'
|
143
|
-
end
|
144
|
-
xml_str += '</Results>'
|
145
|
-
|
146
|
-
|
147
|
-
# End report
|
148
|
-
xml_str += '</TestRun>'
|
149
|
-
|
150
|
-
|
151
|
-
Dir.mkdir(@config['out_path']) unless Dir.exists? @config['out_path']
|
152
|
-
|
153
|
-
file_path = File.join(@config['out_path'], "spectre-vstest_#{now.strftime('%s')}.trx")
|
154
|
-
|
155
|
-
File.write(file_path, xml_str)
|
156
|
-
end
|
157
|
-
|
158
|
-
private
|
159
|
-
|
160
|
-
def get_name run_info
|
161
|
-
run_name = "[#{run_info.spec.name}] #{run_info.spec.subject.desc}"
|
162
|
-
run_name += " - #{run_info.spec.context.__desc} -" unless run_info.spec.context.__desc.nil?
|
163
|
-
run_name += " #{run_info.spec.desc}"
|
164
|
-
run_name
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
Binary file
|
Binary file
|
data/resources/fa-solid-900.ttf
DELETED
Binary file
|
data/resources/spectre_icon.svg
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
-
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
3
|
-
|
4
|
-
<svg
|
5
|
-
width="100"
|
6
|
-
height="100"
|
7
|
-
viewBox="0 0 26.458333 26.458334"
|
8
|
-
version="1.1"
|
9
|
-
id="spectre-logo"
|
10
|
-
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
11
|
-
sodipodi:docname="spectre_icon.svg"
|
12
|
-
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
13
|
-
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
14
|
-
xmlns="http://www.w3.org/2000/svg"
|
15
|
-
xmlns:svg="http://www.w3.org/2000/svg">
|
16
|
-
<sodipodi:namedview
|
17
|
-
id="namedview5496"
|
18
|
-
pagecolor="#505050"
|
19
|
-
bordercolor="#eeeeee"
|
20
|
-
borderopacity="1"
|
21
|
-
inkscape:pageshadow="0"
|
22
|
-
inkscape:pageopacity="0"
|
23
|
-
inkscape:pagecheckerboard="0"
|
24
|
-
inkscape:document-units="mm"
|
25
|
-
showgrid="false"
|
26
|
-
units="px"
|
27
|
-
inkscape:zoom="2.1997092"
|
28
|
-
inkscape:cx="47.051674"
|
29
|
-
inkscape:cy="98.876706"
|
30
|
-
inkscape:window-width="1920"
|
31
|
-
inkscape:window-height="1129"
|
32
|
-
inkscape:window-x="-8"
|
33
|
-
inkscape:window-y="-8"
|
34
|
-
inkscape:window-maximized="1"
|
35
|
-
inkscape:current-layer="layer1" />
|
36
|
-
<defs
|
37
|
-
id="defs5491">
|
38
|
-
<linearGradient
|
39
|
-
id="Spectre_Dark"
|
40
|
-
inkscape:swatch="solid"
|
41
|
-
gradientTransform="matrix(4.7460144,0,0,4.7460144,-50.422278,-45.446773)">
|
42
|
-
<stop
|
43
|
-
style="stop-color:#001b41;stop-opacity:1;"
|
44
|
-
offset="0"
|
45
|
-
id="stop935" />
|
46
|
-
</linearGradient>
|
47
|
-
<linearGradient
|
48
|
-
id="Spectre"
|
49
|
-
inkscape:swatch="solid"
|
50
|
-
gradientTransform="translate(3.6978833,7.3957665)">
|
51
|
-
<stop
|
52
|
-
style="stop-color:#0b9dcc;stop-opacity:1;"
|
53
|
-
offset="0"
|
54
|
-
id="stop929" />
|
55
|
-
</linearGradient>
|
56
|
-
</defs>
|
57
|
-
<g
|
58
|
-
inkscape:label="Layer 1"
|
59
|
-
inkscape:groupmode="layer"
|
60
|
-
id="layer1">
|
61
|
-
<path
|
62
|
-
d="M 23.562614,1.8538626 H 2.0855215 A 1.3423183,1.3423183 0 0 0 0.7432002,3.1961811 V 18.632839 a 1.3423183,1.3423183 0 0 0 1.3423213,1.342315 h 7.0471714 v 2.01348 A 0.67115913,0.67115913 0 0 1 8.4615361,22.659792 H 6.1124777 a 0.33558161,0.33558161 0 0 0 0,0.67116 h 5.7048483 a 0.33558161,0.33558161 0 0 0 0,-0.67116 H 9.6226382 a 1.3423183,1.3423183 0 0 0 0.1812166,-0.671158 v -2.01348 h 1.3423172 a 0.33557958,0.33557958 0 0 0 0,-0.671153 H 2.0855241 A 0.67115913,0.67115913 0 0 1 1.4143648,18.632839 V 3.1961811 A 0.67115913,0.67115913 0 0 1 2.0855241,2.5250204 H 23.562621 a 0.67115913,0.67115913 0 0 1 0.671162,0.6711607 v 8.3894869 a 0.33557958,0.33557958 0 0 0 0.671153,0 V 3.1961811 A 1.3423183,1.3423183 0 0 0 23.562614,1.8538626 Z"
|
63
|
-
style="display:inline;fill:url(#Spectre_Dark);fill-opacity:1;stroke-width:0.167791"
|
64
|
-
id="path853" />
|
65
|
-
<g
|
66
|
-
id="g865"
|
67
|
-
style="display:inline"
|
68
|
-
transform="matrix(0.24129238,0,0,0.24129238,1.9407417,-38.899368)">
|
69
|
-
<path
|
70
|
-
style="fill:none;stroke:url(#Spectre);stroke-width:2.75181;stroke-linecap:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
71
|
-
inkscape:connector-curvature="0"
|
72
|
-
class="st0"
|
73
|
-
d="m 87.314438,220.45502 c -2.965446,-1.69357 -4.198358,-7.47409 -6.531567,-12.84322 -2.344591,-5.39532 -5.80024,-10.37523 -13.241437,-10.37523 -14.84627,0 -12.430241,16.45022 -18.715617,18.63643 -6.285375,2.18621 -11.344875,8.86753 -11.344875,15.69946 14.2896,-1.82364 8.286409,9.69604 11.92715,13.32925 4.174521,4.16589 7.891305,0.93451 11.934895,7.69523 3.695179,6.17818 12.014082,6.69916 12.014082,6.69916 0,0 -3.17754,-10.29522 5.345264,-12.54277 12.0242,-3.55261 3.991998,-12.1135 17.745155,-9.35513 -0.654889,-4.27936 0.134141,-11.65066 -9.13305,-16.94318 z"
|
74
|
-
id="path857"
|
75
|
-
sodipodi:nodetypes="sssscsscccs"
|
76
|
-
inkscape:export-filename="C:\Tools\spectre-core\spectre_icon.png"
|
77
|
-
inkscape:export-xdpi="299"
|
78
|
-
inkscape:export-ydpi="299" />
|
79
|
-
<g
|
80
|
-
id="g863"
|
81
|
-
transform="matrix(6.7937703,0,0,6.7937703,24.913612,115.45241)"
|
82
|
-
style="fill:#0b9dcc;fill-opacity:1">
|
83
|
-
<path
|
84
|
-
d="m 5.9963355,15.094538 c 0,0 -0.1905226,0.399828 -0.6815162,0.320321 -0.4909939,-0.0795 -0.6341843,-0.591042 -0.6341843,-0.591042 0,0 0.378481,0.114842 0.6619948,0.167782 0.2835137,0.05294 0.6537059,0.102935 0.6537059,0.102935 z"
|
85
|
-
id="path859"
|
86
|
-
inkscape:connector-curvature="0"
|
87
|
-
sodipodi:nodetypes="czczcc"
|
88
|
-
class="spectre-logo-eye"
|
89
|
-
style="fill:url(#Spectre);fill-opacity:1;stroke-width:0.522545"
|
90
|
-
inkscape:export-filename="C:\Tools\spectre-core\spectre_icon.png"
|
91
|
-
inkscape:export-xdpi="299"
|
92
|
-
inkscape:export-ydpi="299" />
|
93
|
-
<path
|
94
|
-
d="m 8.0112257,14.954736 c 0,0 -0.2622402,0.669385 -0.748107,0.683114 -0.4858668,0.01373 -0.7413854,-0.519393 -0.7413854,-0.519393 0,0 0.391654,0.0016 0.7384379,-0.03607 0.3467838,-0.03767 0.7510545,-0.127651 0.7510545,-0.127651 z"
|
95
|
-
id="path861"
|
96
|
-
inkscape:connector-curvature="0"
|
97
|
-
sodipodi:nodetypes="czczcc"
|
98
|
-
class="spectre-logo-eye"
|
99
|
-
style="fill:url(#Spectre);fill-opacity:1;stroke-width:0.522545"
|
100
|
-
inkscape:export-filename="C:\Tools\spectre-core\spectre_icon.png"
|
101
|
-
inkscape:export-xdpi="299"
|
102
|
-
inkscape:export-ydpi="299" />
|
103
|
-
</g>
|
104
|
-
</g>
|
105
|
-
</g>
|
106
|
-
</svg>
|