fastlane-plugin-xcresult_to_junit 0.2.2 → 0.3.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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c185b9548c916b38b2ed3a08299517bc82a3694f53389bc5cd71ade036935755
|
4
|
+
data.tar.gz: 9503d30e4b60b7ae44920cc2d088086cfe605b56e70e80bc3b6c4687a282b152
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f14cbe747d41187ba986958d91118e98fe6f6fd458eb5d9d30e6d518e964b4f88cbe4a8e5a6eca6dfe3e68fb4a8917b3aae531eea9b86b0c7010a1b8a004f4bb
|
7
|
+
data.tar.gz: 36c44c53cc8bece4598c77033ed0251e275cd0b407cba993161606e48397c656eafe1ab5ab4aeed1601534878924ce0f9c59805a1c5117012f3296f2543a47b6
|
@@ -9,75 +9,105 @@ module Fastlane
|
|
9
9
|
UI.message("The xcresult_to_junit plugin has started!")
|
10
10
|
all_results = Helper::XcresultToJunitHelper.load_results(params[:xcresult_path])['actions']['_values']
|
11
11
|
all_results.each do |test_run|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
next unless test_run['actionResult']['testsRef'] # Skip if section has no testRef data as this means its not a test run
|
13
|
+
map = {}
|
14
|
+
junit_folder = Helper::XcresultToJunitHelper.save_device_details_to_file(params[:output_path], test_run['runDestination'])
|
15
|
+
test_run_id = test_run['actionResult']['testsRef']['id']['_value']
|
16
|
+
all_tests = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], test_run_id)['summaries']['_values'][0]['testableSummaries']['_values']
|
17
|
+
test_suites = []
|
18
|
+
all_tests.each do |target|
|
19
|
+
target_name = target['targetName']['_value']
|
20
|
+
unless target['tests']
|
21
|
+
failure_summary = target['failureSummaries']['_values'][0]
|
22
|
+
test_suites << { name: target_name, error: failure_summary['message']['_value'] }
|
23
|
+
next
|
24
|
+
end
|
25
|
+
test_classes = []
|
26
|
+
if defined?(target['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values'])
|
25
27
|
test_classes = target['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values']
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
end
|
29
|
+
test_classes.each do |test_class|
|
30
|
+
suite_name = "#{target_name}.#{test_class['name']['_value']}"
|
31
|
+
suite = { name: suite_name, cases: [] }
|
32
|
+
if test_class['subtests']
|
33
|
+
test_class['subtests']['_values'].each do |test|
|
34
|
+
duration = 0
|
35
|
+
duration = test['duration']['_value'] if test['duration']
|
36
|
+
testcase_name = test['name']['_value'].tr('()', '')
|
37
|
+
tags = testcase_name.split('_')[1..-1]
|
38
|
+
testcase_name = testcase_name.split('_').first
|
39
|
+
testcase = { name: testcase_name, time: duration }
|
40
|
+
map["#{suite_name}.#{testcase_name}"] = { 'files' => [], 'tags' => tags }
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
42
|
+
if defined?(test['summaryRef']['id']['_value'])
|
43
|
+
summary_ref = test['summaryRef']['id']['_value']
|
44
|
+
ref = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], summary_ref)
|
45
|
+
if defined?(ref['activitySummaries']['_values'])
|
46
|
+
ref['activitySummaries']['_values'].each do |summary|
|
47
|
+
next unless summary['attachments']
|
48
|
+
summary['attachments']['_values'].each do |attachment|
|
49
|
+
timestamp = DateTime.parse(attachment['timestamp']['_value']).to_time.to_i
|
50
|
+
filename = attachment['filename']['_value']
|
51
|
+
name = attachment['name']['_value']
|
52
|
+
folder_name = "#{suite_name}.#{testcase_name}"
|
53
|
+
id = attachment['payloadRef']['id']['_value']
|
54
|
+
Helper::XcresultToJunitHelper.fetch_screenshot(params[:xcresult_path], "#{junit_folder}/attachments/#{folder_name}", filename.to_s, id)
|
55
|
+
map[folder_name]['files'].push({ 'description' => name, 'mime-type' => 'image/png', 'path' => "#{folder_name}/#{filename}", 'timestamp' => timestamp })
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
57
59
|
|
58
|
-
if
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
60
|
+
if defined?(ref['performanceMetrics']['_value'])
|
61
|
+
performancemetrics = ""
|
62
|
+
ref['performanceMetrics']['_values'].each do |metric|
|
63
|
+
metricname = metric['displayName']['_value']
|
64
|
+
if defined?(metric['baselineAverage']['_value'])
|
65
|
+
metricbaseline = metric['baselineAverage']['_value']
|
66
|
+
else
|
67
|
+
metricbaseline = 0
|
68
|
+
end
|
69
|
+
metricmaxdev = metric['maxPercentRelativeStandardDeviation']['_value']
|
70
|
+
metricunit = metric['unitOfMeasurement']['_value']
|
71
|
+
metricave = 0
|
72
|
+
measurecount = 0
|
73
|
+
metric['measurements']['_values'].each do |measure|
|
74
|
+
metricave += measure['_value'].to_f
|
75
|
+
measurecount += 1
|
76
|
+
end
|
77
|
+
metricave = (metricave / measurecount).round(2)
|
78
|
+
if metricbaseline != 0
|
79
|
+
metricresult = (((metricbaseline.to_f - metricave) / metricbaseline.to_f) * 100).round(2)
|
80
|
+
else
|
81
|
+
metricresult = 0
|
82
|
+
end
|
83
|
+
performancemetric = "\nMetric: #{metricname}\nResult: #{metricresult}%\nAverage: #{metricave}#{metricunit}\nBaseline: #{metricbaseline}#{metricunit}\nMax Deviation: #{metricmaxdev}%\n\n"
|
84
|
+
performancemetrics << performancemetric
|
67
85
|
end
|
86
|
+
testcase[:performance] = performancemetrics
|
87
|
+
end
|
88
|
+
end
|
89
|
+
if test['testStatus']['_value'] == 'Failure'
|
90
|
+
failure = Helper::XcresultToJunitHelper.load_object(params[:xcresult_path], test['summaryRef']['id']['_value'])['failureSummaries']['_values'][0]
|
91
|
+
filename = failure.dig('fileName', '_value')
|
92
|
+
message = failure['message']['_value']
|
93
|
+
if filename == '<unknown>' || filename.nil?
|
94
|
+
testcase[:error] = message
|
95
|
+
else
|
96
|
+
testcase[:failure] = message
|
97
|
+
testcase[:failure_location] = "#{filename}:#{failure['lineNumber']['_value']}"
|
68
98
|
end
|
69
|
-
suite[:cases] << testcase
|
70
99
|
end
|
100
|
+
suite[:cases] << testcase
|
71
101
|
end
|
72
|
-
suite[:count] = suite[:cases].size
|
73
|
-
suite[:failures] = suite[:cases].count { |testcase| testcase[:failure] }
|
74
|
-
suite[:errors] = suite[:cases].count { |testcase| testcase[:error] }
|
75
|
-
test_suites << suite
|
76
102
|
end
|
103
|
+
suite[:count] = suite[:cases].size
|
104
|
+
suite[:failures] = suite[:cases].count { |testcase| testcase[:failure] }
|
105
|
+
suite[:errors] = suite[:cases].count { |testcase| testcase[:error] }
|
106
|
+
test_suites << suite
|
77
107
|
end
|
78
|
-
Helper::XcresultToJunitHelper.generate_junit(junit_folder, test_suites)
|
79
|
-
Helper::XcresultToJunitHelper.save_screenshot_mapping(map, "#{junit_folder}/attachments/")
|
80
108
|
end
|
109
|
+
Helper::XcresultToJunitHelper.generate_junit(junit_folder, test_suites)
|
110
|
+
Helper::XcresultToJunitHelper.save_screenshot_mapping(map, "#{junit_folder}/attachments/")
|
81
111
|
end
|
82
112
|
UI.message("The xcresult_to_junit plugin has finished!")
|
83
113
|
end
|
@@ -105,17 +135,17 @@ module Fastlane
|
|
105
135
|
description: "The path to the xcresult file",
|
106
136
|
optional: false,
|
107
137
|
type: String),
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
119
|
-
end
|
138
|
+
FastlaneCore::ConfigItem.new(key: :output_path,
|
139
|
+
env_name: "XCRESULT_TO_JUNIT_OUTPUT_PATH",
|
140
|
+
description: "The path where the output will be placed",
|
141
|
+
optional: false,
|
142
|
+
type: String)
|
143
|
+
]
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.is_supported?(platform)
|
147
|
+
[:ios, :mac].include?(platform)
|
120
148
|
end
|
121
149
|
end
|
150
|
+
end
|
151
|
+
end
|
@@ -8,18 +8,18 @@ module Fastlane
|
|
8
8
|
module Helper
|
9
9
|
class XcresultToJunitHelper
|
10
10
|
def self.load_object(xcresult_path, id)
|
11
|
-
JSON.
|
11
|
+
JSON.parse(FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool get --format json --path #{xcresult_path} --id #{id}"))
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.load_results(xcresult_path)
|
15
|
-
JSON.
|
15
|
+
JSON.parse(FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool get --format json --path #{xcresult_path}"))
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.fetch_screenshot(xcresult_path, output_path, file_name, id)
|
19
|
-
|
20
|
-
FileUtils.mkdir
|
19
|
+
unless File.directory?(output_path)
|
20
|
+
FileUtils.mkdir(output_path)
|
21
21
|
end
|
22
|
-
|
22
|
+
FastlaneCore::CommandExecutor.execute(command: "xcrun xcresulttool export --path #{xcresult_path} --output-path \"#{output_path}/#{file_name}\" --id #{id} --type file")
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.save_screenshot_mapping(map_hash, output_path)
|
@@ -37,9 +37,8 @@ module Fastlane
|
|
37
37
|
}.to_json
|
38
38
|
|
39
39
|
junit_folder = "#{output_path}/ios-#{device_udid}.junit"
|
40
|
-
FileUtils.rm_rf
|
41
|
-
FileUtils.
|
42
|
-
FileUtils.mkdir "#{junit_folder}/attachments"
|
40
|
+
FileUtils.rm_rf(junit_folder)
|
41
|
+
FileUtils.mkdir_p("#{junit_folder}/attachments")
|
43
42
|
File.open("#{junit_folder}/device.json", 'w') do |f|
|
44
43
|
f << device_details
|
45
44
|
end
|
@@ -47,52 +46,52 @@ module Fastlane
|
|
47
46
|
end
|
48
47
|
|
49
48
|
def self.junit_file_start
|
50
|
-
puts
|
51
|
-
puts
|
49
|
+
puts('<?xml version="1.0" encoding="UTF-8"?>')
|
50
|
+
puts('<testsuites>')
|
52
51
|
end
|
53
52
|
|
54
53
|
def self.junit_file_end
|
55
|
-
puts
|
54
|
+
puts('</testsuites>')
|
56
55
|
end
|
57
56
|
|
58
57
|
def self.junit_suite_error(suite)
|
59
|
-
puts
|
60
|
-
puts
|
58
|
+
puts("<testsuite name=#{suite[:name].encode(xml: :attr)} errors='1'>")
|
59
|
+
puts("<error>#{suite[:error].encode(xml: :text)}</error>")
|
61
60
|
end
|
62
61
|
|
63
62
|
def self.junit_suite_start(suite)
|
64
|
-
puts
|
63
|
+
puts("<testsuite name=#{suite[:name].encode(xml: :attr)} tests='#{suite[:count]}' failures='#{suite[:failures]}' errors='#{suite[:errors]}'>")
|
65
64
|
end
|
66
65
|
|
67
66
|
def self.junit_suite_end
|
68
|
-
puts
|
67
|
+
puts('</testsuite>')
|
69
68
|
end
|
70
69
|
|
71
70
|
def self.junit_testcase_start(suite, testcase)
|
72
|
-
print
|
71
|
+
print("<testcase name=#{testcase[:name].encode(xml: :attr)} classname=#{suite[:name].encode(xml: :attr)} time='#{testcase[:time]}'>")
|
73
72
|
end
|
74
73
|
|
75
|
-
def self.
|
76
|
-
puts
|
74
|
+
def self.junit_testcase_end
|
75
|
+
puts('</testcase>')
|
77
76
|
end
|
78
77
|
|
79
78
|
def self.junit_testcase_failure(testcase)
|
80
|
-
puts
|
81
|
-
puts "<failure message=#{testcase[:failure].encode xml: :attr}>#{testcase[:failure_location].encode xml: :text}</failure>"
|
82
|
-
puts '</testcase>'
|
79
|
+
puts("<failure message=#{testcase[:failure].encode(xml: :attr)}>#{testcase[:failure_location].encode(xml: :text)}</failure>")
|
83
80
|
end
|
84
81
|
|
85
82
|
def self.junit_testcase_error(testcase)
|
86
|
-
puts
|
87
|
-
|
88
|
-
|
83
|
+
puts("<error>#{testcase[:error].encode(xml: :text)}</error>")
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.junit_testcase_performance(testcase)
|
87
|
+
puts("<system-out>#{testcase[:performance]}</system-out>")
|
89
88
|
end
|
90
89
|
|
91
90
|
def self.generate_junit(junit_folder, test_suites)
|
92
91
|
File.open("#{junit_folder}/results.xml", 'w') do |fo|
|
93
92
|
old_stdout = $stdout
|
94
93
|
$stdout = fo
|
95
|
-
Helper::XcresultToJunitHelper.junit_file_start
|
94
|
+
Helper::XcresultToJunitHelper.junit_file_start
|
96
95
|
test_suites.each do |suite|
|
97
96
|
if suite[:error]
|
98
97
|
Helper::XcresultToJunitHelper.junit_suite_error(suite)
|
@@ -104,14 +103,16 @@ module Fastlane
|
|
104
103
|
Helper::XcresultToJunitHelper.junit_testcase_failure(testcase)
|
105
104
|
elsif testcase[:error]
|
106
105
|
Helper::XcresultToJunitHelper.junit_testcase_error(testcase)
|
107
|
-
else
|
108
|
-
Helper::XcresultToJunitHelper.junit_testcase_success()
|
109
106
|
end
|
107
|
+
if testcase[:performance]
|
108
|
+
Helper::XcresultToJunitHelper.junit_testcase_performance(testcase)
|
109
|
+
end
|
110
|
+
Helper::XcresultToJunitHelper.junit_testcase_end
|
110
111
|
end
|
111
112
|
end
|
112
|
-
Helper::XcresultToJunitHelper.junit_suite_end
|
113
|
+
Helper::XcresultToJunitHelper.junit_suite_end
|
113
114
|
end
|
114
|
-
Helper::XcresultToJunitHelper.junit_file_end
|
115
|
+
Helper::XcresultToJunitHelper.junit_file_end
|
115
116
|
$stdout = old_stdout
|
116
117
|
end
|
117
118
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-xcresult_to_junit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Birdsall
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -136,7 +136,7 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 2.134.0
|
139
|
-
description:
|
139
|
+
description:
|
140
140
|
email: shane.birdsall@fiserv.com
|
141
141
|
executables: []
|
142
142
|
extensions: []
|
@@ -152,7 +152,7 @@ homepage: https://github.com/zanizrules/fastlane-plugin-xcresult_to_junit
|
|
152
152
|
licenses:
|
153
153
|
- MIT
|
154
154
|
metadata: {}
|
155
|
-
post_install_message:
|
155
|
+
post_install_message:
|
156
156
|
rdoc_options: []
|
157
157
|
require_paths:
|
158
158
|
- lib
|
@@ -167,9 +167,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
167
|
- !ruby/object:Gem::Version
|
168
168
|
version: '0'
|
169
169
|
requirements: []
|
170
|
-
rubyforge_project:
|
170
|
+
rubyforge_project:
|
171
171
|
rubygems_version: 2.7.6.2
|
172
|
-
signing_key:
|
172
|
+
signing_key:
|
173
173
|
specification_version: 4
|
174
174
|
summary: Produces junit xml files from Xcode 11+ xcresult files
|
175
175
|
test_files: []
|