fastlane-plugin-test_center 3.3.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|