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

Sign up to get free protection for your applications and to get access to all the features.
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
+