fastlane-plugin-retry_tests 1.2.8 → 1.2.9

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: 32c5975d7acd0ad38b357fa71192c8557609f42b
4
- data.tar.gz: 57ea614acc20fcee707d2a35f36180cc15504038
3
+ metadata.gz: 32bf848c6f9dedbbc10b83eb2c3a0b494e54ce27
4
+ data.tar.gz: f588d58c28cf698efedb32332897020f59f5db54
5
5
  SHA512:
6
- metadata.gz: 61d4605ab74ed8ac4345d4713ba057ac23b97c613efe32c4b0e39c15e8544065339ff9c5cb4c2a1cca73ea6786f9fb0e01031b902d2ad2b68f721911da4270c9
7
- data.tar.gz: de0dd075ecdd7d1339222b948f606d640a85d1970623afbff47ba53b028466287524e8dbb78061d96af24f145c576323a44b9b48deb4d6affe4490705db66fd1
6
+ metadata.gz: 95b16cd8a9c88160821a2206e853fdadb62ac7419da7b94d866ff0d12daed2cb6d4972a5cc3ee1357c3e7a6a11a9f4466bdb37c278d6564567b99ea9756b35ca
7
+ data.tar.gz: 1993130eea75cd9111e02643f9ad33a29b114b87a8dee41c08a55fa09ee8d06a6264da5fa066f743033eb937ce61d477def7ffacbd5e1592ccf8c632491e0cc1
@@ -0,0 +1,16 @@
1
+ #require 'fastlane/plugin/retry_tests/version'
2
+
3
+ module Fastlane
4
+ module TestCenter
5
+ # Return all .rb files inside the "actions" and "helper" directory
6
+ def self.all_classes
7
+ Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
8
+ end
9
+ end
10
+ end
11
+
12
+ # By default we want to import all available actions and helpers
13
+ # A plugin can contain any number of actions and plugins
14
+ Fastlane::TestCenter.all_classes.each do |current|
15
+ require current
16
+ end
@@ -0,0 +1,178 @@
1
+
2
+ require 'nokogiri'
3
+ require 'nokogiri-plist'
4
+ require 'FileUtils'
5
+ module Fastlane
6
+ module Actions
7
+ class CollateJunitReportsAction < Action
8
+
9
+ def self.run(params)
10
+ report_filepaths = params[:reports].reverse
11
+ if report_filepaths.size == 1
12
+ FileUtils.cp(report_filepaths[0], params[:collated_report])
13
+ else
14
+ target_report = File.open(report_filepaths.shift) {|f| Nokogiri::XML(f)}
15
+ file_name = params[:collated_report] + "/#{params[:scheme]}.test_result/1_Test/action_TestSummaries.plist"
16
+ reports = report_filepaths.map { |report_filepath| Nokogiri::XML(Nokogiri::PList(open(report_filepath)).to_plist_xml) }
17
+ reports.each do |retry_report|
18
+ mergeLists(target_report, retry_report, params)
19
+ end
20
+ end
21
+ merge_assets(params[:assets], params[:collated_report] + "/Attachments")
22
+ copy_log(params[:logs], params[:collated_report] + "/")
23
+ end
24
+
25
+ def self.clean_report(report)
26
+ report = report.gsub(/<(\w+): 0x(\w+)>/, '(\1: 0x\2)')
27
+ report = report.gsub(/<XCAccessibilityElement:\/>0x(\w+)/, '(XCAccessibilityElement): 0x\1')
28
+ report
29
+ end
30
+
31
+ def self.copy_log(log_files, logs_folder)
32
+ target_log = log_files.shift
33
+ FileUtils.cp_r(target_log, logs_folder)
34
+ end
35
+
36
+ def self.mergeLists(target_report, retry_report, params)
37
+ retry_report = clean_report(retry_report)
38
+ UI.verbose("Merging retried results...")
39
+ Dir.mkdir(params[:collated_report]) unless File.exists?(params[:collated_report])
40
+ file_name = params[:collated_report] + "/action_TestSummaries.plist"
41
+ retried_tests = retry_report.xpath("//key[contains(.,'TestSummaryGUID')]/..")
42
+ current_node = retried_tests.shift
43
+ while (current_node != nil)
44
+ testName = get_test_name(current_node)
45
+ matching_node = target_report.at_xpath("//string[contains(.,'#{testName}')]/..")
46
+
47
+ if (!matching_node.nil?)
48
+ matching_node.previous.next.replace(current_node)
49
+ write_report_to_file(target_report, file_name)
50
+ end
51
+ current_node = retried_tests.shift
52
+ end
53
+ end
54
+
55
+ def self.merge_assets(asset_files, assets_folder)
56
+ UI.verbose ("Merging screenshot folders...")
57
+ Dir.mkdir(assets_folder) unless File.exists?(assets_folder)
58
+ asset_files.each do |folder|
59
+ FileUtils.cp_r(Dir[folder + '/*'], assets_folder)
60
+ end
61
+ end
62
+
63
+ def self.merge_logs(log_files, logs_folder)
64
+ UI.verbose("Merging console logs...")
65
+ target_log = log_files.shift
66
+ log_files.each do |log|
67
+ to_append = File.read(log)
68
+ File.open(target_log, "a") do |handle|
69
+ handle.puts to_append
70
+ end
71
+ FileUtils.cp_r(target_log, logs_folder)
72
+ end
73
+ end
74
+
75
+ def self.write_report_to_file(report, file_name)
76
+ UI.verbose("Writing merged results to file...")
77
+ File.new(file_name, 'w')
78
+ File.open(file_name, 'w') do |f|
79
+ f.write(report.to_xml)
80
+ end
81
+ end
82
+
83
+ def self.get_test_name(test_data)
84
+ test_name = test_data.xpath("(//key[contains(.,'TestSummaryGUID')])/../key[contains(.,'TestName')]/following-sibling::string").to_a[0].to_s
85
+ test_name = test_name[8..-10]
86
+ test_name
87
+ end
88
+
89
+ #####################################################
90
+ # @!group Documentation
91
+ #####################################################
92
+
93
+ def self.description
94
+ "Combines and combines tests from multiple junit report files"
95
+ end
96
+
97
+ def self.details
98
+ "The first junit report is used as the base report. Testcases " \
99
+ "from other reports are added if they do not already exist, or " \
100
+ "if the testcases already exist, they are replaced." \
101
+ "" \
102
+ "This is done because it is assumed that fragile tests, when " \
103
+ "re-run will often succeed due to less interference from other " \
104
+ "tests and the subsequent junit reports will have more passed tests." \
105
+ "" \
106
+ "Inspired by Derek Yang's fastlane-plugin-merge_junit_report"
107
+ end
108
+
109
+ def self.available_options
110
+ [
111
+ FastlaneCore::ConfigItem.new(
112
+ key: :scheme,
113
+ env_name: 'SCHEME',
114
+ description: 'The test scheme being run',
115
+ optional: false,
116
+ default_value: '',
117
+ type: String
118
+ ),
119
+ FastlaneCore::ConfigItem.new(
120
+ key: :reports,
121
+ env_name: 'COLLATE_JUNIT_REPORTS_REPORTS',
122
+ description: 'An array of junit reports to collate. The first report is used as the base into which other reports are merged in',
123
+ optional: false,
124
+ type: Array,
125
+ verify_block: proc do |reports|
126
+ UI.user_error!('No junit report files found') if reports.empty?
127
+ reports.each do |report|
128
+ UI.user_error!("Error: junit report not found: '#{report}'") unless File.exist?(report)
129
+ end
130
+ end
131
+ ),
132
+ FastlaneCore::ConfigItem.new(
133
+ key: :collated_report,
134
+ env_name: 'COLLATE_JUNIT_REPORTS_COLLATED_REPORT',
135
+ description: 'The final junit report file where all testcases will be merged into',
136
+ optional: true,
137
+ default_value: 'result.xml',
138
+ type: String
139
+ ),
140
+ FastlaneCore::ConfigItem.new(
141
+ key: :assets,
142
+ env_name: 'COLLATE_JUNIT_REPORTS_ASSETS',
143
+ description: 'An array of junit reports to collate. The first report is used as the base into which other reports are merged in',
144
+ optional: false,
145
+ type: Array,
146
+ verify_block: proc do |assets|
147
+ UI.user_error!('No junit report files found') if assets.empty?
148
+ assets.each do |asset|
149
+ UI.user_error!("Error: junit report not found: '#{asset}'") unless File.exist?(asset)
150
+ end
151
+ end
152
+ ),
153
+ FastlaneCore::ConfigItem.new(
154
+ key: :logs,
155
+ env_name: 'COLLATE_JUNIT_REPORTS_LOGS',
156
+ description: 'An array of junit reports to collate. The first report is used as the base into which other reports are merged in',
157
+ optional: false,
158
+ type: Array,
159
+ verify_block: proc do |logs|
160
+ UI.user_error!('No junit report files found') if logs.empty?
161
+ logs.each do |log|
162
+ UI.user_error!("Error: junit report not found: '#{log}'") unless File.exist?(log)
163
+ end
164
+ end
165
+ )
166
+ ]
167
+ end
168
+
169
+ def self.authors
170
+ ["lyndsey-ferguson/@lyndseydf"]
171
+ end
172
+
173
+ def self.is_supported?(platform)
174
+ platform == :ios
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,143 @@
1
+ module Fastlane
2
+ module Actions
3
+ require 'fastlane/actions/scan'
4
+ require 'shellwords'
5
+
6
+ class MultiScanAction < Action
7
+ def self.run(params)
8
+ try_count = 0
9
+ scan_options = params.values.reject { |k| k == :try_count }
10
+ final_report_path = scan_options[:result_bundle]
11
+ unless Helper.test?
12
+ FastlaneCore::PrintTable.print_values(
13
+ config: params._values.reject { |k, v| scan_options.key?(k) },
14
+ title: "Summary for multi_scan (test_center v#{Fastlane::TestCenter::VERSION})"
15
+ )
16
+ end
17
+
18
+ scan_options = config_with_junit_report(scan_options)
19
+
20
+ begin
21
+ try_count += 1
22
+ scan_options = config_with_retry(scan_options, try_count)
23
+ config = FastlaneCore::Configuration.create(Fastlane::Actions::ScanAction.available_options, scan_options)
24
+ Fastlane::Actions::ScanAction.run(config)
25
+ rescue FastlaneCore::Interface::FastlaneTestFailure => e
26
+ UI.verbose("Scan failed with #{e}")
27
+ if try_count < params[:try_count]
28
+ report_filepath = junit_report_filepath(scan_options)
29
+ failed_tests = other_action.tests_from_junit(junit: report_filepath)[:failed]
30
+ scan_options[:only_testing] = failed_tests.map(&:shellescape)
31
+ retry
32
+ end
33
+ end
34
+ merge_reports(scan_options, final_report_path)
35
+ end
36
+
37
+ def self.merge_reports(scan_options, final_report_path)
38
+ folder = get_folder_root(scan_options[:output_directory])
39
+ report_files = Dir.glob("#{folder}*/#{scan_options[:scheme]}.test_result/1_Test/action_TestSummaries.plist")
40
+ asset_files = Dir.glob("#{folder}*/#{scan_options[:scheme]}.test_result/1_Test/Attachments")
41
+ log_files = Dir.glob("#{folder}*/#{scan_options[:scheme]}.test_result/1_Test/action.xcactivitylog")
42
+ #Merge all reports, screenshots, and logs if there were retried tests
43
+
44
+ if report_files.size > 1
45
+ other_action.collate_junit_reports(
46
+ scheme: scan_options[:scheme],
47
+ reports: report_files,
48
+ collated_report: final_report_path,
49
+ assets: asset_files,
50
+ logs: log_files,
51
+ )
52
+ end
53
+ end
54
+
55
+ def self.config_has_junit_report(config)
56
+ output_types = config.fetch(:output_types, '').to_s.split(',')
57
+ output_filenames = config.fetch(:output_files, '').to_s.split(',')
58
+
59
+ output_type_file_count_match = output_types.size == output_filenames.size
60
+ output_types.include?('junit') && (output_type_file_count_match || config[:custom_report_file_name].to_s.strip.length > 0)
61
+ end
62
+
63
+ def self.config_with_retry(config, count)
64
+ folder = get_folder_root(config[:result_bundle])
65
+ config[:result_bundle] = (folder + count.to_s)
66
+ config[:output_directory] = (folder + count.to_s)
67
+ config
68
+ end
69
+
70
+ def self.get_folder_root(folder)
71
+ folder = folder.gsub(/ *\d+$/, '')
72
+ folder
73
+ end
74
+
75
+ def self.config_with_junit_report(config)
76
+ return config if config_has_junit_report(config)
77
+
78
+ if config[:output_types].to_s.strip.empty? || config[:custom_report_file_name]
79
+ config[:custom_report_file_name] ||= 'report.xml'
80
+ config[:output_types] = 'junit'
81
+ elsif config[:output_types].strip == 'junit' && config[:output_files].to_s.strip.empty?
82
+ config[:custom_report_file_name] ||= 'report.xml'
83
+ elsif !config[:output_types].split(',').include?('junit')
84
+ config[:output_types] << ',junit'
85
+ config[:output_files] << ',report.xml'
86
+ elsif config[:output_files].nil?
87
+ config[:output_files] = config[:output_types].split(',').map { |type| "report.#{type}" }.join(',')
88
+ end
89
+ config
90
+ end
91
+
92
+ def self.junit_report_filename(config)
93
+ report_filename = config[:custom_report_file_name]
94
+ if report_filename.nil?
95
+ junit_index = config[:output_types].split(',').find_index('junit')
96
+ report_filename = config[:output_files].to_s.split(',')[junit_index]
97
+ end
98
+ report_filename
99
+ end
100
+
101
+ def self.junit_report_filepath(config)
102
+ File.absolute_path(File.join(config[:output_directory], junit_report_filename(config)))
103
+ end
104
+
105
+ #####################################################
106
+ # @!group Documentation
107
+ #####################################################
108
+
109
+ def self.description
110
+ "Uses scan to run Xcode tests a given number of times: only re-testing failing tests."
111
+ end
112
+
113
+ def self.details
114
+ "Use this action to run your tests if you have fragile tests that fail sporadically."
115
+ end
116
+
117
+ def self.scan_options
118
+ ScanAction.available_options
119
+ end
120
+
121
+ def self.available_options
122
+ scan_options + [
123
+ FastlaneCore::ConfigItem.new(
124
+ key: :try_count,
125
+ env_name: "FL_MULTI_SCAN_TRY_COUNT",
126
+ description: "The number of times to retry running tests via scan",
127
+ type: Integer,
128
+ is_string: false,
129
+ default_value: 1
130
+ )
131
+ ]
132
+ end
133
+
134
+ def self.authors
135
+ ["lyndsey-ferguson/@lyndseydf"]
136
+ end
137
+
138
+ def self.is_supported?(platform)
139
+ platform == :ios
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,93 @@
1
+ module Fastlane
2
+ module Actions
3
+ class SuppressTestsAction < Action
4
+ require 'xcodeproj'
5
+
6
+ def self.run(params)
7
+ project_path = params[:xcodeproj]
8
+ all_tests_to_skip = params[:tests]
9
+ scheme = params[:scheme]
10
+
11
+ scheme_filepaths = Dir.glob("#{project_path}/{xcshareddata,xcuserdata}/**/xcschemes/#{scheme || '*'}.xcscheme")
12
+ if scheme_filepaths.length.zero?
13
+ UI.user_error!("Error: cannot find any scheme named #{scheme}") unless scheme.nil?
14
+ UI.user_error!("Error: cannot find any schemes in the Xcode project")
15
+ end
16
+
17
+ scheme_filepaths.each do |scheme_filepath|
18
+ is_dirty = false
19
+ xcscheme = Xcodeproj::XCScheme.new(scheme_filepath)
20
+ xcscheme.test_action.testables.each do |testable|
21
+ buildable_name = File.basename(testable.buildable_references[0].buildable_name, '.xctest')
22
+
23
+ tests_to_skip = all_tests_to_skip.select { |test| test.start_with?(buildable_name) }
24
+ .map { |test| test.sub("#{buildable_name}/", '') }
25
+
26
+ tests_to_skip.each do |test_to_skip|
27
+ skipped_test = Xcodeproj::XCScheme::TestAction::TestableReference::SkippedTest.new
28
+ skipped_test.identifier = test_to_skip
29
+ testable.add_skipped_test(skipped_test)
30
+ is_dirty = true
31
+ end
32
+ end
33
+ xcscheme.save! if is_dirty
34
+ end
35
+ nil
36
+ end
37
+
38
+ #####################################################
39
+ # @!group Documentation
40
+ #####################################################
41
+
42
+ def self.description
43
+ "Suppresses specific tests in a specific or all Xcode Schemes in a given project"
44
+ end
45
+
46
+ def self.available_options
47
+ [
48
+ FastlaneCore::ConfigItem.new(
49
+ key: :xcodeproj,
50
+ env_name: "FL_SUPPRESS_TESTS_XCODE_PROJECT",
51
+ description: "The file path to the Xcode project file to modify",
52
+ verify_block: proc do |path|
53
+ UI.user_error!("Error: Xcode project file path not given!") unless path and !path.empty?
54
+ UI.user_error!("Error: Xcode project '#{path}' not found!") unless Dir.exist?(path)
55
+ end
56
+ ),
57
+ FastlaneCore::ConfigItem.new(
58
+ key: :tests,
59
+ env_name: "FL_SUPPRESS_TESTS_TESTS_TO_SUPPRESS",
60
+ description: "A list of tests to suppress",
61
+ verify_block: proc do |tests|
62
+ UI.user_error!("Error: no tests were given to suppress!") unless tests and !tests.empty?
63
+ tests.each do |test_identifier|
64
+ is_valid_test_identifier = %r{^[a-zA-Z][a-zA-Z0-9]+\/[a-zA-Z][a-zA-Z0-9]+(\/test[a-zA-Z0-9]+)?$} =~ test_identifier
65
+ unless is_valid_test_identifier
66
+ UI.user_error!("Error: invalid test identifier '#{test_identifier}'. It must be in the format of 'Testable/TestSuiteToSuppress' or 'Testable/TestSuiteToSuppress/testToSuppress'")
67
+ end
68
+ end
69
+ end,
70
+ type: Array
71
+ ),
72
+ FastlaneCore::ConfigItem.new(
73
+ key: :scheme,
74
+ optional: true,
75
+ env_name: "FL_SUPPRESS_TESTS_SCHEME_TO_UPDATE",
76
+ description: "The Xcode scheme where the tests should be suppressed",
77
+ verify_block: proc do |scheme_name|
78
+ UI.user_error!("Error: Xcode Scheme '#{scheme_name}' is not valid!") if scheme_name and scheme_name.empty?
79
+ end
80
+ )
81
+ ]
82
+ end
83
+
84
+ def self.authors
85
+ ["lyndsey-ferguson/@lyndseydf"]
86
+ end
87
+
88
+ def self.is_supported?(platform)
89
+ platform == :ios
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,102 @@
1
+ module Fastlane
2
+ module Actions
3
+ class SuppressTestsFromJunitAction < Action
4
+ def self.run(params)
5
+ project_path = params[:xcodeproj]
6
+ scheme = params[:scheme]
7
+
8
+ scheme_filepaths = Dir.glob("#{project_path}/{xcshareddata,xcuserdata}/**/xcschemes/#{scheme || '*'}.xcscheme")
9
+ if scheme_filepaths.length.zero?
10
+ UI.user_error!("Error: cannot find any scheme named #{scheme}") unless scheme.nil?
11
+ UI.user_error!("Error: cannot find any schemes in the Xcode project")
12
+ end
13
+
14
+ testables = Hash.new([])
15
+ desired_passed_status = (params[:suppress_type] == :passing)
16
+
17
+ report = ::TestCenter::Helper::XcodeJunit::Report.new(params[:junit])
18
+
19
+ report.testables.each do |testable|
20
+ testables[testable.name] = []
21
+ testable.testsuites.each do |testsuite|
22
+ testsuite.testcases.each do |testcase|
23
+ if testcase.passed? == desired_passed_status
24
+ testables[testable.name] << testcase.skipped_test
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ scheme_filepaths.each do |scheme_filepath|
31
+ is_dirty = false
32
+ xcscheme = Xcodeproj::XCScheme.new(scheme_filepath)
33
+
34
+ xcscheme.test_action.testables.each do |testable|
35
+ buildable_name = testable.buildable_references[0].buildable_name
36
+ testables[buildable_name].each do |skipped_test|
37
+ testable.add_skipped_test(skipped_test)
38
+ is_dirty = true
39
+ end
40
+ end
41
+ xcscheme.save! if is_dirty
42
+ end
43
+ end
44
+
45
+ #####################################################
46
+ # @!group Documentation
47
+ #####################################################
48
+
49
+ def self.description
50
+ "Uses a junit xml report file to suppress either passing or failing tests in an Xcode Scheme"
51
+ end
52
+
53
+ def self.available_options
54
+ [
55
+ FastlaneCore::ConfigItem.new(
56
+ key: :xcodeproj,
57
+ env_name: "FL_SUPPRESS_TESTS_FROM_JUNIT_XCODE_PROJECT",
58
+ description: "The file path to the Xcode project file to modify",
59
+ verify_block: proc do |path|
60
+ UI.user_error!("Error: Xcode project file path not given!") unless path and !path.empty?
61
+ UI.user_error!("Error: Xcode project '#{path}' not found!") unless Dir.exist?(path)
62
+ end
63
+ ),
64
+ FastlaneCore::ConfigItem.new(
65
+ key: :junit,
66
+ env_name: "FL_SUPPRESS_TESTS_FROM_JUNIT_JUNIT_REPORT",
67
+ description: "The junit xml report file from which to collect the tests to suppress",
68
+ verify_block: proc do |path|
69
+ UI.user_error!("Error: cannot find the junit xml report file '#{path}'") unless File.exist?(path)
70
+ end
71
+ ),
72
+ FastlaneCore::ConfigItem.new(
73
+ key: :scheme,
74
+ optional: true,
75
+ env_name: "FL_SUPPRESS_TESTS_FROM_JUNIT_SCHEME_TO_UPDATE",
76
+ description: "The Xcode scheme where the tests should be suppressed",
77
+ verify_block: proc do |scheme_name|
78
+ UI.user_error!("Error: Xcode Scheme '#{scheme_name}' is not valid!") if scheme_name and scheme_name.empty?
79
+ end
80
+ ),
81
+ FastlaneCore::ConfigItem.new(
82
+ key: :suppress_type,
83
+ type: Symbol,
84
+ env_name: "FL_SUPPRESS_TESTS_FROM_JUNIT_SUPPRESS_TYPE",
85
+ description: "Tests to suppress are either :failed or :passing",
86
+ verify_block: proc do |type|
87
+ UI.user_error!("Error: suppress type ':#{type}' is invalid! Only :failed or :passing are valid types") unless %i[failed passing].include?(type)
88
+ end
89
+ )
90
+ ]
91
+ end
92
+
93
+ def self.authors
94
+ ["lyndsey-ferguson/@lyndseydf"]
95
+ end
96
+
97
+ def self.is_supported?(platform)
98
+ platform == :ios
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,72 @@
1
+ module Fastlane
2
+ module Actions
3
+ class SuppressedTestsAction < Action
4
+ require 'set'
5
+
6
+ def self.run(params)
7
+ project_path = params[:xcodeproj]
8
+ scheme = params[:scheme]
9
+
10
+ scheme_filepaths = Dir.glob("#{project_path}/{xcshareddata,xcuserdata}/**/xcschemes/#{scheme || '*'}.xcscheme")
11
+ if scheme_filepaths.length.zero?
12
+ UI.user_error!("Error: cannot find any scheme named #{scheme}") unless scheme.nil?
13
+ UI.user_error!("Error: cannot find any schemes in the Xcode project")
14
+ end
15
+
16
+ skipped_tests = Set.new
17
+ scheme_filepaths.each do |scheme_filepath|
18
+ xcscheme = Xcodeproj::XCScheme.new(scheme_filepath)
19
+ xcscheme.test_action.testables.each do |testable|
20
+ buildable_name = testable.buildable_references[0]
21
+ .buildable_name
22
+
23
+ buildable_name = File.basename(buildable_name, '.xctest')
24
+ testable.skipped_tests.map do |skipped_test|
25
+ skipped_tests.add("#{buildable_name}/#{skipped_test.identifier}")
26
+ end
27
+ end
28
+ end
29
+ skipped_tests.to_a
30
+ end
31
+
32
+ #####################################################
33
+ # @!group Documentation
34
+ #####################################################
35
+
36
+ def self.description
37
+ "Retrieves a list of tests that are suppressed in a specific or all Xcode Schemes in a project"
38
+ end
39
+
40
+ def self.available_options
41
+ [
42
+ FastlaneCore::ConfigItem.new(
43
+ key: :xcodeproj,
44
+ env_name: "FL_SUPPRESSED_TESTS_XCODE_PROJECT",
45
+ description: "The file path to the Xcode project file to read the skipped tests from",
46
+ verify_block: proc do |path|
47
+ UI.user_error!("Error: Xcode project file path not given!") unless path and !path.empty?
48
+ UI.user_error!("Error: Xcode project '#{path}' not found!") unless Dir.exist?(path)
49
+ end
50
+ ),
51
+ FastlaneCore::ConfigItem.new(
52
+ key: :scheme,
53
+ optional: true,
54
+ env_name: "FL_SUPPRESSED_TESTS_SCHEME_TO_UPDATE",
55
+ description: "The Xcode scheme where the suppressed tests may be",
56
+ verify_block: proc do |scheme_name|
57
+ UI.user_error!("Error: Xcode Scheme '#{scheme_name}' is not valid!") if scheme_name and scheme_name.empty?
58
+ end
59
+ )
60
+ ]
61
+ end
62
+
63
+ def self.authors
64
+ ["lyndsey-ferguson/@lyndseydf"]
65
+ end
66
+
67
+ def self.is_supported?(platform)
68
+ platform == :ios
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,59 @@
1
+ module Fastlane
2
+ module Actions
3
+ class TestsFromJunitAction < Action
4
+ def self.run(params)
5
+ report = ::TestCenter::Helper::XcodeJunit::Report.new(params[:junit])
6
+ passing = []
7
+ failed = []
8
+ report.testables.each do |testable|
9
+ testable.testsuites.each do |testsuite|
10
+ testsuite.testcases.each do |testcase|
11
+ if testcase.passed?
12
+ passing << testcase.identifier
13
+ else
14
+ failed << testcase.identifier
15
+ end
16
+ end
17
+ end
18
+ end
19
+ {
20
+ failed: failed,
21
+ passing: passing
22
+ }
23
+ end
24
+
25
+ #####################################################
26
+ # @!group Documentation
27
+ #####################################################
28
+
29
+ def self.description
30
+ "Retrieves the failing and passing tests as reported in a junit xml file"
31
+ end
32
+
33
+ def self.available_options
34
+ [
35
+ FastlaneCore::ConfigItem.new(
36
+ key: :junit,
37
+ env_name: "FL_SUPPRESS_TESTS_FROM_JUNIT_JUNIT_REPORT", # The name of the environment variable
38
+ description: "The junit xml report file from which to collect the tests to suppress",
39
+ verify_block: proc do |path|
40
+ UI.user_error!("Error: cannot find the junit xml report file '#{path}'") unless File.exist?(path)
41
+ end
42
+ )
43
+ ]
44
+ end
45
+
46
+ def self.return_value
47
+ "A Hash with an Array of :passing and :failed tests"
48
+ end
49
+
50
+ def self.authors
51
+ ["lyndsey-ferguson/lyndseydf"]
52
+ end
53
+
54
+ def self.is_supported?(platform)
55
+ platform == :ios
56
+ end
57
+ end
58
+ end
59
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-retry_tests
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.8
4
+ version: 1.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gloria Chow
@@ -180,6 +180,13 @@ extra_rdoc_files: []
180
180
  files:
181
181
  - LICENSE
182
182
  - README.md
183
+ - lib/fastlane/plugin/retry_tests.rb
184
+ - lib/fastlane/plugin/retry_tests/actions/collate_junit_reports.rb
185
+ - lib/fastlane/plugin/retry_tests/actions/multi_scan.rb
186
+ - lib/fastlane/plugin/retry_tests/actions/suppress_tests.rb
187
+ - lib/fastlane/plugin/retry_tests/actions/suppress_tests_from_junit.rb
188
+ - lib/fastlane/plugin/retry_tests/actions/suppressed_tests.rb
189
+ - lib/fastlane/plugin/retry_tests/actions/tests_from_junit.rb
183
190
  homepage: https://github.com/kouzoh/fastlane-plugin-retry_tests
184
191
  licenses:
185
192
  - MIT