fastlane-plugin-test_center 3.3.0 → 3.4.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/README.md +83 -6
- data/lib/fastlane/plugin/test_center/actions/collate_json_reports.rb +168 -0
- data/lib/fastlane/plugin/test_center/actions/multi_scan.rb +31 -2
- data/lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb +69 -19
- data/lib/fastlane/plugin/test_center/helper/reportname_helper.rb +38 -3
- data/lib/fastlane/plugin/test_center/version.rb +1 -1
- metadata +31 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '083be0187ece34a8f7019e4992c1fa2330b4732d'
|
|
4
|
+
data.tar.gz: 364b206944566949934477d518853537f27cdabb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 64532eb3e5dfe6afdf6b49fe27555e58d052fc60cf3d57363becf437704e0519a696889032f0106fabafabaf5ab808f0f713b059af75a38f0e9aecc44e8f2cde
|
|
7
|
+
data.tar.gz: 301e3e7946ab86b32aa310fd73b01cb2b222c00b99d1a255575964c1bed55ca864bf66b55ff2d50690776ff399d3c57335ac3d6737de2262c50a720a565af0e5
|
data/README.md
CHANGED
|
@@ -69,6 +69,7 @@ This fastlane plugin includes the following actions:
|
|
|
69
69
|
- [`tests_from_xctestrun`](#tests_from_xctestrun): from an xctestrun file, returns a list of tests for each of its test targets.
|
|
70
70
|
- [`collate_junit_reports`](#collate_junit_reports): combines multiple junit test reports into one report.
|
|
71
71
|
- [`collate_html_reports`](#collate_html_reports): combines multiple html test reports into one report.
|
|
72
|
+
- [`collate_json_reports`](#collate_json_reports): combines multiple json test reports into one report.
|
|
72
73
|
|
|
73
74
|
### multi_scan 🎉
|
|
74
75
|
|
|
@@ -202,7 +203,8 @@ multi_scan(
|
|
|
202
203
|
skip_build: true,
|
|
203
204
|
clean: true,
|
|
204
205
|
try_count: 3,
|
|
205
|
-
result_bundle: true
|
|
206
|
+
result_bundle: true,
|
|
207
|
+
fail_build: false
|
|
206
208
|
)
|
|
207
209
|
|
|
208
210
|
```
|
|
@@ -235,7 +237,25 @@ multi_scan(
|
|
|
235
237
|
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
|
236
238
|
scheme: 'AtomicBoy',
|
|
237
239
|
try_count: 3,
|
|
238
|
-
only_testing: ['AtomicBoyTests']
|
|
240
|
+
only_testing: ['AtomicBoyTests'],
|
|
241
|
+
fail_build: false
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
|
|
248
|
+
UI.important(
|
|
249
|
+
'example: ' \
|
|
250
|
+
'multi_scan also works with json.'
|
|
251
|
+
)
|
|
252
|
+
multi_scan(
|
|
253
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
|
254
|
+
scheme: 'AtomicBoy',
|
|
255
|
+
try_count: 3,
|
|
256
|
+
output_types: 'json',
|
|
257
|
+
output_files: 'report.json',
|
|
258
|
+
fail_build: false
|
|
239
259
|
)
|
|
240
260
|
|
|
241
261
|
```
|
|
@@ -328,6 +348,23 @@ suppress_tests(
|
|
|
328
348
|
scheme: 'Professor'
|
|
329
349
|
)
|
|
330
350
|
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
```ruby
|
|
354
|
+
|
|
355
|
+
UI.important(
|
|
356
|
+
'example: ' \
|
|
357
|
+
'suppress some tests in one Scheme from a workspace'
|
|
358
|
+
)
|
|
359
|
+
suppress_tests(
|
|
360
|
+
workspace: 'AtomicBoy/AtomicBoy.xcworkspace',
|
|
361
|
+
tests: [
|
|
362
|
+
'AtomicBoyUITests/HappyNapperTests/testBeepingNonExistentFriendDisplaysError',
|
|
363
|
+
'AtomicBoyUITests/GrumpyWorkerTests'
|
|
364
|
+
],
|
|
365
|
+
scheme: 'Professor'
|
|
366
|
+
)
|
|
367
|
+
|
|
331
368
|
```
|
|
332
369
|
<!-- suppress_tests examples: end -->
|
|
333
370
|
</details>
|
|
@@ -364,6 +401,20 @@ UI.message(
|
|
|
364
401
|
"Suppressed tests for project: #{suppressed_tests(xcodeproj: 'AtomicBoy/AtomicBoy.xcodeproj')}"
|
|
365
402
|
)
|
|
366
403
|
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
```ruby
|
|
407
|
+
|
|
408
|
+
UI.important(
|
|
409
|
+
'example: ' \
|
|
410
|
+
'get the tests that are suppressed in all Schemes in a workspace'
|
|
411
|
+
)
|
|
412
|
+
tests = suppressed_tests(
|
|
413
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
|
414
|
+
scheme: 'Professor'
|
|
415
|
+
)
|
|
416
|
+
UI.message("tests: #{tests}")
|
|
417
|
+
|
|
367
418
|
```
|
|
368
419
|
<!-- suppressed_tests examples: end -->
|
|
369
420
|
</details>
|
|
@@ -438,10 +489,11 @@ Do you have multiple junit test reports coming in from different sources and nee
|
|
|
438
489
|
|
|
439
490
|
UI.important(
|
|
440
491
|
'example: ' \
|
|
441
|
-
'collate the xml reports to a temporary file
|
|
492
|
+
'collate the xml reports to a temporary file "result.xml"'
|
|
442
493
|
)
|
|
494
|
+
reports = Dir['../spec/fixtures/*.xml'].map { |relpath| File.absolute_path(relpath) }
|
|
443
495
|
collate_junit_reports(
|
|
444
|
-
reports:
|
|
496
|
+
reports: reports,
|
|
445
497
|
collated_report: File.join(Dir.mktmpdir, 'result.xml')
|
|
446
498
|
)
|
|
447
499
|
|
|
@@ -461,10 +513,11 @@ Do you have multiple html test reports coming in from different sources and need
|
|
|
461
513
|
|
|
462
514
|
UI.important(
|
|
463
515
|
'example: ' \
|
|
464
|
-
'collate the html reports to a temporary file
|
|
516
|
+
'collate the html reports to a temporary file "result.html"'
|
|
465
517
|
)
|
|
518
|
+
reports = Dir['../spec/fixtures/*.html'].map { |relpath| File.absolute_path(relpath) }
|
|
466
519
|
collate_html_reports(
|
|
467
|
-
reports:
|
|
520
|
+
reports: reports,
|
|
468
521
|
collated_report: File.join(Dir.mktmpdir, 'result.html')
|
|
469
522
|
)
|
|
470
523
|
|
|
@@ -472,6 +525,30 @@ collate_html_reports(
|
|
|
472
525
|
<!-- collate_html_reports examples: end -->
|
|
473
526
|
</details>
|
|
474
527
|
|
|
528
|
+
### collate_json_reports
|
|
529
|
+
|
|
530
|
+
Do you have multiple json test reports coming in from different sources and need it combined? Use this action to collate all the tests performed for a given test target into one report file.
|
|
531
|
+
|
|
532
|
+
<details>
|
|
533
|
+
<summary>Example Code:</summary>
|
|
534
|
+
<!-- collate_json_reports examples: begin -->
|
|
535
|
+
|
|
536
|
+
```ruby
|
|
537
|
+
|
|
538
|
+
UI.important(
|
|
539
|
+
'example: ' \
|
|
540
|
+
'collate the json reports to a temporary file "result.json"'
|
|
541
|
+
)
|
|
542
|
+
reports = Dir['../spec/fixtures/report*.json'].map { |relpath| File.absolute_path(relpath) }
|
|
543
|
+
collate_json_reports(
|
|
544
|
+
reports: reports,
|
|
545
|
+
collated_report: File.join(Dir.mktmpdir, 'result.json')
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
```
|
|
549
|
+
<!-- collate_json_reports examples: end -->
|
|
550
|
+
</details>
|
|
551
|
+
|
|
475
552
|
## Run tests for this plugin
|
|
476
553
|
|
|
477
554
|
To run both the tests, and code style validation, run
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
module Fastlane
|
|
2
|
+
module Actions
|
|
3
|
+
class CollateJsonReportsAction < Action
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
def self.run(params)
|
|
7
|
+
report_filepaths = params[:reports]
|
|
8
|
+
if report_filepaths.size == 1
|
|
9
|
+
FileUtils.cp(report_filepaths[0], params[:collated_report])
|
|
10
|
+
else
|
|
11
|
+
base_report_json = JSON.parse(File.read(report_filepaths.shift))
|
|
12
|
+
report_filepaths.each do |report_file|
|
|
13
|
+
report_json = JSON.parse(File.read(report_file))
|
|
14
|
+
update_previous_test_failures(base_report_json)
|
|
15
|
+
merge_reports(base_report_json, report_json)
|
|
16
|
+
end
|
|
17
|
+
File.open(params[:collated_report], 'w') do |f|
|
|
18
|
+
f.write(JSON.pretty_generate(base_report_json))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.merge_reports(base_report, other_report)
|
|
24
|
+
base_report.each_key do |key|
|
|
25
|
+
unless %w(previous_tests_failures tests_failures tests_summary_messages).include?(key)
|
|
26
|
+
base_report[key].concat(other_report[key])
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
base_report["tests_failures"] = other_report["tests_failures"]
|
|
30
|
+
update_failed_tests_count(base_report, other_report)
|
|
31
|
+
update_time(base_report, other_report)
|
|
32
|
+
update_unexpected_failures(base_report, other_report)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.update_time(base_report, other_report)
|
|
36
|
+
base_test_time, base_total_time = times_from_summary(base_report['tests_summary_messages'][0])
|
|
37
|
+
other_test_time, other_total_time = times_from_summary(other_report['tests_summary_messages'][0])
|
|
38
|
+
time_regex = '(?:\d|\.)+'
|
|
39
|
+
|
|
40
|
+
test_time_sum = (base_test_time + other_test_time).round(3)
|
|
41
|
+
total_time_sum = (base_total_time + other_total_time).round(3)
|
|
42
|
+
base_report['tests_summary_messages'][0].sub!(
|
|
43
|
+
/in #{time_regex} \(#{time_regex}\) seconds/,
|
|
44
|
+
"in #{test_time_sum} (#{total_time_sum}) seconds"
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.update_unexpected_failures(base_report, other_report)
|
|
49
|
+
base_unexpected_failures = unexpected_failures_from_summary(base_report['tests_summary_messages'][0])
|
|
50
|
+
other_unexpected_failures = unexpected_failures_from_summary(other_report['tests_summary_messages'][0])
|
|
51
|
+
base_report['tests_summary_messages'][0].sub!(
|
|
52
|
+
/\(\d+ unexpected\)/,
|
|
53
|
+
"(#{base_unexpected_failures + other_unexpected_failures} unexpected)"
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.unexpected_failures_from_summary(summary)
|
|
58
|
+
/\((?<unexpected_failures>\d+) unexpected\)/ =~ summary
|
|
59
|
+
unexpected_failures.to_i
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.times_from_summary(summary)
|
|
63
|
+
time_regex = '(?:\d|\.)+'
|
|
64
|
+
match = /in (?<test_time>#{time_regex}) \((?<total_time>#{time_regex})\) seconds/.match(summary)
|
|
65
|
+
return [
|
|
66
|
+
match['test_time'].to_f,
|
|
67
|
+
match['total_time'].to_f
|
|
68
|
+
]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.update_failed_tests_count(base_report, other_report)
|
|
72
|
+
/\s+Executed \d+ tests?, with (?<failed_test_count>\d+) failures?/ =~ other_report['tests_summary_messages'][0]
|
|
73
|
+
|
|
74
|
+
base_report['tests_summary_messages'][0].sub!(
|
|
75
|
+
/(\d+) failure/,
|
|
76
|
+
"#{failed_test_count} failure"
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.update_previous_test_failures(base_report)
|
|
81
|
+
previous_tests_failures = base_report['previous_tests_failures']
|
|
82
|
+
if previous_tests_failures
|
|
83
|
+
tests_failures = base_report['tests_failures']
|
|
84
|
+
tests_failures.each do |failure_suite, failures|
|
|
85
|
+
if previous_tests_failures.key?(failure_suite)
|
|
86
|
+
previous_tests_failures[failure_suite].concat(failures)
|
|
87
|
+
else
|
|
88
|
+
previous_tests_failures[failure_suite] = failures
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
else
|
|
92
|
+
base_report['previous_tests_failures'] = base_report['tests_failures'] || {}
|
|
93
|
+
end
|
|
94
|
+
base_report.delete('tests_failures')
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
#####################################################
|
|
98
|
+
# @!group Documentation
|
|
99
|
+
#####################################################
|
|
100
|
+
|
|
101
|
+
def self.description
|
|
102
|
+
"Combines and combines tests from multiple json report files"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def self.details
|
|
106
|
+
"The first JSON report is used as the base report. Due to the nature of " \
|
|
107
|
+
"xcpretty JSON reports, only the failing test cases are recorded. " \
|
|
108
|
+
"Testcases that failed in previous reports that no longer appear in " \
|
|
109
|
+
"later reports are assumed to have passed in a re-run, thus not appearing " \
|
|
110
|
+
"in the collated report. " \
|
|
111
|
+
"This is done because it is assumed that fragile tests, when " \
|
|
112
|
+
"re-run will often succeed due to less interference from other " \
|
|
113
|
+
"tests and the subsequent JSON reports will have fewer failing tests." \
|
|
114
|
+
""
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.available_options
|
|
118
|
+
[
|
|
119
|
+
FastlaneCore::ConfigItem.new(
|
|
120
|
+
key: :reports,
|
|
121
|
+
env_name: 'COLLATE_JSON_REPORTS_REPORTS',
|
|
122
|
+
description: 'An array of JSON reports to collate. The first report is used as the base into which other reports are merged in',
|
|
123
|
+
optional: false,
|
|
124
|
+
type: Array,
|
|
125
|
+
verify_block: proc do |reports|
|
|
126
|
+
UI.user_error!('No JSON report files found') if reports.empty?
|
|
127
|
+
reports.each do |report|
|
|
128
|
+
UI.user_error!("Error: JSON report not found: '#{report}'") unless File.exist?(report)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
),
|
|
132
|
+
FastlaneCore::ConfigItem.new(
|
|
133
|
+
key: :collated_report,
|
|
134
|
+
env_name: 'COLLATE_JSON_REPORTS_COLLATED_REPORT',
|
|
135
|
+
description: 'The final JSON report file where all testcases will be merged into',
|
|
136
|
+
optional: true,
|
|
137
|
+
default_value: 'result.json',
|
|
138
|
+
type: String
|
|
139
|
+
)
|
|
140
|
+
]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def self.example_code
|
|
144
|
+
[
|
|
145
|
+
"
|
|
146
|
+
UI.important(
|
|
147
|
+
'example: ' \\
|
|
148
|
+
'collate the json reports to a temporary file \"result.json\"'
|
|
149
|
+
)
|
|
150
|
+
reports = Dir['../spec/fixtures/report*.json'].map { |relpath| File.absolute_path(relpath) }
|
|
151
|
+
collate_json_reports(
|
|
152
|
+
reports: reports,
|
|
153
|
+
collated_report: File.join(Dir.mktmpdir, 'result.json')
|
|
154
|
+
)
|
|
155
|
+
"
|
|
156
|
+
]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def self.authors
|
|
160
|
+
["lyndsey-ferguson/@lyndseydf"]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def self.is_supported?(platform)
|
|
164
|
+
platform == :ios
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -58,6 +58,11 @@ module Fastlane
|
|
|
58
58
|
File.absolute_path(relative_filepath)
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
|
+
if reportnamer.includes_json?
|
|
62
|
+
report_files += Dir.glob("#{scan_options[:output_directory]}/**/#{reportnamer.json_fileglob}").map do |relative_filepath|
|
|
63
|
+
File.absolute_path(relative_filepath)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
61
66
|
{
|
|
62
67
|
result: tests_passed,
|
|
63
68
|
total_tests: passing_testcount + failed_tests.size,
|
|
@@ -76,6 +81,8 @@ module Fastlane
|
|
|
76
81
|
batch_count
|
|
77
82
|
testrun_completed_block
|
|
78
83
|
test_without_building
|
|
84
|
+
output_types
|
|
85
|
+
output_files
|
|
79
86
|
]
|
|
80
87
|
config = FastlaneCore::Configuration.create(
|
|
81
88
|
Fastlane::Actions::ScanAction.available_options,
|
|
@@ -118,7 +125,7 @@ module Fastlane
|
|
|
118
125
|
end
|
|
119
126
|
|
|
120
127
|
def self.scan_options
|
|
121
|
-
ScanAction.available_options
|
|
128
|
+
ScanAction.available_options.reject { |config| config.key == :output_types }
|
|
122
129
|
end
|
|
123
130
|
|
|
124
131
|
def self.available_options
|
|
@@ -143,6 +150,13 @@ module Fastlane
|
|
|
143
150
|
UI.user_error!("Error: Batch counts must be greater than zero") unless count > 0
|
|
144
151
|
end
|
|
145
152
|
),
|
|
153
|
+
FastlaneCore::ConfigItem.new(
|
|
154
|
+
key: :output_types,
|
|
155
|
+
short_option: "-f",
|
|
156
|
+
env_name: "SCAN_OUTPUT_TYPES",
|
|
157
|
+
description: "Comma separated list of the output types (e.g. html, junit, json, json-compilation-database)",
|
|
158
|
+
default_value: "html,junit"
|
|
159
|
+
),
|
|
146
160
|
FastlaneCore::ConfigItem.new(
|
|
147
161
|
key: :testrun_completed_block,
|
|
148
162
|
description: 'A block invoked each time a test run completes',
|
|
@@ -286,7 +300,22 @@ module Fastlane
|
|
|
286
300
|
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
|
287
301
|
scheme: 'AtomicBoy',
|
|
288
302
|
try_count: 3,
|
|
289
|
-
only_testing: ['AtomicBoyTests']
|
|
303
|
+
only_testing: ['AtomicBoyTests'],
|
|
304
|
+
fail_build: false
|
|
305
|
+
)
|
|
306
|
+
",
|
|
307
|
+
"
|
|
308
|
+
UI.important(
|
|
309
|
+
'example: ' \\
|
|
310
|
+
'multi_scan also works with json.'
|
|
311
|
+
)
|
|
312
|
+
multi_scan(
|
|
313
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
|
314
|
+
scheme: 'AtomicBoy',
|
|
315
|
+
try_count: 3,
|
|
316
|
+
output_types: 'json',
|
|
317
|
+
output_files: 'report.json',
|
|
318
|
+
fail_build: false
|
|
290
319
|
)
|
|
291
320
|
"
|
|
292
321
|
]
|
|
@@ -2,7 +2,7 @@ module TestCenter
|
|
|
2
2
|
module Helper
|
|
3
3
|
require 'fastlane_core/ui/ui.rb'
|
|
4
4
|
require 'plist'
|
|
5
|
-
|
|
5
|
+
require 'json'
|
|
6
6
|
class CorrectingScanHelper
|
|
7
7
|
attr_reader :retry_total_count
|
|
8
8
|
|
|
@@ -26,6 +26,8 @@ module TestCenter
|
|
|
26
26
|
custom_report_file_name
|
|
27
27
|
fail_build
|
|
28
28
|
testrun_completed_block
|
|
29
|
+
output_types
|
|
30
|
+
output_files
|
|
29
31
|
].include?(option)
|
|
30
32
|
end
|
|
31
33
|
@scan_options[:clean] = false
|
|
@@ -92,6 +94,59 @@ module TestCenter
|
|
|
92
94
|
end
|
|
93
95
|
|
|
94
96
|
def collate_reports(output_directory, reportnamer)
|
|
97
|
+
collate_junit_reports(output_directory, reportnamer)
|
|
98
|
+
|
|
99
|
+
if reportnamer.includes_html?
|
|
100
|
+
collate_html_reports(output_directory, reportnamer)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
if reportnamer.includes_json?
|
|
104
|
+
collate_json_reports(output_directory, reportnamer)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def passed_test_count_from_summary(summary)
|
|
109
|
+
/.*Executed (?<test_count>\d+) test, with (?<test_failures>\d+) failure/ =~ summary
|
|
110
|
+
test_count.to_i - test_failures.to_i
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def collate_json_reports(output_directory, reportnamer)
|
|
114
|
+
report_filepaths = Dir.glob("#{output_directory}/#{reportnamer.json_fileglob}").map do |relative_filepath|
|
|
115
|
+
File.absolute_path(relative_filepath)
|
|
116
|
+
end
|
|
117
|
+
if report_filepaths.size > 1
|
|
118
|
+
config = FastlaneCore::Configuration.create(
|
|
119
|
+
Fastlane::Actions::CollateJsonReportsAction.available_options,
|
|
120
|
+
{
|
|
121
|
+
reports: report_filepaths.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
|
|
122
|
+
collated_report: File.absolute_path(File.join(output_directory, reportnamer.json_reportname))
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
Fastlane::Actions::CollateJsonReportsAction.run(config)
|
|
126
|
+
end
|
|
127
|
+
retried_json_reportfiles = Dir.glob("#{output_directory}/#{reportnamer.json_numbered_fileglob}")
|
|
128
|
+
FileUtils.rm_f(retried_json_reportfiles)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def collate_html_reports(output_directory, reportnamer)
|
|
132
|
+
report_files = Dir.glob("#{output_directory}/#{reportnamer.html_fileglob}").map do |relative_filepath|
|
|
133
|
+
File.absolute_path(relative_filepath)
|
|
134
|
+
end
|
|
135
|
+
if report_files.size > 1
|
|
136
|
+
config = FastlaneCore::Configuration.create(
|
|
137
|
+
Fastlane::Actions::CollateHtmlReportsAction.available_options,
|
|
138
|
+
{
|
|
139
|
+
reports: report_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
|
|
140
|
+
collated_report: File.absolute_path(File.join(output_directory, reportnamer.html_reportname))
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
Fastlane::Actions::CollateHtmlReportsAction.run(config)
|
|
144
|
+
end
|
|
145
|
+
retried_html_reportfiles = Dir.glob("#{output_directory}/#{reportnamer.html_numbered_fileglob}")
|
|
146
|
+
FileUtils.rm_f(retried_html_reportfiles)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def collate_junit_reports(output_directory, reportnamer)
|
|
95
150
|
report_files = Dir.glob("#{output_directory}/#{reportnamer.junit_fileglob}").map do |relative_filepath|
|
|
96
151
|
File.absolute_path(relative_filepath)
|
|
97
152
|
end
|
|
@@ -107,30 +162,13 @@ module TestCenter
|
|
|
107
162
|
end
|
|
108
163
|
retried_junit_reportfiles = Dir.glob("#{output_directory}/#{reportnamer.junit_numbered_fileglob}")
|
|
109
164
|
FileUtils.rm_f(retried_junit_reportfiles)
|
|
110
|
-
|
|
111
|
-
if reportnamer.includes_html?
|
|
112
|
-
report_files = Dir.glob("#{output_directory}/#{reportnamer.html_fileglob}").map do |relative_filepath|
|
|
113
|
-
File.absolute_path(relative_filepath)
|
|
114
|
-
end
|
|
115
|
-
if report_files.size > 1
|
|
116
|
-
config = FastlaneCore::Configuration.create(
|
|
117
|
-
Fastlane::Actions::CollateHtmlReportsAction.available_options,
|
|
118
|
-
{
|
|
119
|
-
reports: report_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
|
|
120
|
-
collated_report: File.absolute_path(File.join(output_directory, reportnamer.html_reportname))
|
|
121
|
-
}
|
|
122
|
-
)
|
|
123
|
-
Fastlane::Actions::CollateHtmlReportsAction.run(config)
|
|
124
|
-
end
|
|
125
|
-
retried_html_reportfiles = Dir.glob("#{output_directory}/#{reportnamer.html_numbered_fileglob}")
|
|
126
|
-
FileUtils.rm_f(retried_html_reportfiles)
|
|
127
|
-
end
|
|
128
165
|
end
|
|
129
166
|
|
|
130
167
|
def correcting_scan(scan_run_options, batch, reportnamer)
|
|
131
168
|
scan_options = @scan_options.merge(scan_run_options)
|
|
132
169
|
try_count = 0
|
|
133
170
|
tests_passed = true
|
|
171
|
+
xcpretty_json_file_output = ENV['XCPRETTY_JSON_FILE_OUTPUT']
|
|
134
172
|
begin
|
|
135
173
|
try_count += 1
|
|
136
174
|
config = FastlaneCore::Configuration.create(
|
|
@@ -138,6 +176,12 @@ module TestCenter
|
|
|
138
176
|
scan_options.merge(reportnamer.scan_options)
|
|
139
177
|
)
|
|
140
178
|
quit_simulators
|
|
179
|
+
if reportnamer.includes_json?
|
|
180
|
+
ENV['XCPRETTY_JSON_FILE_OUTPUT'] = File.join(
|
|
181
|
+
scan_options[:output_directory],
|
|
182
|
+
reportnamer.json_last_reportname
|
|
183
|
+
)
|
|
184
|
+
end
|
|
141
185
|
Fastlane::Actions::ScanAction.run(config)
|
|
142
186
|
@testrun_completed_block && @testrun_completed_block.call(
|
|
143
187
|
testrun_info(batch, try_count, reportnamer, scan_options[:output_directory])
|
|
@@ -164,6 +208,8 @@ module TestCenter
|
|
|
164
208
|
retry
|
|
165
209
|
end
|
|
166
210
|
tests_passed = false
|
|
211
|
+
ensure
|
|
212
|
+
ENV['XCPRETTY_JSON_FILE_OUTPUT'] = xcpretty_json_file_output
|
|
167
213
|
end
|
|
168
214
|
tests_passed
|
|
169
215
|
end
|
|
@@ -189,6 +235,10 @@ module TestCenter
|
|
|
189
235
|
html_report_filepath = File.join(output_directory, reportnamer.html_last_reportname)
|
|
190
236
|
info[:html_report_filepath] = html_report_filepath
|
|
191
237
|
end
|
|
238
|
+
if reportnamer.includes_json?
|
|
239
|
+
json_report_filepath = File.join(output_directory, reportnamer.json_last_reportname)
|
|
240
|
+
info[:json_report_filepath] = json_report_filepath
|
|
241
|
+
end
|
|
192
242
|
info
|
|
193
243
|
end
|
|
194
244
|
|
|
@@ -39,15 +39,24 @@ module TestCenter
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def scan_options
|
|
42
|
+
options = {}
|
|
43
|
+
|
|
44
|
+
types = @output_types.split(',').each(&:chomp)
|
|
42
45
|
files = @output_files.split(',').each(&:chomp)
|
|
46
|
+
if (json_index = types.find_index('json'))
|
|
47
|
+
options[:formatter] = 'xcpretty-json-formatter'
|
|
48
|
+
files.delete_at(json_index)
|
|
49
|
+
types.delete_at(json_index)
|
|
50
|
+
end
|
|
43
51
|
files.map! do |filename|
|
|
44
52
|
filename.chomp
|
|
45
53
|
numbered_filename(filename)
|
|
46
54
|
end
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
|
|
56
|
+
options.merge(
|
|
57
|
+
output_types: types.join(','),
|
|
49
58
|
output_files: files.join(',')
|
|
50
|
-
|
|
59
|
+
)
|
|
51
60
|
end
|
|
52
61
|
|
|
53
62
|
def junit_last_reportname
|
|
@@ -98,6 +107,32 @@ module TestCenter
|
|
|
98
107
|
"#{File.basename(html_reportname, '.*')}-[1-9]*#{html_filextension}"
|
|
99
108
|
end
|
|
100
109
|
|
|
110
|
+
def includes_json?
|
|
111
|
+
@output_types.split(',').find_index('json') != nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def json_last_reportname
|
|
115
|
+
json_index = @output_types.split(',').find_index('json')
|
|
116
|
+
numbered_filename(@output_files.to_s.split(',')[json_index])
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def json_reportname
|
|
120
|
+
json_index = @output_types.split(',').find_index('json')
|
|
121
|
+
@output_files.to_s.split(',')[json_index]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def json_filextension
|
|
125
|
+
File.extname(json_reportname)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def json_fileglob
|
|
129
|
+
"#{File.basename(json_reportname, '.*')}*#{json_filextension}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def json_numbered_fileglob
|
|
133
|
+
"#{File.basename(json_reportname, '.*')}-[1-9]*#{json_filextension}"
|
|
134
|
+
end
|
|
135
|
+
|
|
101
136
|
def increment
|
|
102
137
|
@report_count += 1
|
|
103
138
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fastlane-plugin-test_center
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lyndsey Ferguson
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-06-
|
|
11
|
+
date: 2018-06-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: json
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: plist
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -178,6 +192,20 @@ dependencies:
|
|
|
178
192
|
- - ">="
|
|
179
193
|
- !ruby/object:Gem::Version
|
|
180
194
|
version: '0'
|
|
195
|
+
- !ruby/object:Gem::Dependency
|
|
196
|
+
name: xcpretty-json-formatter
|
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
|
198
|
+
requirements:
|
|
199
|
+
- - ">="
|
|
200
|
+
- !ruby/object:Gem::Version
|
|
201
|
+
version: '0'
|
|
202
|
+
type: :development
|
|
203
|
+
prerelease: false
|
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
205
|
+
requirements:
|
|
206
|
+
- - ">="
|
|
207
|
+
- !ruby/object:Gem::Version
|
|
208
|
+
version: '0'
|
|
181
209
|
description: |2
|
|
182
210
|
This fastlane plugin includes the following actions:
|
|
183
211
|
1) multi_scan: uses scan to run Xcode tests, optionally in batches, a given number of times: only re-testing failing tests.
|
|
@@ -196,6 +224,7 @@ files:
|
|
|
196
224
|
- README.md
|
|
197
225
|
- lib/fastlane/plugin/test_center.rb
|
|
198
226
|
- lib/fastlane/plugin/test_center/actions/collate_html_reports.rb
|
|
227
|
+
- lib/fastlane/plugin/test_center/actions/collate_json_reports.rb
|
|
199
228
|
- lib/fastlane/plugin/test_center/actions/collate_junit_reports.rb
|
|
200
229
|
- lib/fastlane/plugin/test_center/actions/multi_scan.rb
|
|
201
230
|
- lib/fastlane/plugin/test_center/actions/suppress_tests.rb
|