fastlane-plugin-test_center 3.14.3 → 3.14.4
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 +1 -1
- data/lib/fastlane/plugin/test_center/actions/multi_scan.rb +128 -2
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/retrying_scan_helper.rb +23 -1
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/runner.rb +4 -4
- data/lib/fastlane/plugin/test_center/helper/test_collector.rb +145 -152
- data/lib/fastlane/plugin/test_center/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4364b9e3e49e3aa1a3bbd1e26feb07e449de72900bcd1ec3341ff8d1b0ca62ad
|
4
|
+
data.tar.gz: f983745b33c34838839d546aff4c4e407673c8241e72ab14b695d288792bdac4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bb52a9bcc82781df58b2ab2b6dd33c1831da0b345b9b51842959b8a372e5341b773cf639e3cb884bccc426336dad01c8ff1e7fc418fad0baefe201e12c46bab
|
7
|
+
data.tar.gz: 8d6e6a9321e13aada993f1099f45b7317f4d4c30e8bbdfa55a35a49a1a0dd3aa6c7e06c7dd244132e37d4c149ac0a6b9f94d9198d3f0bd8ee912853fa44f773d
|
data/README.md
CHANGED
@@ -99,7 +99,7 @@ _fastlane_ is the easiest way to automate beta deployments and releases for your
|
|
99
99
|
## Supporters
|
100
100
|
|
101
101
|

|
102
|
-
[vdavydovHH](https://github.com/vdavydovHH)
|
102
|
+
[vdavydovHH](https://github.com/vdavydovHH) [amelendezSGY](https://github.com/amelendezSGY)
|
103
103
|
|
104
104
|
## License
|
105
105
|
|
@@ -361,6 +361,14 @@ module Fastlane
|
|
361
361
|
UI.user_error!("Error: Batch counts must be greater than zero") unless count > 0
|
362
362
|
end
|
363
363
|
),
|
364
|
+
FastlaneCore::ConfigItem.new(
|
365
|
+
key: :batches,
|
366
|
+
env_name: "FL_MULTI_SCAN_BATCHES",
|
367
|
+
description: "The explicit batches (an Array of Arrays of test identifiers) to run either serially, or each batch on a simulator in parallel if :parallel_testrun_count is given",
|
368
|
+
type: Array,
|
369
|
+
optional: true,
|
370
|
+
conflicting_options: [:batch_count]
|
371
|
+
),
|
364
372
|
FastlaneCore::ConfigItem.new(
|
365
373
|
key: :retry_test_runner_failures,
|
366
374
|
description: "Set to true If you want to treat build failures during testing, like 'Test runner exited before starting test execution', as 'all tests failed'",
|
@@ -375,7 +383,7 @@ module Fastlane
|
|
375
383
|
is_string: false,
|
376
384
|
default_value: false,
|
377
385
|
optional: true,
|
378
|
-
conflicting_options: [
|
386
|
+
conflicting_options: %i[batch_count batches],
|
379
387
|
conflict_block: proc do |value|
|
380
388
|
UI.user_error!(
|
381
389
|
"Error: Can't use 'invocation_based_tests' and 'batch_count' options in one run, "\
|
@@ -433,7 +441,7 @@ module Fastlane
|
|
433
441
|
),
|
434
442
|
FastlaneCore::ConfigItem.new(
|
435
443
|
key: :testrun_completed_block,
|
436
|
-
description: 'A block invoked each time a test run completes. When combined with :parallel_testrun_count, will be called separately in each child process',
|
444
|
+
description: 'A block invoked each time a test run completes. When combined with :parallel_testrun_count, will be called separately in each child process. Return a Hash with :continue set to false to stop retrying tests, or :only_testing to change which tests will be run in the next try',
|
437
445
|
optional: true,
|
438
446
|
is_string: false,
|
439
447
|
default_value: nil,
|
@@ -461,6 +469,10 @@ module Fastlane
|
|
461
469
|
|
462
470
|
# UI.abort_with_message!('You could conditionally abort')
|
463
471
|
UI.message(\"\\\u1F60A everything is fine, let's continue try \#{try_attempt + 1} for batch \#{batch}\")
|
472
|
+
{
|
473
|
+
continue: true,
|
474
|
+
only_testing: ['AtomicBoyUITests/AtomicBoyUITests/testExample17']
|
475
|
+
}
|
464
476
|
end
|
465
477
|
|
466
478
|
multi_scan(
|
@@ -486,6 +498,120 @@ module Fastlane
|
|
486
498
|
output_files: 'report.json',
|
487
499
|
fail_build: false
|
488
500
|
)
|
501
|
+
",
|
502
|
+
"
|
503
|
+
UI.header('batches feature')
|
504
|
+
multi_scan(
|
505
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
506
|
+
scheme: 'AtomicBoy',
|
507
|
+
try_count: 3,
|
508
|
+
fail_build: false,
|
509
|
+
batches: [
|
510
|
+
[
|
511
|
+
'AtomicBoyUITests/AtomicBoyUITests/testExample5',
|
512
|
+
'AtomicBoyUITests/AtomicBoyUITests/testExample10',
|
513
|
+
'AtomicBoyUITests/AtomicBoyUITests/testExample15'
|
514
|
+
],
|
515
|
+
[
|
516
|
+
'AtomicBoyUITests/AtomicBoyUITests/testExample6',
|
517
|
+
'AtomicBoyUITests/AtomicBoyUITests/testExample12',
|
518
|
+
'AtomicBoyUITests/AtomicBoyUITests/testExample18'
|
519
|
+
]
|
520
|
+
]
|
521
|
+
)
|
522
|
+
"
|
523
|
+
]
|
524
|
+
end
|
525
|
+
|
526
|
+
def self.integration_tests
|
527
|
+
[
|
528
|
+
"
|
529
|
+
UI.header('Basic test')
|
530
|
+
multi_scan(
|
531
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
532
|
+
scheme: 'AtomicBoy',
|
533
|
+
fail_build: false,
|
534
|
+
try_count: 2,
|
535
|
+
disable_xcpretty: true
|
536
|
+
)
|
537
|
+
",
|
538
|
+
"
|
539
|
+
UI.header('Basic test with 1 specific test')
|
540
|
+
multi_scan(
|
541
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
542
|
+
scheme: 'AtomicBoy',
|
543
|
+
fail_build: false,
|
544
|
+
try_count: 2,
|
545
|
+
only_testing: ['AtomicBoyUITests/AtomicBoyUITests/testExample']
|
546
|
+
)
|
547
|
+
",
|
548
|
+
"
|
549
|
+
UI.header('Basic test with test target expansion')
|
550
|
+
multi_scan(
|
551
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
552
|
+
scheme: 'AtomicBoy',
|
553
|
+
fail_build: false,
|
554
|
+
try_count: 2,
|
555
|
+
only_testing: ['AtomicBoyUITests', 'AtomicBoyTests']
|
556
|
+
)
|
557
|
+
",
|
558
|
+
"
|
559
|
+
UI.header('Parallel test run')
|
560
|
+
multi_scan(
|
561
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
562
|
+
scheme: 'AtomicBoy',
|
563
|
+
fail_build: false,
|
564
|
+
try_count: 2,
|
565
|
+
parallel_testrun_count: 2
|
566
|
+
)
|
567
|
+
",
|
568
|
+
"
|
569
|
+
UI.header('Parallel test run with fewer tests than parallel test runs')
|
570
|
+
multi_scan(
|
571
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
572
|
+
scheme: 'AtomicBoy',
|
573
|
+
fail_build: false,
|
574
|
+
try_count: 2,
|
575
|
+
parallel_testrun_count: 4,
|
576
|
+
only_testing: ['AtomicBoyUITests/AtomicBoyUITests/testExample']
|
577
|
+
)
|
578
|
+
",
|
579
|
+
"
|
580
|
+
UI.header('Basic test with batch count')
|
581
|
+
multi_scan(
|
582
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
583
|
+
scheme: 'AtomicBoy',
|
584
|
+
fail_build: false,
|
585
|
+
try_count: 2,
|
586
|
+
batch_count: 2
|
587
|
+
)
|
588
|
+
",
|
589
|
+
"
|
590
|
+
UI.header('Basic test with batches')
|
591
|
+
multi_scan(
|
592
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
593
|
+
scheme: 'AtomicBoy',
|
594
|
+
fail_build: false,
|
595
|
+
try_count: 2,
|
596
|
+
batches: [
|
597
|
+
['AtomicBoyUITests/AtomicBoyUITests/testExample', 'AtomicBoyUITests/AtomicBoyUITests/testExample2'],
|
598
|
+
['AtomicBoyUITests/AtomicBoyUITests/testExample3', 'AtomicBoyUITests/AtomicBoyUITests/testExample4']
|
599
|
+
],
|
600
|
+
parallel_testrun_count: 2
|
601
|
+
)
|
602
|
+
",
|
603
|
+
"
|
604
|
+
UI.header('Basic test with xcresult')
|
605
|
+
multi_scan(
|
606
|
+
workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
|
607
|
+
scheme: 'AtomicBoy',
|
608
|
+
output_types: 'xcresult',
|
609
|
+
output_files: 'result.xcresult',
|
610
|
+
collate_reports: false,
|
611
|
+
fail_build: false,
|
612
|
+
try_count: 2,
|
613
|
+
batch_count: 2
|
614
|
+
)
|
489
615
|
"
|
490
616
|
]
|
491
617
|
end
|
@@ -16,6 +16,7 @@ module TestCenter
|
|
16
16
|
@options[:output_files],
|
17
17
|
@options[:custom_report_file_name]
|
18
18
|
)
|
19
|
+
@callback_overrides_only_testing = false
|
19
20
|
end
|
20
21
|
|
21
22
|
def before_testrun
|
@@ -189,7 +190,26 @@ module TestCenter
|
|
189
190
|
update_json_failure_details(info)
|
190
191
|
update_test_result_bundle_details(info)
|
191
192
|
|
192
|
-
@
|
193
|
+
@callback_overrides_only_testing = false
|
194
|
+
callback_result = @options[:testrun_completed_block].call(info)
|
195
|
+
if callback_result.kind_of?(Hash)
|
196
|
+
should_continue = callback_result.fetch(:continue, true)
|
197
|
+
if !should_continue
|
198
|
+
discontinue_message = 'Following testrun_completed_block\'s request to discontinue testing'
|
199
|
+
discontinue_message << " for batch ##{@options[:batch]}" unless @options[:batch].nil?
|
200
|
+
FastlaneCore::UI.verbose(discontinue_message)
|
201
|
+
@testrun_count = options[:try_count]
|
202
|
+
end
|
203
|
+
overridden_only_testing = callback_result.fetch(:only_testing, nil)
|
204
|
+
if overridden_only_testing && should_continue
|
205
|
+
override_only_testing_message = 'Following testrun_completed_block\'s request to change :only_testing to '
|
206
|
+
override_only_testing_message << overridden_only_testing.to_s
|
207
|
+
override_only_testing_message << " for batch ##{@options[:batch]}" unless @options[:batch].nil?
|
208
|
+
FastlaneCore::UI.verbose(override_only_testing_message)
|
209
|
+
@callback_overrides_only_testing = true
|
210
|
+
@options[:only_testing] = overridden_only_testing
|
211
|
+
end
|
212
|
+
end
|
193
213
|
end
|
194
214
|
|
195
215
|
def failure_details(additional_info)
|
@@ -242,6 +262,8 @@ module TestCenter
|
|
242
262
|
end
|
243
263
|
|
244
264
|
def update_only_testing
|
265
|
+
return if @callback_overrides_only_testing
|
266
|
+
|
245
267
|
report_filepath = File.join(output_directory, @reportnamer.junit_last_reportname)
|
246
268
|
config = FastlaneCore::Configuration.create(
|
247
269
|
Fastlane::Actions::TestsFromJunitAction.available_options,
|
@@ -65,8 +65,8 @@ module TestCenter
|
|
65
65
|
|
66
66
|
@test_collector = TestCollector.new(@options)
|
67
67
|
@options.reject! { |key| %i[testplan].include?(key) }
|
68
|
-
@batch_count = @test_collector.
|
69
|
-
tests = @test_collector.
|
68
|
+
@batch_count = @test_collector.batches.size
|
69
|
+
tests = @test_collector.batches.flatten
|
70
70
|
if tests.size < @options[:parallel_testrun_count].to_i
|
71
71
|
FastlaneCore::UI.important(":parallel_testrun_count greater than the number of tests (#{tests.size}). Reducing to that number.")
|
72
72
|
@options[:parallel_testrun_count] = tests.size
|
@@ -196,7 +196,7 @@ module TestCenter
|
|
196
196
|
pool = TestBatchWorkerPool.new(pool_options)
|
197
197
|
pool.setup_workers
|
198
198
|
|
199
|
-
remaining_test_batches = @test_collector.
|
199
|
+
remaining_test_batches = @test_collector.batches.clone
|
200
200
|
remaining_test_batches.each_with_index do |test_batch, current_batch_index|
|
201
201
|
worker = pool.wait_for_worker
|
202
202
|
FastlaneCore::UI.message("Starting test run #{current_batch_index + 1}")
|
@@ -209,7 +209,7 @@ module TestCenter
|
|
209
209
|
end
|
210
210
|
|
211
211
|
def scan_options_for_worker(test_batch, batch_index)
|
212
|
-
if @test_collector.
|
212
|
+
if @test_collector.batches.size > 1
|
213
213
|
# If there are more than 1 batch, then we want each batch result
|
214
214
|
# sent to a "batch index" output folder to be collated later
|
215
215
|
# into the requested output_folder.
|
@@ -3,34 +3,154 @@ module TestCenter
|
|
3
3
|
require 'fastlane_core/ui/ui.rb'
|
4
4
|
require 'fastlane/actions/scan'
|
5
5
|
require 'plist'
|
6
|
+
require 'set'
|
6
7
|
|
7
8
|
class TestCollector
|
8
9
|
attr_reader :xctestrun_path
|
9
|
-
attr_reader :
|
10
|
+
attr_reader :batches
|
11
|
+
attr_reader :testables
|
10
12
|
|
11
13
|
def initialize(options)
|
12
|
-
|
13
|
-
|
14
|
+
@invocation_based_tests = options[:invocation_based_tests]
|
15
|
+
@swift_test_prefix = options[:swift_test_prefix]
|
16
|
+
|
17
|
+
@xctestrun_path = self.class.xctestrun_filepath(options)
|
18
|
+
initialize_batches(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def initialize_batches(options)
|
24
|
+
if options[:batches]
|
25
|
+
expand_given_batches_to_full_test_identifiers(options)
|
26
|
+
else
|
27
|
+
derive_batches_from_tests(options)
|
14
28
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
29
|
+
end
|
30
|
+
|
31
|
+
def expand_given_batches_to_full_test_identifiers(options)
|
32
|
+
@batches = options[:batches]
|
33
|
+
testables = Set.new
|
34
|
+
@batches.each do |batch|
|
35
|
+
expand_test_identifiers(batch)
|
36
|
+
batch.each { |t| testables << t.split('/')[0] }
|
18
37
|
end
|
19
|
-
@
|
20
|
-
|
21
|
-
|
38
|
+
@testables = testables.to_a
|
39
|
+
end
|
40
|
+
|
41
|
+
def derive_batch_count(options)
|
42
|
+
batch_count = options.fetch(:batch_count, 1)
|
43
|
+
if batch_count == 1 && options.fetch(:parallel_testrun_count, 0) > 1
|
44
|
+
# if the batch count is 1, and the users wants parallel runs
|
45
|
+
# we *must* set the batch count to the same number of parallel
|
46
|
+
# runs or else the desired reports will not be written
|
47
|
+
batch_count = options[:parallel_testrun_count]
|
22
48
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
49
|
+
batch_count
|
50
|
+
end
|
51
|
+
|
52
|
+
def derive_only_testing(options)
|
53
|
+
only_testing = options[:only_testing] || self.class.only_testing_from_testplan(options)
|
54
|
+
if only_testing && only_testing.kind_of?(String)
|
55
|
+
only_testing = only_testing.split(',').map(&:strip)
|
28
56
|
end
|
57
|
+
only_testing
|
58
|
+
end
|
29
59
|
|
30
|
-
|
60
|
+
def testable_tests_hash_from_options(options)
|
61
|
+
testable_tests_hash = Hash.new { |h, k| h[k] = [] }
|
62
|
+
only_testing = derive_only_testing(options)
|
63
|
+
if only_testing
|
64
|
+
expand_test_identifiers(only_testing)
|
65
|
+
only_testing.each do |test_identifier|
|
66
|
+
testable = test_identifier.split('/')[0]
|
67
|
+
testable_tests_hash[testable] << test_identifier
|
68
|
+
end
|
69
|
+
else
|
70
|
+
testable_tests_hash = xctestrun_known_tests.clone
|
71
|
+
if options[:skip_testing]
|
72
|
+
expand_test_identifiers(options[:skip_testing])
|
73
|
+
testable_tests_hash.each do |testable, test_identifiers|
|
74
|
+
test_identifiers.replace(test_identifiers - options[:skip_testing])
|
75
|
+
testable_tests_hash.delete(testable) if test_identifiers.empty?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
testable_tests_hash
|
80
|
+
end
|
81
|
+
|
82
|
+
def derive_batches_from_tests(options)
|
83
|
+
@batches = []
|
84
|
+
testable_tests_hash = testable_tests_hash_from_options(options)
|
85
|
+
@testables = testable_tests_hash.keys
|
86
|
+
batch_count = derive_batch_count(options)
|
87
|
+
testable_tests_hash.each do |testable, test_identifiers|
|
88
|
+
next if test_identifiers.empty?
|
89
|
+
|
90
|
+
if batch_count > 1
|
91
|
+
slice_count = [(test_identifiers.length / batch_count.to_f).ceil, 1].max
|
92
|
+
test_identifiers.each_slice(slice_count).to_a.each do |batch|
|
93
|
+
@batches << batch
|
94
|
+
end
|
95
|
+
else
|
96
|
+
@batches << test_identifiers
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def expand_test_identifiers(test_identifiers)
|
102
|
+
all_known_tests = nil
|
103
|
+
test_identifiers.each_with_index do |test_identifier, index|
|
104
|
+
test_components = test_identifier.split('/')
|
105
|
+
is_full_test_identifier = (test_components.size == 3)
|
106
|
+
next if is_full_test_identifier
|
107
|
+
|
108
|
+
all_known_tests ||= xctestrun_known_tests.clone
|
109
|
+
|
110
|
+
testsuite = ''
|
111
|
+
testable = test_components[0]
|
112
|
+
expanded_test_identifiers = []
|
113
|
+
if test_components.size == 1
|
114
|
+
# this is a testable, also known as a test target. Let's expand it out
|
115
|
+
# to all of its tests. Note: a test target can have many testSuites, each
|
116
|
+
# with their own testCases.
|
117
|
+
if all_known_tests[testable].to_a.empty?
|
118
|
+
FastlaneCore::UI.verbose("Unable to expand #{testable} to constituent tests")
|
119
|
+
expand_test_identifiers = [testable]
|
120
|
+
else
|
121
|
+
expand_test_identifiers = all_known_tests[testable]
|
122
|
+
end
|
123
|
+
else
|
124
|
+
# this is a testable and a test suite, let's expand it out to all of
|
125
|
+
# its testCases. Note: if the user put the same test identifier in more than
|
126
|
+
# one place in this array, this could lead to multiple repititions of the same
|
127
|
+
# set of test identifiers
|
128
|
+
testsuite = test_components[1]
|
129
|
+
expanded_test_identifiers = all_known_tests[testable].select do |known_test|
|
130
|
+
known_test.split('/')[1] == testsuite
|
131
|
+
end
|
132
|
+
end
|
133
|
+
test_identifiers.delete_at(index)
|
134
|
+
test_identifiers.insert(index, *expand_test_identifiers)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def xctestrun_known_tests
|
139
|
+
unless @known_tests
|
140
|
+
config = FastlaneCore::Configuration.create(
|
141
|
+
::Fastlane::Actions::TestsFromXctestrunAction.available_options,
|
142
|
+
{
|
143
|
+
xctestrun: @xctestrun_path,
|
144
|
+
invocation_based_tests: @invocation_based_tests,
|
145
|
+
swift_test_prefix: @swift_test_prefix
|
146
|
+
}
|
147
|
+
)
|
148
|
+
@known_tests = ::Fastlane::Actions::TestsFromXctestrunAction.run(config)
|
149
|
+
end
|
150
|
+
@known_tests
|
31
151
|
end
|
32
152
|
|
33
|
-
def only_testing_from_testplan(options)
|
153
|
+
def self.only_testing_from_testplan(options)
|
34
154
|
return unless options[:testplan] && options[:scheme]
|
35
155
|
|
36
156
|
config = FastlaneCore::Configuration.create(
|
@@ -60,153 +180,26 @@ module TestCenter
|
|
60
180
|
return test_options[:only_testing]
|
61
181
|
end
|
62
182
|
|
63
|
-
def default_derived_data_path
|
183
|
+
def self.default_derived_data_path
|
64
184
|
project_derived_data_path = Scan.project.build_settings(key: "BUILT_PRODUCTS_DIR")
|
65
185
|
File.expand_path("../../..", project_derived_data_path)
|
66
186
|
end
|
67
187
|
|
68
|
-
def derived_testrun_path(derived_data_path
|
188
|
+
def self.derived_testrun_path(derived_data_path)
|
69
189
|
xctestrun_files = Dir.glob("#{derived_data_path}/Build/Products/*.xctestrun")
|
70
190
|
xctestrun_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) }.last
|
71
191
|
end
|
72
192
|
|
73
|
-
def
|
74
|
-
unless
|
75
|
-
|
76
|
-
@testables ||= only_testing_to_testables_tests.keys
|
77
|
-
else
|
78
|
-
@testables = xctestrun_known_tests.keys
|
79
|
-
end
|
80
|
-
end
|
81
|
-
@testables
|
82
|
-
end
|
83
|
-
|
84
|
-
def only_testing_to_testables_tests
|
85
|
-
tests = Hash.new { |h, k| h[k] = [] }
|
86
|
-
@only_testing.sort.each do |test_identifier|
|
87
|
-
testable = test_identifier.split('/', 2)[0]
|
88
|
-
tests[testable] << test_identifier
|
89
|
-
end
|
90
|
-
tests
|
91
|
-
end
|
92
|
-
|
93
|
-
def xctestrun_known_tests
|
94
|
-
unless @known_tests
|
95
|
-
config = FastlaneCore::Configuration.create(
|
96
|
-
::Fastlane::Actions::TestsFromXctestrunAction.available_options,
|
97
|
-
{
|
98
|
-
xctestrun: @xctestrun_path,
|
99
|
-
invocation_based_tests: @invocation_based_tests,
|
100
|
-
swift_test_prefix: @swift_test_prefix
|
101
|
-
}
|
102
|
-
)
|
103
|
-
@known_tests = ::Fastlane::Actions::TestsFromXctestrunAction.run(config)
|
104
|
-
end
|
105
|
-
@known_tests
|
106
|
-
end
|
107
|
-
|
108
|
-
def expand_short_testidentifiers_to_tests(testables_tests)
|
109
|
-
# Remember, testable_tests is of the format:
|
110
|
-
# {
|
111
|
-
# 'testable1' => [
|
112
|
-
# 'testsuite1/testcase1',
|
113
|
-
# 'testsuite1/testcase2',
|
114
|
-
# 'testsuite2/testcase1',
|
115
|
-
# 'testsuite2/testcase2',
|
116
|
-
# ...
|
117
|
-
# 'testsuiteN/testcase1', ... 'testsuiteN/testcaseM'
|
118
|
-
# ],
|
119
|
-
# ...
|
120
|
-
# 'testableO' => [
|
121
|
-
# 'testsuite1/testcase1',
|
122
|
-
# 'testsuite1/testcase2',
|
123
|
-
# 'testsuite2/testcase1',
|
124
|
-
# 'testsuite2/testcase2',
|
125
|
-
# ...
|
126
|
-
# 'testsuiteN/testcase1', ... 'testsuiteN/testcaseM'
|
127
|
-
# ]
|
128
|
-
# }
|
129
|
-
return if @invocation_based_tests
|
130
|
-
|
131
|
-
# iterate among all the test identifers for each testable
|
132
|
-
# A test identifier is seperated into components by '/'
|
133
|
-
# if a test identifier has only 2 separators, it probably is
|
134
|
-
# 'testable/testsuite' (but it could be 'testsuite/testcase' )
|
135
|
-
all_known_tests = nil
|
136
|
-
known_tests = []
|
137
|
-
testables_tests.each do |testable, tests|
|
138
|
-
tests.each_with_index do |test, index|
|
139
|
-
test_components = test.split('/')
|
140
|
-
is_full_test_identifier = (test_components.size == 3)
|
141
|
-
next if is_full_test_identifier
|
142
|
-
|
143
|
-
all_known_tests ||= xctestrun_known_tests.clone
|
144
|
-
|
145
|
-
testsuite = ''
|
146
|
-
if test_components.size == 1
|
147
|
-
if test_components[0] == testable
|
148
|
-
# The following || [] is just in case the user provided multiple
|
149
|
-
# test targets or there are no actual tests found.
|
150
|
-
testables_tests[testable][index] = all_known_tests[testable] || []
|
151
|
-
all_known_tests.delete(testable)
|
152
|
-
next
|
153
|
-
end
|
154
|
-
|
155
|
-
testsuite = test_components[0]
|
156
|
-
else
|
157
|
-
testsuite = test_components[1]
|
158
|
-
end
|
159
|
-
|
160
|
-
testables_tests[testable][index], all_known_tests[testable] = all_known_tests[testable].partition do |known_test|
|
161
|
-
known_test.split('/')[1] == testsuite
|
162
|
-
end
|
163
|
-
end
|
164
|
-
testables_tests[testable].flatten!
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def testables_tests
|
169
|
-
unless @testables_tests
|
170
|
-
if @only_testing
|
171
|
-
@testables_tests = only_testing_to_testables_tests
|
172
|
-
expand_short_testidentifiers_to_tests(@testables_tests)
|
173
|
-
else
|
174
|
-
@testables_tests = xctestrun_known_tests
|
175
|
-
if @skip_testing
|
176
|
-
skipped_testable_tests = Hash.new { |h, k| h[k] = [] }
|
177
|
-
@skip_testing.sort.each do |skipped_test_identifier|
|
178
|
-
testable = skipped_test_identifier.split('/', 2)[0]
|
179
|
-
skipped_testable_tests[testable] << skipped_test_identifier
|
180
|
-
end
|
181
|
-
@testables_tests.each_key do |testable|
|
182
|
-
@testables_tests[testable] -= skipped_testable_tests[testable]
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
193
|
+
def self.xctestrun_filepath(options)
|
194
|
+
unless options[:xctestrun] || options[:derived_data_path]
|
195
|
+
options[:derived_data_path] = default_derived_data_path
|
186
196
|
end
|
197
|
+
path = (options[:xctestrun] || derived_testrun_path(options[:derived_data_path]))
|
187
198
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
def test_batches
|
192
|
-
if @batches.nil?
|
193
|
-
@batches = []
|
194
|
-
testables.each do |testable|
|
195
|
-
testable_tests = testables_tests[testable]
|
196
|
-
next if testable_tests.empty?
|
197
|
-
|
198
|
-
if @batch_count > 1
|
199
|
-
slice_count = [(testable_tests.length / @batch_count.to_f).ceil, 1].max
|
200
|
-
testable_tests.each_slice(slice_count).to_a.each do |tests_batch|
|
201
|
-
@batches << tests_batch
|
202
|
-
end
|
203
|
-
else
|
204
|
-
@batches << testable_tests
|
205
|
-
end
|
206
|
-
end
|
199
|
+
unless path && File.exist?(path)
|
200
|
+
FastlaneCore::UI.user_error!("Error: cannot find xctestrun file '#{path}'")
|
207
201
|
end
|
208
|
-
|
209
|
-
@batches
|
202
|
+
path
|
210
203
|
end
|
211
204
|
end
|
212
205
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-test_center
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.14.
|
4
|
+
version: 3.14.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lyndsey Ferguson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|