Class: TestCenter::Helper::CorrectingScanHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(multi_scan_options) ⇒ CorrectingScanHelper

Returns a new instance of CorrectingScanHelper.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 9

def initialize(multi_scan_options)
  @batch_count = multi_scan_options[:batch_count] || 1
  @output_directory = multi_scan_options[:output_directory] || 'test_results'
  @try_count = multi_scan_options[:try_count]
  @quit_simulators = multi_scan_options[:quit_simulators]
  @retry_total_count = 0
  @testrun_completed_block = multi_scan_options[:testrun_completed_block]
  @given_custom_report_file_name = multi_scan_options[:custom_report_file_name]
  @given_output_types = multi_scan_options[:output_types]
  @given_output_files = multi_scan_options[:output_files]
  @scan_options = multi_scan_options.reject do |option, _|
    %i[
      output_directory
      only_testing
      skip_testing
      clean
      try_count
      batch_count
      quit_simulators
      custom_report_file_name
      fail_build
      testrun_completed_block
      output_types
      output_files
    ].include?(option)
  end
  @scan_options[:clean] = false
  @test_collector = TestCollector.new(multi_scan_options)
end

Instance Attribute Details

#retry_total_countObject (readonly)

Returns the value of attribute retry_total_count.



7
8
9
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 7

def retry_total_count
  @retry_total_count
end

Instance Method Details

#collate_html_reports(output_directory, reportnamer) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 160

def collate_html_reports(output_directory, reportnamer)
  report_files = Dir.glob("#{output_directory}/#{reportnamer.html_fileglob}").map do |relative_filepath|
    File.absolute_path(relative_filepath)
  end
  if report_files.size > 1
    config = FastlaneCore::Configuration.create(
      Fastlane::Actions::CollateHtmlReportsAction.available_options,
      {
        reports: report_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
        collated_report: File.absolute_path(File.join(output_directory, reportnamer.html_reportname))
      }
    )
    Fastlane::Actions::CollateHtmlReportsAction.run(config)
  end
  retried_html_reportfiles = Dir.glob("#{output_directory}/#{reportnamer.html_numbered_fileglob}")
  FileUtils.rm_f(retried_html_reportfiles)
end

#collate_json_reports(output_directory, reportnamer) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 142

def collate_json_reports(output_directory, reportnamer)
  report_filepaths = Dir.glob("#{output_directory}/#{reportnamer.json_fileglob}").map do |relative_filepath|
    File.absolute_path(relative_filepath)
  end
  if report_filepaths.size > 1
    config = FastlaneCore::Configuration.create(
      Fastlane::Actions::CollateJsonReportsAction.available_options,
      {
        reports: report_filepaths.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
        collated_report: File.absolute_path(File.join(output_directory, reportnamer.json_reportname))
      }
    )
    Fastlane::Actions::CollateJsonReportsAction.run(config)
  end
  retried_json_reportfiles = Dir.glob("#{output_directory}/#{reportnamer.json_numbered_fileglob}")
  FileUtils.rm_f(retried_json_reportfiles)
end

#collate_junit_reports(output_directory, reportnamer) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 178

def collate_junit_reports(output_directory, reportnamer)
  report_files = Dir.glob("#{output_directory}/#{reportnamer.junit_fileglob}").map do |relative_filepath|
    File.absolute_path(relative_filepath)
  end
  if report_files.size > 1
    config = FastlaneCore::Configuration.create(
      Fastlane::Actions::CollateJunitReportsAction.available_options,
      {
        reports: report_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
        collated_report: File.absolute_path(File.join(output_directory, reportnamer.junit_reportname))
      }
    )
    Fastlane::Actions::CollateJunitReportsAction.run(config)
  end
  retried_junit_reportfiles = Dir.glob("#{output_directory}/#{reportnamer.junit_numbered_fileglob}")
  FileUtils.rm_f(retried_junit_reportfiles)
end

#collate_reports(output_directory, reportnamer) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 103

def collate_reports(output_directory, reportnamer)
  collate_junit_reports(output_directory, reportnamer)

  if reportnamer.includes_html?
    collate_html_reports(output_directory, reportnamer)
  end

  if reportnamer.includes_json?
    collate_json_reports(output_directory, reportnamer)
  end

  if @scan_options[:result_bundle]
    collate_test_result_bundles(output_directory, reportnamer)
  end
end

#collate_test_result_bundles(output_directory, reportnamer) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 124

def collate_test_result_bundles(output_directory, reportnamer)
  test_result_bundlepaths = Dir.glob("#{output_directory}/#{@scan_options[:scheme]}*.test_result").map do |relative_test_result_bundle_filepath|
    File.absolute_path(relative_test_result_bundle_filepath)
  end
  if test_result_bundlepaths.size > 1
    config = FastlaneCore::Configuration.create(
      Fastlane::Actions::CollateTestResultBundlesAction.available_options,
      {
        bundles: test_result_bundlepaths.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
        collated_bundle: File.join(output_directory, @scan_options[:scheme]) + '.test_result'
      }
    )
    Fastlane::Actions::CollateTestResultBundlesAction.run(config)
  end
  retried_test_result_bundlepaths = Dir.glob("#{output_directory}/#{@scan_options[:scheme]}_*.test_result")
  FileUtils.rm_rf(retried_test_result_bundlepaths)
end

#correcting_scan(scan_run_options, batch, reportnamer) ⇒ Object



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 196

def correcting_scan(scan_run_options, batch, reportnamer)
  scan_options = @scan_options.merge(scan_run_options)
  try_count = 0
  tests_passed = true
  xcpretty_json_file_output = ENV['XCPRETTY_JSON_FILE_OUTPUT']
  begin
    try_count += 1
    config = FastlaneCore::Configuration.create(
      Fastlane::Actions::ScanAction.available_options,
      scan_options.merge(reportnamer.scan_options)
    )
    quit_simulators
    if reportnamer.includes_json?
      ENV['XCPRETTY_JSON_FILE_OUTPUT'] = File.join(
        scan_options[:output_directory],
        reportnamer.json_last_reportname
      )
    end
    Fastlane::Actions::ScanAction.run(config)
    @testrun_completed_block && @testrun_completed_block.call(
      testrun_info(batch, try_count, reportnamer, scan_options[:output_directory])
    )
    tests_passed = true
  rescue FastlaneCore::Interface::FastlaneTestFailure => e
    FastlaneCore::UI.verbose("Scan failed with #{e}")
    info = testrun_info(batch, try_count, reportnamer, scan_options[:output_directory])
    @testrun_completed_block && @testrun_completed_block.call(
      info
    )
    if try_count < @try_count
      @retry_total_count += 1
      scan_options.delete(:code_coverage)
      scan_options[:only_testing] = info[:failed].map(&:shellescape)
      FastlaneCore::UI.message('Re-running scan on only failed tests')
      reportnamer.increment
      if @scan_options[:result_bundle]
        built_test_result, moved_test_result = test_result_bundlepaths(
          scan_options[:output_directory], reportnamer
        )
        FileUtils.mv(built_test_result, moved_test_result)
      end
      retry
    end
    tests_passed = false
  ensure
    ENV['XCPRETTY_JSON_FILE_OUTPUT'] = xcpretty_json_file_output
  end
  tests_passed
end

#passed_test_count_from_summary(summary) ⇒ Object



119
120
121
122
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 119

def passed_test_count_from_summary(summary)
  /.*Executed (?<test_count>\d+) test, with (?<test_failures>\d+) failure/ =~ summary
  test_count.to_i - test_failures.to_i
end

#quit_simulatorsObject



280
281
282
283
284
285
286
287
288
289
290
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 280

def quit_simulators
  return unless @quit_simulators

  Fastlane::Actions.sh("killall -9 'iPhone Simulator' 'Simulator' 'SimulatorBridge' &> /dev/null || true", log: false)
  launchctl_list_count = 0
  while Fastlane::Actions.sh('launchctl list | grep com.apple.CoreSimulator.CoreSimulatorService || true', log: false) != ''
    break if (launchctl_list_count += 1) > 10
    Fastlane::Actions.sh('launchctl remove com.apple.CoreSimulator.CoreSimulatorService &> /dev/null || true', log: false)
    sleep(1)
  end
end

#scanObject



39
40
41
42
43
44
45
46
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 39

def scan
  tests_passed = true
  @testables_count = @test_collector.testables.size
  @test_collector.testables.each do |testable|
    tests_passed = scan_testable(testable) && tests_passed
  end
  tests_passed
end

#scan_testable(testable) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 48

def scan_testable(testable)
  tests_passed = true
  reportnamer = ReportNameHelper.new(
    @given_output_types,
    @given_output_files,
    @given_custom_report_file_name
  )
  output_directory = @output_directory
  testable_tests = @test_collector.testables_tests[testable]
  if testable_tests.empty?
    FastlaneCore::UI.important("There are no tests to run in testable '#{testable}'. Skipping")
    return true
  end

  if @batch_count > 1 || @testables_count > 1
    current_batch = 1
    testable_tests.each_slice((testable_tests.length / @batch_count.to_f).round).to_a.each do |tests_batch|
      if @testables_count > 1
        output_directory = File.join(@output_directory, "results-#{testable}")
      end
      FastlaneCore::UI.header("Starting test run on testable '#{testable}'")
      if @scan_options[:result_bundle]
        FastlaneCore::UI.message("Clearing out previous test_result bundles in #{output_directory}")
        FileUtils.rm_rf(Dir.glob("#{output_directory}/*.test_result"))
      end

      tests_passed = correcting_scan(
        {
          only_testing: tests_batch,
          output_directory: output_directory
        },
        current_batch,
        reportnamer
      ) && tests_passed
      current_batch += 1
      reportnamer.increment
    end
  else
    options = {
      output_directory: output_directory,
      only_testing: testable_tests
    }
    tests_passed = correcting_scan(options, 1, reportnamer) && tests_passed
  end
  collate_reports(output_directory, reportnamer)
  tests_passed
end

#test_result_bundlepaths(output_directory, reportnamer) ⇒ Object



96
97
98
99
100
101
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 96

def test_result_bundlepaths(output_directory, reportnamer)
  [
    File.join(output_directory, @scan_options[:scheme]) + '.test_result',
    File.join(output_directory, @scan_options[:scheme]) + "_#{reportnamer.report_count}.test_result"
  ]
end

#testrun_info(batch, try_count, reportnamer, output_directory) ⇒ Object



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb', line 246

def testrun_info(batch, try_count, reportnamer, output_directory)
  report_filepath = File.join(output_directory, reportnamer.junit_last_reportname)
  config = FastlaneCore::Configuration.create(
    Fastlane::Actions::TestsFromJunitAction.available_options,
    {
      junit: File.absolute_path(report_filepath)
    }
  )
  junit_results = Fastlane::Actions::TestsFromJunitAction.run(config)

  info = {
    failed: junit_results[:failed],
    passing: junit_results[:passing],
    batch: batch,
    try_count: try_count,
    report_filepath: report_filepath
  }
  if reportnamer.includes_html?
    html_report_filepath = File.join(output_directory, reportnamer.html_last_reportname)
    info[:html_report_filepath] = html_report_filepath
  end
  if reportnamer.includes_json?
    json_report_filepath = File.join(output_directory, reportnamer.json_last_reportname)
    info[:json_report_filepath] = json_report_filepath
  end
  if @scan_options[:result_bundle]
    test_result_suffix = '.test_result'
    test_result_suffix.prepend("_#{reportnamer.report_count}") unless reportnamer.report_count.zero?
    test_result_bundlepath = File.join(output_directory, @scan_options[:scheme]) + test_result_suffix
    info[:test_result_bundlepath] = test_result_bundlepath
  end
  info
end