fastlane-plugin-test_center 3.7.0 → 3.8.0.parallelizing.beta.1

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +71 -6
  3. data/lib/fastlane/plugin/test_center/actions/collate_html_reports.rb +2 -0
  4. data/lib/fastlane/plugin/test_center/actions/collate_json_reports.rb +2 -0
  5. data/lib/fastlane/plugin/test_center/actions/collate_junit_reports.rb +2 -1
  6. data/lib/fastlane/plugin/test_center/actions/collate_test_result_bundles.rb +2 -0
  7. data/lib/fastlane/plugin/test_center/actions/multi_scan.rb +127 -32
  8. data/lib/fastlane/plugin/test_center/actions/quit_core_simulator_service.rb +40 -0
  9. data/lib/fastlane/plugin/test_center/actions/suppress_tests.rb +2 -0
  10. data/lib/fastlane/plugin/test_center/actions/suppress_tests_from_junit.rb +3 -1
  11. data/lib/fastlane/plugin/test_center/actions/suppressed_tests.rb +2 -0
  12. data/lib/fastlane/plugin/test_center/actions/tests_from_junit.rb +2 -0
  13. data/lib/fastlane/plugin/test_center/actions/tests_from_xctestrun.rb +2 -0
  14. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/device_manager.rb +30 -0
  15. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/parallel_test_batch_worker.rb +73 -0
  16. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/report_collator.rb +129 -0
  17. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/retrying_scan.rb +77 -0
  18. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/retrying_scan_helper.rb +272 -0
  19. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/runner.rb +109 -0
  20. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/simulator_helper.rb +49 -0
  21. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/test_batch_worker.rb +24 -0
  22. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/test_batch_worker_pool.rb +133 -0
  23. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager.rb +3 -0
  24. data/lib/fastlane/plugin/test_center/helper/reportname_helper.rb +15 -6
  25. data/lib/fastlane/plugin/test_center/helper/test_collector.rb +55 -14
  26. data/lib/fastlane/plugin/test_center/helper/xctestrun_info.rb +42 -0
  27. data/lib/fastlane/plugin/test_center/version.rb +1 -1
  28. data/lib/fastlane/plugin/test_center.rb +1 -1
  29. metadata +22 -11
  30. data/lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb +0 -315
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd7fbaf52ee79115ad9ea8f260bdd35e90868c14
4
- data.tar.gz: 03ab87b0d261fde47d37edfa7d997e33a6f3faa7
3
+ metadata.gz: e0d83a81d13511c8798b43c1b458e6619d94c786
4
+ data.tar.gz: '048f7bc9d0465b5fba70b682271b6d5952e88963'
5
5
  SHA512:
6
- metadata.gz: 9cd9189973cddeab19e82f2bee16577eca64b0eea355d0229cf17fa555b6231f536d558ac44a086ddbfb22ae6877cf857f45db20a9fedbe80a392cc0594db7b6
7
- data.tar.gz: 3d3747b5497960d65c97b44b20291eea6133c68752449f29d442b6f2e144b4dfc853a7b44eb09523f383749b11d143abbdab028ff73ee314e2bef1e056725ef7
6
+ metadata.gz: 2e7c925081b38580cb7efe949c689963f44368db7f92a73ad5c1eec497aed23c17ec3416afd5e57578277359899989c2cd700a26a79f6c1a14ae455ab4ac2f31
7
+ data.tar.gz: 4434d5b5502c17a6fe3b3c70fcba0a39a03212479c331b10a0deb6780a243ec1b5fa9c147d5b8d70a7f0bb55c17d1737a34e5d1fcec28d7c89673169b7d9ee69
data/README.md CHANGED
@@ -184,16 +184,41 @@ multi_scan(
184
184
 
185
185
  ```ruby
186
186
 
187
+ UI.important(
188
+ 'example: ' \
189
+ 'multi_scan also works with invocation based tests.'
190
+ )
191
+ Dir.chdir('../AtomicBoy') do
192
+ bundle_install
193
+ cocoapods(podfile: File.absolute_path('Podfile'))
194
+ multi_scan(
195
+ workspace: File.absolute_path('AtomicBoy.xcworkspace'),
196
+ scheme: 'KiwiBoy',
197
+ try_count: 3,
198
+ clean: true,
199
+ invocation_based_tests: true,
200
+ fail_build: false
201
+ )
202
+ end
203
+
204
+ ```
205
+
206
+ ```ruby
207
+
187
208
  UI.important(
188
209
  'example: ' \
189
210
  'use the :workspace parameter instead of the :project parameter to find, ' \
190
211
  'build, and test the iOS app.'
191
212
  )
192
- multi_scan(
193
- workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
194
- scheme: 'AtomicBoy',
195
- try_count: 3
196
- )
213
+ begin
214
+ multi_scan(
215
+ workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
216
+ scheme: 'AtomicBoy',
217
+ try_count: 3
218
+ )
219
+ rescue # anything
220
+ UI.error('Found real failing tests!')
221
+ end
197
222
 
198
223
  ```
199
224
 
@@ -226,7 +251,7 @@ multi_scan(
226
251
  project: File.absolute_path('../AtomicBoy/AtomicBoy.xcodeproj'),
227
252
  scheme: 'Professor',
228
253
  try_count: 3,
229
- custom_report_file_name: 'atomic_report.xml',
254
+ output_files: 'atomic_report.xml',
230
255
  output_types: 'junit',
231
256
  fail_build: false
232
257
  )
@@ -244,6 +269,7 @@ multi_scan(
244
269
  workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
245
270
  scheme: 'AtomicBoy',
246
271
  try_count: 3,
272
+ code_coverage: true,
247
273
  only_testing: ['AtomicBoyTests'],
248
274
  fail_build: false
249
275
  )
@@ -265,6 +291,45 @@ multi_scan(
265
291
  fail_build: false
266
292
  )
267
293
 
294
+ ```
295
+
296
+ ```ruby
297
+
298
+ UI.important(
299
+ 'example: ' \
300
+ 'multi_scan parallelizes its test runs.'
301
+ )
302
+ multi_scan(
303
+ workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
304
+ scheme: 'AtomicBoy',
305
+ try_count: 3,
306
+ parallel_testrun_count: 4,
307
+ fail_build: false
308
+ )
309
+
310
+ ```
311
+
312
+ ```ruby
313
+
314
+ UI.important(
315
+ 'example: ' \
316
+ 'use the :xctestrun parameter instead of the :project parameter to find, ' \
317
+ 'build, and test the iOS app.'
318
+ )
319
+ Dir.mktmpdir do |derived_data_path|
320
+ project_path = File.absolute_path('../AtomicBoy/AtomicBoy.xcodeproj')
321
+ command = "bundle exec fastlane scan --build_for_testing true --project '#{project_path}' --derived_data_path #{derived_data_path} --scheme AtomicBoy"
322
+ `#{command}`
323
+ xctestrun_file = Dir.glob("#{derived_data_path}/Build/Products/AtomicBoy*.xctestrun").first
324
+ multi_scan(
325
+ scheme: 'AtomicBoy',
326
+ try_count: 3,
327
+ fail_build: false,
328
+ xctestrun: xctestrun_file,
329
+ test_without_building: true
330
+ )
331
+ end
332
+
268
333
  ```
269
334
  <!-- multi_scan examples: end -->
270
335
  </details>
@@ -159,6 +159,7 @@ module Fastlane
159
159
  # @!group Documentation
160
160
  #####################################################
161
161
 
162
+ # :nocov:
162
163
  def self.description
163
164
  "Combines and combines tests from multiple html report files"
164
165
  end
@@ -227,6 +228,7 @@ module Fastlane
227
228
  def self.category
228
229
  :testing
229
230
  end
231
+ # :nocov:
230
232
  end
231
233
  end
232
234
  end
@@ -98,6 +98,7 @@ module Fastlane
98
98
  # @!group Documentation
99
99
  #####################################################
100
100
 
101
+ # :nocov:
101
102
  def self.description
102
103
  "Combines and combines tests from multiple json report files"
103
104
  end
@@ -167,6 +168,7 @@ module Fastlane
167
168
  def self.category
168
169
  :testing
169
170
  end
171
+ # :nocov:
170
172
  end
171
173
  end
172
174
  end
@@ -147,7 +147,7 @@ module Fastlane
147
147
  #####################################################
148
148
  # @!group Documentation
149
149
  #####################################################
150
-
150
+ # :nocov:
151
151
  def self.description
152
152
  "Combines and combines tests from multiple junit report files"
153
153
  end
@@ -217,6 +217,7 @@ module Fastlane
217
217
  def self.is_supported?(platform)
218
218
  %i[ios mac].include?(platform)
219
219
  end
220
+ # :nocov:
220
221
  end
221
222
  end
222
223
  end
@@ -111,6 +111,7 @@ module Fastlane
111
111
  # @!group Documentation
112
112
  #####################################################
113
113
 
114
+ # :nocov:
114
115
  def self.description
115
116
  "Combines and combines tests from multiple test_result bundles"
116
117
  end
@@ -179,6 +180,7 @@ module Fastlane
179
180
  def self.is_supported?(platform)
180
181
  %i[ios mac].include?(platform)
181
182
  end
183
+ # :nocov:
182
184
  end
183
185
  end
184
186
  end
@@ -5,29 +5,43 @@ module Fastlane
5
5
  require 'shellwords'
6
6
  require 'xctest_list'
7
7
  require 'plist'
8
+ require_relative '../helper/multi_scan_manager/runner'
8
9
 
9
10
  class MultiScanAction < Action
10
11
  def self.run(params)
12
+ # :nocov:
11
13
  unless Helper.test?
14
+ scan_keys = Fastlane::Actions::ScanAction.available_options.map(&:key)
12
15
  FastlaneCore::PrintTable.print_values(
13
- config: params._values.select { |k, _| %i[try_count batch_count invocation_based_tests fail_build quit_simulators].include?(k) },
16
+ config: params._values.reject { |k, _| scan_keys.include?(k) },
14
17
  title: "Summary for multi_scan (test_center v#{Fastlane::TestCenter::VERSION})"
15
18
  )
16
19
  end
17
- unless params[:test_without_building] || params[:skip_build]
18
- build_for_testing(
19
- params._values
20
- )
20
+ # :nocov:
21
+ force_quit_simulator_processes if params[:force_quit_simulator]
22
+
23
+ prepare_for_testing(params.values)
24
+
25
+ platform = :mac
26
+ platform = :ios if Scan.config[:destination].any? { |d| d.include?('platform=iOS Simulator') }
27
+
28
+ runner_options = params.values.merge(platform: platform)
29
+ runner = ::TestCenter::Helper::MultiScanManager::Runner.new(runner_options)
30
+ tests_passed = runner.run
31
+ if params[:fail_build] && !tests_passed
32
+ raise UI.test_failure!('Tests have failed')
21
33
  end
22
- smart_scanner = ::TestCenter::Helper::CorrectingScanHelper.new(params.values)
23
- tests_passed = smart_scanner.scan
24
- summary = run_summary(params, tests_passed, smart_scanner.retry_total_count)
34
+
35
+ summary = run_summary(params, tests_passed, runner.retry_total_count)
36
+ # :nocov:
25
37
  unless Helper.test?
26
38
  FastlaneCore::PrintTable.print_values(
27
39
  config: summary,
28
40
  title: "multi_scan results"
29
41
  )
30
42
  end
43
+ # :nocov:
44
+
31
45
  if params[:fail_build] && !tests_passed
32
46
  raise UI.test_failure!('Tests have failed')
33
47
  end
@@ -80,33 +94,69 @@ module Fastlane
80
94
  }
81
95
  end
82
96
 
83
- def self.build_for_testing(scan_options)
84
- options_to_remove = %i[
85
- try_count
86
- batch_count
87
- quit_simulators
88
- testrun_completed_block
89
- test_without_building
90
- invocation_based_tests
91
- output_types
92
- output_files
93
- ]
94
- config = FastlaneCore::Configuration.create(
97
+ def self.prepare_for_testing(scan_options)
98
+ if scan_options[:test_without_building] || scan_options[:skip_build]
99
+ prepare_scan_config(scan_options)
100
+ else
101
+ build_for_testing(scan_options)
102
+ end
103
+ end
104
+
105
+ def self.prepare_scan_config(scan_options)
106
+ Scan.config ||= FastlaneCore::Configuration.create(
95
107
  Fastlane::Actions::ScanAction.available_options,
96
- scan_options.merge(build_for_testing: true).reject { |k, _| options_to_remove.include?(k) }
108
+ scan_options.select { |k,v| %i[project workspace scheme device devices].include?(k) }
97
109
  )
98
- Fastlane::Actions::ScanAction.run(config)
110
+ end
99
111
 
100
- scan_options.merge!(
101
- test_without_building: true,
102
- derived_data_path: Scan.config[:derived_data_path]
103
- ).delete(:build_for_testing)
112
+ def self.build_for_testing(scan_options)
113
+ valid_scan_keys = Fastlane::Actions::ScanAction.available_options.map(&:key)
114
+ scan_options = scan_options.select { |k,v| %i[project workspace scheme device devices].include?(k) }
115
+
116
+ Scan.config = FastlaneCore::Configuration.create(
117
+ Fastlane::Actions::ScanAction.available_options,
118
+ scan_options.merge(build_for_testing: true)
119
+ )
120
+ values = Scan.config.values(ask: false)
121
+ values[:xcode_path] = File.expand_path("../..", FastlaneCore::Helper.xcode_path)
122
+
123
+ # :nocov:
124
+ unless Helper.test?
125
+ FastlaneCore::PrintTable.print_values(
126
+ config: values,
127
+ hide_keys: [:destination, :slack_url],
128
+ title: "Summary for scan #{Fastlane::VERSION}"
129
+ )
130
+ end
131
+ # :nocov:
132
+
133
+ Scan::Runner.new.run
134
+ remove_build_report_files
135
+
136
+ Scan.config._values.delete(:build_for_testing)
137
+ scan_options[:derived_data_path] = Scan.config[:derived_data_path]
138
+ end
139
+
140
+ def self.remove_build_report_files
141
+ report_options = Scan::XCPrettyReporterOptionsGenerator.generate_from_scan_config
142
+ output_files = report_options.instance_variable_get(:@output_files)
143
+ output_directory = report_options.instance_variable_get(:@output_directory)
144
+
145
+ output_files.each do |output_file|
146
+ FileUtils.rm_f(File.join(output_directory, output_file))
147
+ end
148
+ end
149
+
150
+ def self.force_quit_simulator_processes
151
+ # Silently execute and kill, verbose flags will show this command occurring
152
+ Fastlane::Actions.sh("killall Simulator &> /dev/null || true", log: false)
104
153
  end
105
154
 
106
155
  #####################################################
107
156
  # @!group Documentation
108
157
  #####################################################
109
158
 
159
+ # :nocov:
110
160
  def self.description
111
161
  "Uses scan to run Xcode tests a given number of times, with the option " \
112
162
  "of batching them, only re-testing failing tests."
@@ -174,7 +224,7 @@ module Fastlane
174
224
  FastlaneCore::ConfigItem.new(
175
225
  key: :quit_simulators,
176
226
  env_name: "FL_MULTI_SCAN_QUIT_SIMULATORS",
177
- description: "If the simulators need to be killed before run the tests",
227
+ description: "If the simulators need to be killed before running the tests",
178
228
  type: Boolean,
179
229
  is_string: false,
180
230
  default_value: true,
@@ -187,6 +237,13 @@ module Fastlane
187
237
  description: "Comma separated list of the output types (e.g. html, junit, json, json-compilation-database)",
188
238
  default_value: "html,junit"
189
239
  ),
240
+ FastlaneCore::ConfigItem.new(
241
+ key: :parallel_testrun_count,
242
+ description: 'Run simulators each batch of tests and/or each test target in parallel on its own Simulator',
243
+ optional: true,
244
+ is_string: false,
245
+ default_value: 1
246
+ ),
190
247
  FastlaneCore::ConfigItem.new(
191
248
  key: :testrun_completed_block,
192
249
  description: 'A block invoked each time a test run completes',
@@ -259,6 +316,24 @@ module Fastlane
259
316
  )
260
317
  ",
261
318
  "
319
+ UI.important(
320
+ 'example: ' \\
321
+ 'multi_scan also works with invocation based tests.'
322
+ )
323
+ Dir.chdir('../AtomicBoy') do
324
+ bundle_install
325
+ cocoapods(podfile: File.absolute_path('Podfile'))
326
+ multi_scan(
327
+ workspace: File.absolute_path('AtomicBoy.xcworkspace'),
328
+ scheme: 'KiwiBoy',
329
+ try_count: 3,
330
+ clean: true,
331
+ invocation_based_tests: true,
332
+ fail_build: false
333
+ )
334
+ end
335
+ ",
336
+ "
262
337
  UI.important(
263
338
  'example: ' \\
264
339
  'use the :workspace parameter instead of the :project parameter to find, ' \\
@@ -336,16 +411,35 @@ module Fastlane
336
411
  "
337
412
  UI.important(
338
413
  'example: ' \\
339
- 'multi_scan also works with invocation based tests.'
414
+ 'multi_scan parallelizes its test runs.'
340
415
  )
341
- cocoapods
342
416
  multi_scan(
343
- workspace: File.absolute_path('../KiwiDemo/KiwiDemo.xcworkspace'),
344
- scheme: 'KiwiDemoTests',
417
+ workspace: File.absolute_path('../AtomicBoy/AtomicBoy.xcworkspace'),
418
+ scheme: 'AtomicBoy',
345
419
  try_count: 3,
346
- invocation_based_tests: true,
420
+ parallel_testrun_count: 4,
347
421
  fail_build: false
348
422
  )
423
+ ",
424
+ "
425
+ UI.important(
426
+ 'example: ' \\
427
+ 'use the :xctestrun parameter instead of the :project parameter to find, ' \\
428
+ 'build, and test the iOS app.'
429
+ )
430
+ Dir.mktmpdir do |derived_data_path|
431
+ project_path = File.absolute_path('../AtomicBoy/AtomicBoy.xcodeproj')
432
+ command = \"bundle exec fastlane scan --build_for_testing true --project '\#{project_path}' --derived_data_path \#{derived_data_path} --scheme AtomicBoy\"
433
+ `\#{command}`
434
+ xctestrun_file = Dir.glob(\"\#{derived_data_path}/Build/Products/AtomicBoy*.xctestrun\").first
435
+ multi_scan(
436
+ scheme: 'AtomicBoy',
437
+ try_count: 3,
438
+ fail_build: false,
439
+ xctestrun: xctestrun_file,
440
+ test_without_building: true
441
+ )
442
+ end
349
443
  "
350
444
  ]
351
445
  end
@@ -361,6 +455,7 @@ module Fastlane
361
455
  def self.is_supported?(platform)
362
456
  %i[ios mac].include?(platform)
363
457
  end
458
+ # :nocov:
364
459
  end
365
460
  end
366
461
  end
@@ -0,0 +1,40 @@
1
+ module Fastlane
2
+ module Actions
3
+ class QuitCoreSimulatorServiceAction < Action
4
+ def self.run(params)
5
+ launchctl_list_count = 0
6
+ commands = []
7
+ while Actions.sh('launchctl list | grep com.apple.CoreSimulator.CoreSimulatorService || true', log: false) != ''
8
+ UI.crash!('Unable to quit com.apple.CoreSimulator.CoreSimulatorService after 10 tries') if (launchctl_list_count += 1) > 10
9
+ commands << Actions.sh('launchctl remove com.apple.CoreSimulator.CoreSimulatorService &> /dev/null || true', log: false)
10
+ UI.verbose('Waiting for com.apple.CoreSimulator.CoreSimulatorService to quit')
11
+ sleep(0.5)
12
+ end
13
+ commands
14
+ end
15
+
16
+ #####################################################
17
+ # @!group Documentation
18
+ #####################################################
19
+
20
+ # :nocov:
21
+ def self.description
22
+ "Force-quits the com.apple.CoreSimulator.CoreSimulatorService."
23
+ end
24
+
25
+ def self.details
26
+ "Sometimes the com.apple.CoreSimulator.CoreSimulatorService can hang. " \
27
+ "Use this action to force-quit it."
28
+ end
29
+
30
+ def self.authors
31
+ ["lyndsey-ferguson/@lyndseydf"]
32
+ end
33
+
34
+ def self.is_supported?(platform)
35
+ platform == :ios
36
+ end
37
+ # :nocov:
38
+ end
39
+ end
40
+ end
@@ -59,6 +59,7 @@ module Fastlane
59
59
  # @!group Documentation
60
60
  #####################################################
61
61
 
62
+ # :nocov:
62
63
  def self.description
63
64
  "Suppresses specific tests in a specific or all Xcode Schemes in a given project"
64
65
  end
@@ -171,6 +172,7 @@ module Fastlane
171
172
  def self.is_supported?(platform)
172
173
  %i[ios mac].include?(platform)
173
174
  end
175
+ # :nocov:
174
176
  end
175
177
  end
176
178
  end
@@ -45,7 +45,8 @@ module Fastlane
45
45
  #####################################################
46
46
  # @!group Documentation
47
47
  #####################################################
48
-
48
+
49
+ # :nocov:
49
50
  def self.description
50
51
  "Uses a junit xml report file to suppress either passing or failing tests in an Xcode Scheme"
51
52
  end
@@ -135,6 +136,7 @@ module Fastlane
135
136
  def self.is_supported?(platform)
136
137
  %i[ios mac].include?(platform)
137
138
  end
139
+ # :nocov:
138
140
  end
139
141
  end
140
142
  end
@@ -52,6 +52,7 @@ module Fastlane
52
52
  # @!group Documentation
53
53
  #####################################################
54
54
 
55
+ # :nocov:
55
56
  def self.description
56
57
  "Retrieves a list of tests that are suppressed in a specific or all Xcode Schemes in a project"
57
58
  end
@@ -139,6 +140,7 @@ module Fastlane
139
140
  def self.is_supported?(platform)
140
141
  %i[ios mac].include?(platform)
141
142
  end
143
+ # :nocov:
142
144
  end
143
145
  end
144
146
  end
@@ -32,6 +32,7 @@ module Fastlane
32
32
  # @!group Documentation
33
33
  #####################################################
34
34
 
35
+ # :nocov:
35
36
  def self.description
36
37
  "Retrieves the failing and passing tests as reported in a junit xml file"
37
38
  end
@@ -82,6 +83,7 @@ module Fastlane
82
83
  def self.is_supported?(platform)
83
84
  %i[ios mac].include?(platform)
84
85
  end
86
+ # :nocov:
85
87
  end
86
88
  end
87
89
  end
@@ -47,6 +47,7 @@ module Fastlane
47
47
  # @!group Documentation
48
48
  #####################################################
49
49
 
50
+ # :nocov:
50
51
  def self.description
51
52
  "Retrieves all of the tests from xctest bundles referenced by the xctestrun file"
52
53
  end
@@ -115,6 +116,7 @@ module Fastlane
115
116
  def self.is_supported?(platform)
116
117
  %i[ios mac].include?(platform)
117
118
  end
119
+ # :nocov:
118
120
  end
119
121
  end
120
122
  end
@@ -0,0 +1,30 @@
1
+ module FastlaneCore
2
+ class DeviceManager
3
+ class Device
4
+ def clone
5
+ raise 'Can only clone iOS Simulators' unless self.is_simulator
6
+ Device.new(
7
+ name: self.name,
8
+ udid: `xcrun simctl clone #{self.udid} '#{self.name}'`.chomp,
9
+ os_type: self.os_type,
10
+ os_version: self.os_version,
11
+ state: self.state,
12
+ is_simulator: self.is_simulator
13
+ )
14
+ end
15
+
16
+ def rename(newname)
17
+ `xcrun simctl rename #{self.udid} '#{newname}'`
18
+ self.name = newname
19
+ end
20
+
21
+ def boot
22
+ `xcrun simctl boot #{self.udid}`
23
+ end
24
+
25
+ def shutdown
26
+ `xcrun simctl shutdown #{self.udid}` unless self.state == "Shutdown"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,73 @@
1
+ module TestCenter
2
+ module Helper
3
+ module MultiScanManager
4
+ class ParallelTestBatchWorker < TestBatchWorker
5
+
6
+ attr_reader :pid
7
+
8
+ def initialize(options)
9
+ super(options)
10
+ @pipe_endpoint = nil
11
+ end
12
+
13
+ def state=(new_state)
14
+ super(new_state)
15
+ end
16
+
17
+ def process_results
18
+ @pid = nil
19
+ File.foreach(@log_filepath) do |line|
20
+ puts "[worker #{@options[:batch_index]}] #{line}"
21
+ end
22
+ state = :ready_to_work
23
+ @options[:test_batch_results] << (@reader.gets == 'true')
24
+ end
25
+
26
+ def run(run_options)
27
+ self.state = :working
28
+
29
+ open_interprocess_communication
30
+ @pid = Process.fork do
31
+ tests_passed = false
32
+ begin
33
+ reroute_stdout_to_logfile
34
+ tests_passed = super(run_options)
35
+ ensure
36
+ handle_child_process_results(tests_passed)
37
+ exit!
38
+ end
39
+ end
40
+ close_parent_process_writer
41
+ end
42
+
43
+ def open_interprocess_communication
44
+ @reader, @writer = IO.pipe
45
+ @log_filepath = File.join(
46
+ Dir.mktmpdir,
47
+ "parallel-test-batch-#{@options[:batch_index]}.txt"
48
+ )
49
+ end
50
+
51
+ def reroute_stdout_to_logfile
52
+ @reader.close # we are now in the subprocess
53
+ @logfile = File.open(@log_filepath, 'w')
54
+ @logfile.sync = true
55
+ $stdout.reopen(@logfile)
56
+ $stderr.reopen(@logfile)
57
+ end
58
+
59
+ def handle_child_process_results(tests_passed)
60
+ @logfile.close
61
+ @writer.puts tests_passed.to_s
62
+ @writer.close
63
+ end
64
+
65
+ def close_parent_process_writer
66
+ @writer.close
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+