fastlane-plugin-test_center 3.4.0 → 3.5.0

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
  SHA1:
3
- metadata.gz: '083be0187ece34a8f7019e4992c1fa2330b4732d'
4
- data.tar.gz: 364b206944566949934477d518853537f27cdabb
3
+ metadata.gz: 2c6a17f7ee4ae4381b5cff509b6ea0d2a7e860b8
4
+ data.tar.gz: 79aac0aa87a128f9ab42841a1c5b8b87db1165b8
5
5
  SHA512:
6
- metadata.gz: 64532eb3e5dfe6afdf6b49fe27555e58d052fc60cf3d57363becf437704e0519a696889032f0106fabafabaf5ab808f0f713b059af75a38f0e9aecc44e8f2cde
7
- data.tar.gz: 301e3e7946ab86b32aa310fd73b01cb2b222c00b99d1a255575964c1bed55ca864bf66b55ff2d50690776ff399d3c57335ac3d6737de2262c50a720a565af0e5
6
+ metadata.gz: 602af20f6d4659244c748df0907077e87b432756d1f3c8cf55873f29b8c47432d5f62a4ad6e07227a54313a959e97b2662a3cb6308c35ecc1f38f0764d7eea62
7
+ data.tar.gz: '096cb269e5fad71c010807212a466dc6067fa6dc86f63c9ba1484c6200d71d8af5a2bdf3965f6dd95c6155119b6d069bbd5294d6f067d781faa65e4bc5c170c9'
data/README.md CHANGED
@@ -70,6 +70,7 @@ This fastlane plugin includes the following actions:
70
70
  - [`collate_junit_reports`](#collate_junit_reports): combines multiple junit test reports into one report.
71
71
  - [`collate_html_reports`](#collate_html_reports): combines multiple html test reports into one report.
72
72
  - [`collate_json_reports`](#collate_json_reports): combines multiple json test reports into one report.
73
+ - [`collate_test_result_bundles`](#collate_test_result_bundles): combines multiple test_result bundles into one test_result bundle.
73
74
 
74
75
  ### multi_scan 🎉
75
76
 
@@ -107,27 +108,6 @@ UI.success("multi_scan passed? #{summary[:result]}")
107
108
 
108
109
  ```ruby
109
110
 
110
- UI.important(
111
- 'example: ' \
112
- 'run tests for a scheme that has two test targets, re-trying up to 2 times if ' \
113
- 'tests fail. Make sure that the default behavior of failing the build works.'
114
- )
115
- begin
116
- multi_scan(
117
- project: File.absolute_path('../AtomicBoy/AtomicBoy.xcodeproj'),
118
- scheme: 'AtomicBoy',
119
- try_count: 2
120
- )
121
- rescue FastlaneCore::Interface::FastlaneTestFailure => e
122
- UI.success("failed successfully with #{e.message}")
123
- else
124
- raise 'This should have failed'
125
- end
126
-
127
- ```
128
-
129
- ```ruby
130
-
131
111
  UI.important(
132
112
  'example: ' \
133
113
  'split the tests into 2 batches and run each batch of tests up to 3 ' \
@@ -158,9 +138,7 @@ test_run_block = lambda do |testrun_info|
158
138
  try_attempt = testrun_info[:try_count]
159
139
  batch = testrun_info[:batch]
160
140
 
161
- if passed_test_count > 0 && failed_test_count > passed_test_count / 2
162
- UI.abort_with_message!("Too many tests are failing")
163
- end
141
+ # UI.abort_with_message!('You could conditionally abort')
164
142
  UI.message("\ὠA everything is fine, let's continue try #{try_attempt + 1} for batch #{batch}")
165
143
  end
166
144
 
@@ -220,7 +198,7 @@ multi_scan(
220
198
  scheme: 'Professor',
221
199
  try_count: 3,
222
200
  custom_report_file_name: 'atomic_report.xml',
223
- output_types: 'junit,html',
201
+ output_types: 'junit',
224
202
  fail_build: false
225
203
  )
226
204
 
@@ -549,6 +527,30 @@ collate_json_reports(
549
527
  <!-- collate_json_reports examples: end -->
550
528
  </details>
551
529
 
530
+ ### collate_test_result_bundles
531
+
532
+ Do you have multiple test_result bundles coming in from different sources and need it combined? Use this action to collate all the tests performed for a given test target into one test_result bundle.
533
+
534
+ <details>
535
+ <summary>Example Code:</summary>
536
+ <!-- collate_test_result_bundles examples: begin -->
537
+
538
+ ```ruby
539
+
540
+ UI.important(
541
+ 'example: ' \
542
+ 'collate the test_result bundles to a temporary bundle "result.test_result"'
543
+ )
544
+ bundles = Dir['../spec/fixtures/*.test_result'].map { |relpath| File.absolute_path(relpath) }
545
+ collate_test_result_bundles(
546
+ bundles: bundles,
547
+ collated_bundle: File.join(Dir.mktmpdir, 'result.test_result')
548
+ )
549
+
550
+ ```
551
+ <!-- collate_test_result_bundles examples: end -->
552
+ </details>
553
+
552
554
  ## Run tests for this plugin
553
555
 
554
556
  To run both the tests, and code style validation, run
@@ -0,0 +1,180 @@
1
+ module Fastlane
2
+ module Actions
3
+ class CollateTestResultBundlesAction < Action
4
+ require 'plist'
5
+
6
+ def self.run(params)
7
+ test_result_bundlepaths = params[:bundles]
8
+ base_bundle_path = test_result_bundlepaths[0]
9
+ if test_result_bundlepaths.size > 1
10
+ base_bundle_path = Dir.mktmpdir(['base', '.test_result'])
11
+ FileUtils.cp_r(File.join(test_result_bundlepaths[0], '.'), base_bundle_path)
12
+ test_result_bundlepaths.shift
13
+ test_result_bundlepaths.each do |other_bundlepath|
14
+ collate_bundles(base_bundle_path, other_bundlepath)
15
+ end
16
+ end
17
+ FileUtils.rm_rf(params[:collated_bundle])
18
+ FileUtils.cp_r(base_bundle_path, params[:collated_bundle])
19
+ UI.message("Finished collating test_result bundle to '#{params[:collated_bundle]}'")
20
+ end
21
+
22
+ def self.collate_bundles(base_bundle_path, other_bundle_path)
23
+ Dir.foreach(other_bundle_path) do |child_item|
24
+ if child_item == 'Info.plist'
25
+ collate_infoplist(
26
+ File.join(base_bundle_path, child_item),
27
+ File.join(other_bundle_path, child_item)
28
+ )
29
+ elsif /\d_Test/ =~ child_item
30
+ test_target_path = File.join(base_bundle_path, child_item)
31
+ other_target_path = File.join(other_bundle_path, child_item)
32
+ Dir.foreach(other_target_path) do |grandchild_item|
33
+ collate_bundle(test_target_path, other_target_path, grandchild_item)
34
+ end
35
+ else
36
+ collate_bundle(base_bundle_path, other_bundle_path, child_item)
37
+ end
38
+ end
39
+ end
40
+
41
+ def self.collate_bundle(base_bundle_path, other_bundle_path, child_item_name)
42
+ if %w{Attachments Diagnostics}.include?(child_item_name)
43
+ FileUtils.cp_r(
44
+ File.join(other_bundle_path, child_item_name, '.'),
45
+ File.join(base_bundle_path, child_item_name)
46
+ )
47
+ elsif child_item_name.end_with?('.xcactivitylog')
48
+ concatenate_zipped_activitylogs(
49
+ File.join(base_bundle_path, child_item_name),
50
+ File.join(other_bundle_path, child_item_name)
51
+ )
52
+ elsif child_item_name.end_with?('TestSummaries.plist')
53
+ collate_testsummaries_plist(
54
+ File.join(base_bundle_path, child_item_name),
55
+ File.join(other_bundle_path, child_item_name)
56
+ )
57
+ end
58
+ end
59
+
60
+ def self.concatenate_zipped_activitylogs(base_activity_log_path, other_activity_log_path)
61
+ gunzipped_base_filepath = File.join(
62
+ File.dirname(base_activity_log_path),
63
+ File.basename(base_activity_log_path, '.*')
64
+ )
65
+ gunzipped_other_filepath = File.join(
66
+ File.dirname(other_activity_log_path),
67
+ File.basename(other_activity_log_path, '.*')
68
+ )
69
+ sh("gunzip -k -S .xcactivitylog #{other_activity_log_path}", print_command: false, print_command_output: false)
70
+ sh("gunzip -S .xcactivitylog #{base_activity_log_path}", print_command: false, print_command_output: false)
71
+ sh("cat #{gunzipped_other_filepath} > #{gunzipped_base_filepath}", print_command: false, print_command_output: false)
72
+ FileUtils.rm(gunzipped_other_filepath)
73
+ sh("gzip -S .xcactivitylog #{gunzipped_base_filepath}", print_command: false, print_command_output: false)
74
+ end
75
+
76
+ def self.collate_testsummaries_plist(base_testsummaries_plist_filepath, other_testsummaries_plist_filepath)
77
+ if File.exist?(base_testsummaries_plist_filepath)
78
+ base_testsummaries_plist = Plist.parse_xml(base_testsummaries_plist_filepath)
79
+ other_testsummaries_plist = Plist.parse_xml(other_testsummaries_plist_filepath)
80
+ base_testsummaries_plist['TestableSummaries'].zip(other_testsummaries_plist['TestableSummaries']).each do |base_testable_summary, other_testable_summary|
81
+ unless base_testable_summary.key?('PreviousTests')
82
+ base_testable_summary['PreviousTests'] = []
83
+ end
84
+ base_testable_summary['PreviousTests'].concat(base_testable_summary['Tests'] || [])
85
+ base_testable_summary['Tests'] = other_testable_summary['Tests']
86
+ end
87
+ Plist::Emit.save_plist(base_testsummaries_plist, base_testsummaries_plist_filepath)
88
+ else
89
+ FileUtils.cp(other_testsummaries_plist, base_testsummaries_plist)
90
+ end
91
+ end
92
+
93
+ def self.collate_infoplist(base_infoplist_filepath, other_infoplist_filepath)
94
+ if File.exist?(base_infoplist_filepath)
95
+ base_infoplist = Plist.parse_xml(base_infoplist_filepath)
96
+ other_infoplist = Plist.parse_xml(other_infoplist_filepath)
97
+ other_infoplist['Actions'].zip(base_infoplist['Actions']).each do |other_action, base_action|
98
+ if other_action['Title'] != base_action['Title']
99
+ raise 'Info.plist Actions do not align: cannot collate'
100
+ end
101
+ base_action['EndedTime'] = other_action['EndedTime']
102
+ base_action['ActionResult']['TestsFailedCount'] = other_action['ActionResult']['TestsFailedCount']
103
+ end
104
+ Plist::Emit.save_plist(base_infoplist, base_infoplist_filepath)
105
+ else
106
+ FileUtils.cp(other_infoplist_filepath, base_infoplist_filepath)
107
+ end
108
+ end
109
+
110
+ #####################################################
111
+ # @!group Documentation
112
+ #####################################################
113
+
114
+ def self.description
115
+ "Combines and combines tests from multiple test_result bundles"
116
+ end
117
+
118
+ def self.details
119
+ "The first test_result bundle is used as the base bundle. " \
120
+ "Testcases that failed in previous bundles that no longer appear in " \
121
+ "later bundles are assumed to have passed in a re-run, thus not appearing " \
122
+ "in the collated test_result bundle. " \
123
+ "This is done because it is assumed that fragile tests, when " \
124
+ "re-run will often succeed due to less interference from other " \
125
+ "tests and the subsequent test_result bundles will have fewer failing tests." \
126
+ ""
127
+ end
128
+
129
+ def self.available_options
130
+ [
131
+ FastlaneCore::ConfigItem.new(
132
+ key: :bundles,
133
+ env_name: 'COLLATE_TEST_RESULT_BUNDLES_BUNDLES',
134
+ description: 'An array of test_result bundles to collate. The first bundle is used as the base into which other bundles are merged in',
135
+ optional: false,
136
+ type: Array,
137
+ verify_block: proc do |bundles|
138
+ UI.user_error!('No test_result bundles found') if bundles.empty?
139
+ bundles.each do |bundle|
140
+ UI.user_error!("Error: test_result bundle not found: '#{bundle}'") unless Dir.exist?(bundle)
141
+ end
142
+ end
143
+ ),
144
+ FastlaneCore::ConfigItem.new(
145
+ key: :collated_bundle,
146
+ env_name: 'COLLATE_TEST_RESULT_BUNDLES_COLLATED_BUNDLE',
147
+ description: 'The final test_result bundle where all testcases will be merged into',
148
+ optional: true,
149
+ default_value: 'result.test_result',
150
+ type: String
151
+ )
152
+ ]
153
+ end
154
+
155
+ def self.example_code
156
+ [
157
+ "
158
+ UI.important(
159
+ 'example: ' \\
160
+ 'collate the test_result bundles to a temporary bundle \"result.test_result\"'
161
+ )
162
+ bundles = Dir['../spec/fixtures/*.test_result'].map { |relpath| File.absolute_path(relpath) }
163
+ collate_test_result_bundles(
164
+ bundles: bundles,
165
+ collated_bundle: File.join(Dir.mktmpdir, 'result.test_result')
166
+ )
167
+ "
168
+ ]
169
+ end
170
+
171
+ def self.authors
172
+ ["lyndsey-ferguson/@lyndseydf"]
173
+ end
174
+
175
+ def self.is_supported?(platform)
176
+ platform == :ios
177
+ end
178
+ end
179
+ end
180
+ end
@@ -63,6 +63,11 @@ module Fastlane
63
63
  File.absolute_path(relative_filepath)
64
64
  end
65
65
  end
66
+ if scan_options[:result_bundle]
67
+ report_files += Dir.glob("#{scan_options[:output_directory]}/**/*.test_result").map do |relative_test_result_bundle_filepath|
68
+ File.absolute_path(relative_test_result_bundle_filepath)
69
+ end
70
+ end
66
71
  {
67
72
  result: tests_passed,
68
73
  total_tests: passing_testcount + failed_tests.size,
@@ -188,24 +193,6 @@ module Fastlane
188
193
  UI.success(\"multi_scan passed? \#{summary[:result]}\")
189
194
  ",
190
195
  "
191
- UI.important(
192
- 'example: ' \\
193
- 'run tests for a scheme that has two test targets, re-trying up to 2 times if ' \\
194
- 'tests fail. Make sure that the default behavior of failing the build works.'
195
- )
196
- begin
197
- multi_scan(
198
- project: File.absolute_path('../AtomicBoy/AtomicBoy.xcodeproj'),
199
- scheme: 'AtomicBoy',
200
- try_count: 2
201
- )
202
- rescue FastlaneCore::Interface::FastlaneTestFailure => e
203
- UI.success(\"failed successfully with \#{e.message}\")
204
- else
205
- raise 'This should have failed'
206
- end
207
- ",
208
- "
209
196
  UI.important(
210
197
  'example: ' \\
211
198
  'split the tests into 2 batches and run each batch of tests up to 3 ' \\
@@ -233,9 +220,7 @@ module Fastlane
233
220
  try_attempt = testrun_info[:try_count]
234
221
  batch = testrun_info[:batch]
235
222
 
236
- if passed_test_count > 0 && failed_test_count > passed_test_count / 2
237
- UI.abort_with_message!(\"Too many tests are failing\")
238
- end
223
+ # UI.abort_with_message!('You could conditionally abort')
239
224
  UI.message(\"\\\u1F60A everything is fine, let's continue try \#{try_attempt + 1} for batch \#{batch}\")
240
225
  end
241
226
 
@@ -286,7 +271,7 @@ module Fastlane
286
271
  scheme: 'Professor',
287
272
  try_count: 3,
288
273
  custom_report_file_name: 'atomic_report.xml',
289
- output_types: 'junit,html',
274
+ output_types: 'junit',
290
275
  fail_build: false
291
276
  )
292
277
  ",
@@ -103,6 +103,10 @@ module TestCenter
103
103
  if reportnamer.includes_json?
104
104
  collate_json_reports(output_directory, reportnamer)
105
105
  end
106
+
107
+ if @scan_options[:result_bundle]
108
+ collate_test_result_bundles(output_directory, reportnamer)
109
+ end
106
110
  end
107
111
 
108
112
  def passed_test_count_from_summary(summary)
@@ -110,6 +114,24 @@ module TestCenter
110
114
  test_count.to_i - test_failures.to_i
111
115
  end
112
116
 
117
+ def collate_test_result_bundles(output_directory, reportnamer)
118
+ test_result_bundlepaths = Dir.glob("#{output_directory}/#{@scan_options[:scheme]}*.test_result").map do |relative_test_result_bundle_filepath|
119
+ File.absolute_path(relative_test_result_bundle_filepath)
120
+ end
121
+ if test_result_bundlepaths.size > 1
122
+ config = FastlaneCore::Configuration.create(
123
+ Fastlane::Actions::CollateTestResultBundlesAction.available_options,
124
+ {
125
+ bundles: test_result_bundlepaths.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) },
126
+ collated_bundle: File.join(output_directory, @scan_options[:scheme]) + '.test_result'
127
+ }
128
+ )
129
+ Fastlane::Actions::CollateTestResultBundlesAction.run(config)
130
+ end
131
+ retried_test_result_bundlepaths = Dir.glob("#{output_directory}/#{@scan_options[:scheme]}_*.test_result")
132
+ FileUtils.rm_rf(retried_test_result_bundlepaths)
133
+ end
134
+
113
135
  def collate_json_reports(output_directory, reportnamer)
114
136
  report_filepaths = Dir.glob("#{output_directory}/#{reportnamer.json_fileglob}").map do |relative_filepath|
115
137
  File.absolute_path(relative_filepath)
@@ -198,13 +220,13 @@ module TestCenter
198
220
 
199
221
  scan_options[:only_testing] = info[:failed].map(&:shellescape)
200
222
  FastlaneCore::UI.message('Re-running scan on only failed tests')
223
+ reportnamer.increment
201
224
  if @scan_options[:result_bundle]
202
225
  built_test_result, moved_test_result = test_result_bundlepaths(
203
226
  scan_options[:output_directory], reportnamer
204
227
  )
205
228
  FileUtils.mv(built_test_result, moved_test_result)
206
229
  end
207
- reportnamer.increment
208
230
  retry
209
231
  end
210
232
  tests_passed = false
@@ -239,6 +261,12 @@ module TestCenter
239
261
  json_report_filepath = File.join(output_directory, reportnamer.json_last_reportname)
240
262
  info[:json_report_filepath] = json_report_filepath
241
263
  end
264
+ if @scan_options[:result_bundle]
265
+ test_result_suffix = '.test_result'
266
+ test_result_suffix.prepend("_#{reportnamer.report_count}") unless reportnamer.report_count.zero?
267
+ test_result_bundlepath = File.join(output_directory, @scan_options[:scheme]) + test_result_suffix
268
+ info[:test_result_bundlepath] = test_result_bundlepath
269
+ end
242
270
  info
243
271
  end
244
272
 
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module TestCenter
3
- VERSION = "3.4.0"
3
+ VERSION = "3.5.0"
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.4.0
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lyndsey Ferguson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-24 00:00:00.000000000 Z
11
+ date: 2018-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -206,15 +206,8 @@ dependencies:
206
206
  - - ">="
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0'
209
- description: |2
210
- This fastlane plugin includes the following actions:
211
- 1) multi_scan: uses scan to run Xcode tests, optionally in batches, a given number of times: only re-testing failing tests.
212
- 2) suppress_tests_from_junit: uses a junit xml report file to suppress either passing or failing tests in an Xcode Scheme.
213
- 3) suppress_tests: suppresses specific tests in a specific or all Xcode Schemes in a given project.
214
- 4) suppressed_tests: retrieves a list of tests that are suppressed in a specific or all Xcode Schemes in a project.
215
- 5) tests_from_junit: retrieves the failing and passing tests as reported in a junit xml file.
216
- 6) tests_from_xctestrun: retrieves all of the tests from xctest bundles referenced by the xctestrun file
217
- 7) collate_junit_reports: collects and correctly organizes junit reports from multiple test passes.
209
+ description: " This fastlane plugin includes the following many actions to better
210
+ manage how you test, what you test, and the information you get from your tests\n"
218
211
  email: ldf.public+github@outlook.com
219
212
  executables: []
220
213
  extensions: []
@@ -226,6 +219,7 @@ files:
226
219
  - lib/fastlane/plugin/test_center/actions/collate_html_reports.rb
227
220
  - lib/fastlane/plugin/test_center/actions/collate_json_reports.rb
228
221
  - lib/fastlane/plugin/test_center/actions/collate_junit_reports.rb
222
+ - lib/fastlane/plugin/test_center/actions/collate_test_result_bundles.rb
229
223
  - lib/fastlane/plugin/test_center/actions/multi_scan.rb
230
224
  - lib/fastlane/plugin/test_center/actions/suppress_tests.rb
231
225
  - lib/fastlane/plugin/test_center/actions/suppress_tests_from_junit.rb