fastlane-plugin-test_center 3.10.1 → 3.11.2

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: dc36397b53f7d85a7ab222aaef8fce6652c69d86462d81bac3f78c3d13124667
4
- data.tar.gz: 986cd2f40ac19802835a9d8f222730bc7d78e9f80ceb07e7e872b1038f2a20d5
3
+ metadata.gz: '065618ff56d900cf4b45653bf6985f9f205c200820b4db80d76787bfe8eaa6e9'
4
+ data.tar.gz: 7a2a565897e7a29d16b34318f595b83616c51e97afb5551af0d08ceb2a33b08c
5
5
  SHA512:
6
- metadata.gz: cb0e4067df2bb853becfa2cdd5b15757de3f6f68f47b46fbd2611fe3d58c4378b792ed113df209a915f9cbc710894d8351bf2a6bc4a286c1f15d07949e607320
7
- data.tar.gz: eb701752e1efab0912c82e1b5ea6b9a280645012ae1f393d9d2a047fd823fbf9b723bb84fd823ab063624236109b1bd4b3503b01d660633008f9fa3ec572f5cb
6
+ metadata.gz: 4625cca2677f47cca4d501c16426aa9acc117c0adecbecc1842bb7ef116e99ab100d7827e580639ce18dc3327a4bdbb68d852762320169cffba865448f40fc21
7
+ data.tar.gz: 0abfbc89d1fdc4260b199cd20a7bd8c1b05911510cf628b7339a6bd5ce2790b6c3f6b1d7195677b20e020c8810420c826181621f1dbb47a816ce0c0c8ee2c23a
data/README.md CHANGED
@@ -21,7 +21,7 @@ Have you ever spent too much time trying to fix fragile tests only to give up wi
21
21
 
22
22
  ## Features
23
23
 
24
- This plugin makes testing your iOS app easier by providing you actions that give you greater control over everything related to testing your app.
24
+ This plugin makes testing your iOS app easier by providing you actions that give you greater control over everything related to testing your app.
25
25
 
26
26
  `multi_scan` began when I created an action to only re-run the failed tests in order to determine if they were truly failing, or if they were failing randomly due to a fragile infrastructure. This action morphed into an entire plugin with many actions in the testing category.
27
27
 
@@ -35,6 +35,8 @@ _read the documentation on each action by clicking on the action name_
35
35
  | [`suppress_tests_from_junit`](docs/feature_details/suppress_tests_from_junit.md) | suppress tests in an Xcode Scheme using those in a Junit test report | ios, mac |
36
36
  | [`suppress_tests`](docs/feature_details/suppress_tests.md) | suppress tests in an Xcode Scheme | ios, mac |
37
37
  | [`suppressed_tests`](docs/feature_details/suppressed_tests.md) | returns a list of the suppressed tests in your Xcode Project or Scheme | ios, mac |
38
+ | [`test_options_from_testplan`](docs/feature_details/test_options_from_testplan.md) | returns the tests and test code coverage configuration for a given testplan | ios, mac |
39
+ | [`testplans_from_scheme`](docs/feature_details/testplans_from_scheme.md) | returns the testplans that an Xcode Scheme references | ios, mac |
38
40
  | [`tests_from_junit`](docs/feature_details/tests_from_junit.md) | returns the passing and failing tests in a Junit test report | ios, mac |
39
41
  | [`tests_from_xctestrun`](docs/feature_details/tests_from_xctestrun.md) | returns a list of tests for each test target in a `xctestrun` file | ios, mac |
40
42
  | [`collate_junit_reports`](docs/feature_details/collate_junit_reports.md) | combines multiple Junit test reports into one report | ios, mac |
@@ -62,7 +64,7 @@ The most popular action in the `test_center` plugin is `multi_scan`, and if you
62
64
  multi_scan(
63
65
  project: File.absolute_path('../AtomicBoy/AtomicBoy.xcodeproj'),
64
66
  scheme: 'AtomicBoy',
65
- try_count: 3, # retry _failing_ tests up to three times^1.
67
+ try_count: 3, # retry _failing_ tests up to three times^1.
66
68
  fail_build: false,
67
69
  parallel_testrun_count: 4 # run subsets of your tests on parallel simulators^2
68
70
  )
@@ -91,6 +93,11 @@ For more information about how the `fastlane` plugin system works, check out the
91
93
 
92
94
  _fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
93
95
 
96
+ ## Supporters
97
+
98
+ ![Владислав Давыдов](https://avatars1.githubusercontent.com/u/47553334?s=44&u=4691860dba898943b947180b3d28bb85851b0d7c&v=4)
99
+ [vdavydovHH](https://github.com/vdavydovHH)
100
+
94
101
  ## License
95
102
 
96
103
  MIT
@@ -14,6 +14,10 @@ module Fastlane
14
14
  class MultiScanAction < Action
15
15
  def self.run(params)
16
16
  params[:quit_simulators] = params._values[:force_quit_simulator] if params._values[:force_quit_simulator]
17
+ if params[:try_count] < 1
18
+ UI.important('multi_scan will not test any if :try_count < 0, setting to 1')
19
+ params[:try_count] = 1
20
+ end
17
21
 
18
22
  strip_leading_and_trailing_whitespace_from_output_types(params)
19
23
 
@@ -228,7 +232,7 @@ module Fastlane
228
232
  end
229
233
 
230
234
  def self.prepare_scan_options_for_build_for_testing(scan_options)
231
- build_options = scan_options.merge(build_for_testing: true).reject { |k| k == :test_without_building }
235
+ build_options = scan_options.merge(build_for_testing: true).reject { |k| %i[test_without_building, testplan].include?(k) }
232
236
  Scan.config = FastlaneCore::Configuration.create(
233
237
  Fastlane::Actions::ScanAction.available_options,
234
238
  ScanHelper.scan_options_from_multi_scan_options(build_options)
@@ -240,7 +244,11 @@ module Fastlane
240
244
  end
241
245
 
242
246
  def self.update_xctestrun_after_build(scan_options)
243
- xctestrun_files = Dir.glob("#{Scan.config[:derived_data_path]}/Build/Products/*.xctestrun")
247
+ glob_pattern = "#{Scan.config[:derived_data_path]}/Build/Products/*.xctestrun"
248
+ if scan_options[:testplan]
249
+ glob_pattern = "#{Scan.config[:derived_data_path]}/Build/Products/*_#{scan_options[:testplan]}_*.xctestrun"
250
+ end
251
+ xctestrun_files = Dir.glob(glob_pattern)
244
252
  UI.verbose("After building, found xctestrun files #{xctestrun_files} (choosing 1st)")
245
253
  scan_options[:xctestrun] = xctestrun_files.first
246
254
  end
@@ -0,0 +1,90 @@
1
+ require 'json'
2
+
3
+ module Fastlane
4
+ module Actions
5
+ class TestOptionsFromTestplanAction < Action
6
+ def self.run(params)
7
+ testplan_path = params[:testplan]
8
+
9
+ testplan = JSON.load(File.open(testplan_path))
10
+ only_testing = []
11
+ UI.verbose("Examining testplan JSON: #{testplan}")
12
+ testplan['testTargets'].each do |test_target|
13
+ testable = test_target.dig('target', 'name')
14
+ if test_target.key?('selectedTests')
15
+ UI.verbose(" Found selectedTests")
16
+ test_identifiers = test_target['selectedTests'].each do |selected_test|
17
+ UI.verbose(" Found test: '#{selected_test}'")
18
+ only_testing << "#{testable}/#{selected_test.sub('\/', '/')}"
19
+ end
20
+ else
21
+ UI.verbose(" No selected tests, using testable '#{testable}'")
22
+ only_testing << testable
23
+ end
24
+ end
25
+ {
26
+ code_coverage: testplan.dig('defaultOptions', 'codeCoverage'),
27
+ only_testing: only_testing
28
+ }
29
+ end
30
+
31
+ #####################################################
32
+ # @!group Documentation
33
+ #####################################################
34
+
35
+ def self.description
36
+ "☑️ Gets test info from a given test plan"
37
+ end
38
+
39
+ def self.details
40
+ "Gets tests info consisting of tests to run and whether or not code coverage is enabled"
41
+ end
42
+
43
+ def self.available_options
44
+ [
45
+ FastlaneCore::ConfigItem.new(
46
+ key: :testplan,
47
+ optional: true,
48
+ env_name: "FL_TEST_OPTIONS_FROM_TESTPLAN_TESTPLAN",
49
+ description: "The Xcode testplan to read the test info from",
50
+ verify_block: proc do |test_plan|
51
+ UI.user_error!("Error: Xcode Test Plan '#{test_plan}' is not valid!") if test_plan and test_plan.empty?
52
+ UI.user_error!("Error: Test Plan does not exist at path '#{test_plan}'") unless File.exist?(test_plan)
53
+ end
54
+ )
55
+ ]
56
+ end
57
+
58
+ def self.return_value
59
+ "Returns a Hash with keys :code_coverage and :only_testing for the given testplan"
60
+ end
61
+
62
+ def self.example_code
63
+ [
64
+ "
65
+ UI.important(
66
+ 'example: ' \\
67
+ 'get the tests and the test coverage configuration from a given testplan'
68
+ )
69
+ test_options = test_options_from_testplan(
70
+ testplan: 'AtomicBoy/AtomicBoy_2.xctestplan'
71
+ )
72
+ UI.message(\"The AtomicBoy_2 testplan has the following tests: \#{test_options[:only_testing]}\")
73
+ "
74
+ ]
75
+ end
76
+
77
+ def self.authors
78
+ ["lyndsey-ferguson/lyndseydf"]
79
+ end
80
+
81
+ def self.category
82
+ :testing
83
+ end
84
+
85
+ def self.is_supported?(platform)
86
+ %i[ios mac].include?(platform)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,120 @@
1
+ module Fastlane
2
+ module Actions
3
+ class TestplansFromSchemeAction < Action
4
+ def self.run(params)
5
+ scheme = params[:scheme]
6
+ scheme_filepaths = schemes_from_project(params[:xcodeproj], scheme) || schemes_from_workspace(params[:workspace], scheme)
7
+ if scheme_filepaths.length.zero?
8
+ UI.user_error!("Error: cannot find any schemes in the Xcode project") if params[:xcodeproj]
9
+ UI.user_error!("Error: cannot find any schemes in the Xcode workspace") if params[:workspace]
10
+ end
11
+ testplan_paths = []
12
+ scheme_filepaths.each do |scheme_filepath|
13
+ UI.verbose("Looking in Scheme '#{scheme_filepath}' for any testplans")
14
+ xcscheme = Xcodeproj::XCScheme.new(scheme_filepath)
15
+ next if xcscheme.test_action.nil?
16
+ next if xcscheme.test_action.testables.to_a.empty?
17
+ next if xcscheme.test_action.testables[0].buildable_references.to_a.empty?
18
+ next if xcscheme.test_action.test_plans.to_a.empty?
19
+
20
+ xcodeproj = xcscheme.test_action.testables[0].buildable_references[0].target_referenced_container.sub('container:', '')
21
+ container_dir = scheme_filepath.sub(/#{xcodeproj}.*/, '')
22
+ xcscheme.test_action.test_plans.each do |testplan|
23
+ testplan_path = File.absolute_path(File.join(container_dir, testplan.target_referenced_container.sub('container:', '')))
24
+ UI.verbose(" found testplan '#{testplan_path}'")
25
+ testplan_paths << testplan_path
26
+ end
27
+ end
28
+ testplan_paths
29
+ end
30
+
31
+ def self.schemes_from_project(project_path, scheme)
32
+ return nil unless project_path
33
+
34
+ Dir.glob("#{project_path}/{xcshareddata,xcuserdata}/**/xcschemes/#{scheme || '*'}.xcscheme")
35
+ end
36
+
37
+ def self.schemes_from_workspace(workspace_path, scheme)
38
+ return nil unless workspace_path
39
+
40
+ xcworkspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
41
+ scheme_filepaths = []
42
+ xcworkspace.file_references.each do |file_reference|
43
+ next if file_reference.path.include?('Pods/Pods.xcodeproj')
44
+
45
+ project_path = file_reference.absolute_path(File.dirname(workspace_path))
46
+ scheme_filepaths.concat(schemes_from_project(project_path, scheme))
47
+ end
48
+ scheme_filepaths
49
+ end
50
+
51
+ def self.description
52
+ "☑️Gets all the testplans that a Scheme references"
53
+ end
54
+
55
+ def self.authors
56
+ ["lyndsey-ferguson/lyndseydf"]
57
+ end
58
+
59
+ def self.available_options
60
+ [
61
+ FastlaneCore::ConfigItem.new(
62
+ key: :xcodeproj,
63
+ env_name: "FL_TESTPLANS_FROM_SCHEME_XCODE_PROJECT",
64
+ optional: true,
65
+ description: "The file path to the Xcode project file that references the Scheme",
66
+ verify_block: proc do |path|
67
+ path = File.expand_path(path.to_s)
68
+ UI.user_error!("Error: Xcode project file path not given!") unless path and !path.empty?
69
+ UI.user_error!("Error: Xcode project '#{path}' not found!") unless Dir.exist?(path)
70
+ end
71
+ ),
72
+ FastlaneCore::ConfigItem.new(
73
+ key: :workspace,
74
+ env_name: "FL_TESTPLANS_FROM_SCHEME_XCODE_WORKSPACE",
75
+ optional: true,
76
+ description: "The file path to the Xcode workspace file that references the Scheme",
77
+ verify_block: proc do |value|
78
+ v = File.expand_path(value.to_s)
79
+ UI.user_error!("Error: Workspace file not found at path '#{v}'") unless Dir.exist?(v)
80
+ UI.user_error!("Error: Workspace file is not a workspace, must end with .xcworkspace") unless v.include?(".xcworkspace")
81
+ end
82
+ ),
83
+ FastlaneCore::ConfigItem.new(
84
+ key: :scheme,
85
+ optional: true,
86
+ env_name: "FL_TESTPLANS_FROM_SCHEME_XCODE_SCHEME",
87
+ description: "The Xcode scheme referencing the testplan",
88
+ verify_block: proc do |scheme_name|
89
+ UI.user_error!("Error: Xcode Scheme '#{scheme_name}' is not valid!") if scheme_name and scheme_name.empty?
90
+ end
91
+ )
92
+ ]
93
+ end
94
+
95
+ def self.example_code
96
+ [
97
+ "
98
+ UI.important(
99
+ 'example: ' \\
100
+ 'get all the testplans that an Xcode Scheme references'
101
+ )
102
+ testplans = testplans_from_scheme(
103
+ xcodeproj: 'AtomicBoy/AtomicBoy.xcodeproj',
104
+ scheme: 'AtomicBoy'
105
+ )
106
+ UI.message(\"The AtomicBoy uses the following testplans: \#{testplans}\")
107
+ "
108
+ ]
109
+ end
110
+
111
+ def self.category
112
+ :testing
113
+ end
114
+
115
+ def self.is_supported?(platform)
116
+ %i[ios mac].include?(platform)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,3 +1,5 @@
1
+ require_relative 'reportname_helper'
2
+ require_relative 'test_collector'
1
3
  require_relative 'multi_scan_manager/device_manager'
2
4
  require_relative 'multi_scan_manager/report_collator'
3
5
  require_relative 'multi_scan_manager/retrying_scan_helper'
@@ -17,16 +17,18 @@ module TestCenter
17
17
  end
18
18
  # :nocov:
19
19
 
20
- def prepare_scan_config_for_destination
20
+ def prepare_scan_config
21
21
  # this allows multi_scan's `destination` option to be picked up by `scan`
22
22
  scan_config._values.delete(:device)
23
23
  ENV.delete('SCAN_DEVICE')
24
24
  scan_config._values.delete(:devices)
25
25
  ENV.delete('SCAN_DEVICES')
26
+ # this prevents double -resultBundlePath args to xcodebuild
26
27
  if ReportNameHelper.includes_xcresult?(@options[:output_types])
27
28
  scan_config._values.delete(:result_bundle)
28
29
  ENV.delete('SCAN_RESULT_BUNDLE')
29
30
  end
31
+ scan_config._values.delete(:skip_testing)
30
32
  scan_cache.clear
31
33
  end
32
34
 
@@ -35,8 +37,9 @@ module TestCenter
35
37
  scan_options = @options.select { |k,v| valid_scan_keys.include?(k) }
36
38
  .merge(@retrying_scan_helper.scan_options)
37
39
 
38
- prepare_scan_config_for_destination
40
+ prepare_scan_config
39
41
  scan_options[:build_for_testing] = false
42
+ scan_options.delete(:skip_testing)
40
43
  FastlaneCore::UI.verbose("retrying_scan #update_scan_options")
41
44
  scan_options.each do |k,v|
42
45
  next if v.nil?
@@ -45,7 +45,7 @@ module TestCenter
45
45
 
46
46
  derived_data_path = File.expand_path(@options[:derived_data_path] || Scan.config[:derived_data_path])
47
47
  xcresults = Dir.glob("#{derived_data_path}/Logs/Test/*.xcresult")
48
- if FastlaneCore::Helper.xcode_at_least?('11.0.0')
48
+ if FastlaneCore::Helper.xcode_at_least?('11')
49
49
  xcresults += Dir.glob("#{output_directory}/*.xcresult")
50
50
  end
51
51
  FastlaneCore::UI.verbose("Deleting xcresults:")
@@ -93,6 +93,10 @@ module TestCenter
93
93
  FastlaneCore::UI.important(":xcargs, #{xcargs}, contained 'build-for-testing', removing it")
94
94
  xcargs.slice!('build-for-testing')
95
95
  end
96
+ if xcargs.include?('-quiet')
97
+ FastlaneCore::UI.important('Disabling -quiet as failing tests cannot be found with it enabled.')
98
+ xcargs.gsub!('-quiet', '')
99
+ end
96
100
  xcargs.gsub!(/-parallel-testing-enabled(=|\s+)(YES|NO)/, '')
97
101
  retrying_scan_options = @reportnamer.scan_options.merge(
98
102
  {
@@ -245,7 +249,7 @@ module TestCenter
245
249
  junit: File.absolute_path(report_filepath)
246
250
  }
247
251
  )
248
- @options[:only_testing] = @options[:only_testing] - Fastlane::Actions::TestsFromJunitAction.run(config).fetch(:passing, Hash.new).map(&:shellsafe_testidentifier)
252
+ @options[:only_testing] = (@options[:only_testing] || []) - Fastlane::Actions::TestsFromJunitAction.run(config).fetch(:passing, Hash.new).map(&:shellsafe_testidentifier)
249
253
  if @options[:invocation_based_tests]
250
254
  @options[:only_testing] = @options[:only_testing].map(&:strip_testcase).uniq
251
255
  end
@@ -288,6 +292,27 @@ module TestCenter
288
292
  end
289
293
 
290
294
  def retrieve_test_operation_failure(test_session_last_messages)
295
+ if FastlaneCore::Helper.xcode_at_least?('11')
296
+ retrieve_test_operation_failure_post_xcode11(test_session_last_messages)
297
+ else
298
+ retrieve_test_operation_failure_pre_xcode11(test_session_last_messages)
299
+ end
300
+ end
301
+
302
+ def retrieve_test_operation_failure_post_xcode11(test_session_last_messages)
303
+ if /Connection peer refused channel request/ =~ test_session_last_messages
304
+ test_operation_failure = 'Lost connection to testmanagerd'
305
+ elsif /Please unlock your device and reattach/ =~ test_session_last_messages
306
+ test_operation_failure = 'Test device locked'
307
+ elsif /Test runner exited before starting test execution/ =~ test_session_last_messages
308
+ test_operation_failure = 'Test runner exited before starting test execution'
309
+ else
310
+ test_operation_failure = 'Unknown test operation failure'
311
+ end
312
+ test_operation_failure
313
+ end
314
+
315
+ def retrieve_test_operation_failure_pre_xcode11(test_session_last_messages)
291
316
  test_operation_failure_match = /Test operation failure: (?<test_operation_failure>.*)$/ =~ test_session_last_messages
292
317
  if test_operation_failure_match.nil?
293
318
  test_operation_failure = 'Unknown test operation failure'
@@ -323,15 +348,17 @@ module TestCenter
323
348
  def move_test_result_bundle_for_next_run
324
349
  return unless @options[:result_bundle]
325
350
 
326
- glob_pattern = "#{output_directory}/*.test_result"
351
+ result_extension = FastlaneCore::Helper.xcode_at_least?('11') ? '.xcresult' : '.test_result'
352
+
353
+ glob_pattern = "#{output_directory}/*#{result_extension}"
327
354
  preexisting_test_result_bundles = Dir.glob(glob_pattern)
328
355
  unnumbered_test_result_bundles = preexisting_test_result_bundles.reject do |test_result|
329
- test_result =~ /.*-\d+\.test_result/
356
+ test_result =~ /.*-\d+\#{result_extension}/
330
357
  end
331
358
  src_test_bundle = unnumbered_test_result_bundles.first
332
359
  dst_test_bundle_parent_dir = File.dirname(src_test_bundle)
333
- dst_test_bundle_basename = File.basename(src_test_bundle, '.test_result')
334
- dst_test_bundle = "#{dst_test_bundle_parent_dir}/#{dst_test_bundle_basename}-#{@testrun_count}.test_result"
360
+ dst_test_bundle_basename = File.basename(src_test_bundle, result_extension)
361
+ dst_test_bundle = "#{dst_test_bundle_parent_dir}/#{dst_test_bundle_basename}-#{@testrun_count}#{result_extension}"
335
362
  FastlaneCore::UI.verbose("Moving test_result '#{src_test_bundle}' to '#{dst_test_bundle}'")
336
363
  File.rename(src_test_bundle, dst_test_bundle)
337
364
  end
@@ -1,4 +1,3 @@
1
-
2
1
  module TestCenter
3
2
  module Helper
4
3
  module MultiScanManager
@@ -7,7 +6,7 @@ module TestCenter
7
6
  require 'json'
8
7
  require 'shellwords'
9
8
  require 'snapshot/reset_simulators'
10
-
9
+
11
10
  class Runner
12
11
  attr_reader :retry_total_count
13
12
 
@@ -40,7 +39,8 @@ module TestCenter
40
39
  return if @options[:invocation_based_tests] && @options[:only_testing].nil?
41
40
  return if @test_collector
42
41
 
43
- @test_collector = TestCenter::Helper::TestCollector.new(@options)
42
+ @test_collector = TestCollector.new(@options)
43
+ @options.reject! { |key| %i[testplan].include?(key) }
44
44
  @batch_count = @test_collector.test_batches.size
45
45
  end
46
46
 
@@ -66,12 +66,12 @@ module TestCenter
66
66
  end
67
67
 
68
68
  unless tests_passed || @options[:try_count] < 1
69
- setup_testcollector
69
+ setup_testcollector
70
70
  tests_passed = run_test_batches
71
71
  end
72
72
  tests_passed
73
73
  end
74
-
74
+
75
75
  def should_run_tests_through_single_try?
76
76
  should_run_for_invocation_tests = @options[:invocation_based_tests] && @options[:only_testing].nil?
77
77
  should_run_for_skip_build = @options[:skip_build]
@@ -114,16 +114,16 @@ module TestCenter
114
114
  end
115
115
  @options[:output_directory] = output_directory
116
116
  @options[:destination] = Scan.config[:destination]
117
-
117
+
118
118
  # We do not want Scan.config to _not_ have :device :devices, we want to
119
119
  # use :destination. We remove :force_quit_simulator as we do not want
120
120
  # Scan to handle it as multi_scan takes care of it in its own way
121
121
  options = @options.reject { |key| %i[device devices force_quit_simulator].include?(key) }
122
122
  options[:try_count] = 1
123
-
123
+
124
124
  tests_passed = RetryingScan.run(options)
125
125
  @options[:try_count] -= 1
126
-
126
+
127
127
  reportnamer = ReportNameHelper.new(
128
128
  @options[:output_types],
129
129
  @options[:output_files],
@@ -138,12 +138,12 @@ module TestCenter
138
138
  )
139
139
  @options[:only_testing] = retrieve_failed_single_try_tests
140
140
  @options[:only_testing] = @options[:only_testing].map(&:strip_testcase).uniq
141
-
141
+
142
142
  symlink_result_bundle_to_xcresult(output_directory, reportnamer)
143
143
 
144
144
  tests_passed
145
145
  end
146
-
146
+
147
147
  def retrieve_failed_single_try_tests
148
148
  reportnamer = ReportNameHelper.new(
149
149
  @options[:output_types],
@@ -168,10 +168,10 @@ module TestCenter
168
168
 
169
169
  pool = TestBatchWorkerPool.new(pool_options)
170
170
  pool.setup_workers
171
-
171
+
172
172
  remaining_test_batches = @test_collector.test_batches.clone
173
173
  remaining_test_batches.each_with_index do |test_batch, current_batch_index|
174
- worker = pool.wait_for_worker
174
+ worker = pool.wait_for_worker
175
175
  FastlaneCore::UI.message("Starting test run #{current_batch_index + 1}")
176
176
  worker.run(scan_options_for_worker(test_batch, current_batch_index))
177
177
  end
@@ -189,7 +189,7 @@ module TestCenter
189
189
  batch: batch_index + 1
190
190
  }
191
191
  end
192
-
192
+
193
193
  def collate_batched_reports
194
194
  return unless @batch_count > 1
195
195
  return unless @options[:collate_reports]
@@ -207,10 +207,44 @@ module TestCenter
207
207
  File.absolute_path(output_directory),
208
208
  @test_collector.testables.first
209
209
  )
210
+ merge_single_testable_xcresult_with_final_xcresult(report_files_dir, File.absolute_path(output_directory))
210
211
  FileUtils.cp_r("#{report_files_dir}/.", File.absolute_path(output_directory))
211
212
  FileUtils.rm_rf(report_files_dir)
212
213
  end
213
214
 
215
+ def merge_single_testable_xcresult_with_final_xcresult(testable_output_dir, final_output_dir)
216
+ reportnamer = ReportNameHelper.new(
217
+ @options[:output_types],
218
+ @options[:output_files],
219
+ @options[:custom_report_file_name]
220
+ )
221
+ return unless reportnamer.includes_xcresult?
222
+
223
+ xcresult_bundlename = reportnamer.xcresult_bundlename
224
+ src_xcresult_bundlepath = File.join(testable_output_dir, xcresult_bundlename)
225
+ dst_xcresult_bundlepath = File.join(final_output_dir, xcresult_bundlename)
226
+
227
+ # We do not need to merge if one of these do not exist
228
+ return unless File.exist?(src_xcresult_bundlepath) || File.exist?(dst_xcresult_bundlepath)
229
+
230
+ config = FastlaneCore::Configuration.create(
231
+ Fastlane::Actions::CollateXcresultsAction.available_options,
232
+ {
233
+ xcresults: [src_xcresult_bundlepath, dst_xcresult_bundlepath],
234
+ collated_xcresult: dst_xcresult_bundlepath
235
+ }
236
+ )
237
+ FastlaneCore::UI.verbose("Merging xcresult '#{src_xcresult_bundlepath}' to '#{dst_xcresult_bundlepath}'")
238
+ Fastlane::Actions::CollateXcresultsAction.run(config)
239
+ FileUtils.rm_rf(src_xcresult_bundlepath)
240
+ if @result_bundle_desired
241
+ xcresult_bundlename = reportnamer.xcresult_bundlename
242
+ test_result_bundlename = File.basename(xcresult_bundlename, '.*') + '.test_result'
243
+ test_result_bundlename_path = File.join(testable_output_dir, test_result_bundlename)
244
+ FileUtils.rm_rf(test_result_bundlename_path)
245
+ end
246
+ end
247
+
214
248
  def symlink_result_bundle_to_xcresult(output_dir, reportname_helper)
215
249
  return unless @result_bundle_desired && reportname_helper.includes_xcresult?
216
250
 
@@ -15,7 +15,7 @@ module TestCenter
15
15
  unless @xctestrun_path && File.exist?(@xctestrun_path)
16
16
  FastlaneCore::UI.user_error!("Error: cannot find xctestrun file '#{@xctestrun_path}'")
17
17
  end
18
- @only_testing = options[:only_testing]
18
+ @only_testing = options[:only_testing] || only_testing_from_testplan(options)
19
19
  if @only_testing.kind_of?(String)
20
20
  @only_testing = @only_testing.split(',')
21
21
  end
@@ -27,6 +27,36 @@ module TestCenter
27
27
  end
28
28
  end
29
29
 
30
+ def only_testing_from_testplan(options)
31
+ return unless options[:testplan] && options[:scheme]
32
+
33
+ config = FastlaneCore::Configuration.create(
34
+ Fastlane::Actions::TestplansFromSchemeAction.available_options,
35
+ {
36
+ workspace: options[:workspace],
37
+ xcodeproj: options[:project],
38
+ scheme: options[:scheme]
39
+ }
40
+ )
41
+ testplans = Fastlane::Actions::TestplansFromSchemeAction.run(config)
42
+ FastlaneCore::UI.verbose("TestCollector found testplans: #{testplans}")
43
+ testplan = testplans.find do |testplan_path|
44
+ %r{(.*/?#{ options[:testplan] })\.xctestplan}.match?(testplan_path)
45
+ end
46
+ FastlaneCore::UI.verbose(" using :testplan option, #{options[:testplan]}, using found one: #{testplan}")
47
+
48
+ return if testplan.nil?
49
+
50
+ config = FastlaneCore::Configuration.create(
51
+ Fastlane::Actions::TestOptionsFromTestplanAction.available_options,
52
+ {
53
+ testplan: testplan
54
+ }
55
+ )
56
+ test_options = Fastlane::Actions::TestOptionsFromTestplanAction.run(config)
57
+ return test_options[:only_testing]
58
+ end
59
+
30
60
  def default_derived_data_path(options)
31
61
  project_derived_data_path = Scan.project.build_settings(key: "BUILT_PRODUCTS_DIR")
32
62
  File.expand_path("../../..", project_derived_data_path)
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module TestCenter
3
- VERSION = "3.10.1"
3
+ VERSION = "3.11.2"
4
4
  end
5
5
  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.10.1
4
+ version: 3.11.2
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-04-01 00:00:00.000000000 Z
11
+ date: 2020-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -267,6 +267,8 @@ files:
267
267
  - lib/fastlane/plugin/test_center/actions/suppress_tests.rb
268
268
  - lib/fastlane/plugin/test_center/actions/suppress_tests_from_junit.rb
269
269
  - lib/fastlane/plugin/test_center/actions/suppressed_tests.rb
270
+ - lib/fastlane/plugin/test_center/actions/test_options_from_testplan.rb
271
+ - lib/fastlane/plugin/test_center/actions/testplans_from_scheme.rb
270
272
  - lib/fastlane/plugin/test_center/actions/tests_from_junit.rb
271
273
  - lib/fastlane/plugin/test_center/actions/tests_from_xctestrun.rb
272
274
  - lib/fastlane/plugin/test_center/helper/html_test_report.rb