Class: Fastlane::Actions::SetupFragileTestsForRescanAction

Inherits:
Action
  • Object
show all
Defined in:
lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb

Class Method Summary collapse

Class Method Details

.authorsObject



100
101
102
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 100

def self.authors
  ["Lyndsey Ferguson"]
end

.available_optionsObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 116

def self.available_options
  [
    FastlaneCore::ConfigItem.new(
      key: :project_path,
      env_name: "SETUP_FRAGILE_TESTS_FOR_RESCAN_PROJECT_PATH",
      description: "The file path to the Xcode project file",
      verify_block: proc do |value|
        UI.user_error!('No project file for SetupFragileTestsForRescanAction given, pass using `project_path: \'path/to/project.xcodeproj\'`') if value.nil? || value.empty?
        UI.user_error!("SetupFragileTestsForRescanAction cannot find project file at '#{value}'") unless Dir.exist?(value)
        UI.user_error!("The project '#{value}' is not a valid Xcode project") unless File.extname(value).casecmp('.xcodeproj').zero?
        UI.user_error!("The Xcode project at '#{value}' is invalid: missing the project.pbxproj file") unless File.exist?("#{value}/project.pbxproj")
      end,
      type: String
    ),
    FastlaneCore::ConfigItem.new(
      key: :scheme,
      env_name: "SETUP_FRAGILE_TESTS_FOR_RESCAN_SCHEME",
      description: "The Xcode scheme used to manage the tests",
      verify_block: proc do |value|
        UI.user_error!('No scheme for SetupFragileTestsForRescanAction given, pass using `scheme: \'scheme name\'`') if value.nil? || value.empty?
      end,
      type: String
    ),
    FastlaneCore::ConfigItem.new(
      key: :report_filepath,
      env_name: "SETUP_FRAGILE_TESTS_FOR_RESCAN_TEST_REPORT_FILEPATH",
      description: "The file path to the test report file",
      verify_block: proc do |value|
        UI.user_error!('No test report file for SetupFragileTestsForRescanAction given, pass using `report_filepath: \'path/to/report.xml\'`') if value.nil? || value.empty?
        UI.user_error!("SetupFragileTestsForRescanAction cannot find test report file at '#{value}'") unless File.exist?(value)
      end,
      type: String
    )
  ]
end

.categoryObject



112
113
114
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 112

def self.category
  :deprecated
end

.deprecated_notesObject



108
109
110
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 108

def self.deprecated_notes
  "This action is deprecated in favor of the suppress_tests_from_junit and multi_scan actions shipped with the test_center plugin"
end

.descriptionObject



92
93
94
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 92

def self.description
  "Suppress stabile tests so that 'scan' can run the fragile tests again"
end

.detailsObject



104
105
106
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 104

def self.details
  "Reviews the scan report file to find the passing tests in an Xcode project and then suppresses the tests in the test-suite's source file."
end

.is_supported?(platform) ⇒ Boolean

Returns:

  • (Boolean)


152
153
154
155
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 152

def self.is_supported?(platform)
  STDOUT.puts "platform: #{platform}"
  i[ios mac].include?(platform)
end

.return_valueObject



96
97
98
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 96

def self.return_value
  "A hash of the tests with arrays :passed_tests and :failed_tests which can be used with scan's :skip_testing and :test_only options"
end

.run(params) ⇒ Object



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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 9

def self.run(params)
  report_file = File.open(params[:report_filepath]) { |f| REXML::Document.new(f) }
  UI.user_error!("Malformed XML test report file given") if report_file.root.nil?
  UI.user_error!("Valid XML file is not an Xcode test report") if report_file.get_elements('testsuites').empty?

  result = {
    passed_tests: [],
    failed_tests: []
  }

  # remove all testcases that failed from the report file
  # so that our subsequent steps here can just focus on finding
  # passing testcases to suppress
  report_file.elements.each('*/testsuite/testcase/failure') do |failure_element|
    testcase = failure_element.parent
    testsuite_element = testcase.parent

    result[:failed_tests] << xcodebuild_test_identifier(testsuite_element.parent, testcase)
    testsuite_element.delete_element testcase
  end

  scheme = xcscheme(params)
  is_dirty = false
  summary = []
  report_file.elements.each('testsuites') do |testsuites|
    buildable_name = testsuites.attributes['name']

    test_action = scheme.test_action
    testable = test_action.testables.find { |t| t.buildable_references[0].buildable_name == buildable_name }
    raise "Unable to find testable named #{buildable_name}" if testable.nil?

    testsuites.elements.each('testsuite/testcase') do |testcase|
      skipped_test = Xcodeproj::XCScheme::TestAction::TestableReference::SkippedTest.new
      skipped_test.identifier = xctest_identifier(testcase)
      testable.add_skipped_test(skipped_test)
      result[:passed_tests] << xcodebuild_test_identifier(testsuites, testcase)
      is_dirty = true
      summary << [skipped_test.identifier]
    end
  end
  if is_dirty
    scheme.save!
    table = Terminal::Table.new(
      title: 'setup_fragile_tests_for_rescan suppressed the following tests',
      rows: summary
    )
    UI.success("\n#{table}")
  else
    UI.error('No passing tests found for suppression')
  end
  result
end

.xcodebuild_test_identifier(testsuites, testcase) ⇒ Object



85
86
87
88
89
90
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 85

def self.xcodebuild_test_identifier(testsuites, testcase)
  # remove '.xctest' from the buildable_name
  buildable_name = File.basename(testsuites.attributes['name'], '.*')
  test_identifier = xctest_identifier(testcase).chomp('()')
  "#{buildable_name}/#{test_identifier}"
end

.xcscheme(params) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 62

def self.xcscheme(params)
  project_path = params[:project_path]
  scheme_name = params[:scheme]

  scheme_filepath = File.join(Xcodeproj::XCScheme.shared_data_dir(project_path), "#{scheme_name}.xcscheme")
  unless File.exist?(scheme_filepath)
    scheme_filepath = File.join(Xcodeproj::XCScheme.user_data_dir(project_path), "#{scheme_name}.xcscheme")
  end
  UI.user_error!("Scheme '#{scheme_name}' does not exist in Xcode project found at '#{project_path}'") unless File.exist?(scheme_filepath)

  Xcodeproj::XCScheme.new(scheme_filepath)
end

.xctest_identifier(testcase) ⇒ Object



75
76
77
78
79
80
81
82
83
# File 'lib/fastlane/plugin/setup_fragile_tests_for_rescan/actions/setup_fragile_tests_for_rescan_action.rb', line 75

def self.xctest_identifier(testcase)
  testcase_class = testcase.attributes['classname']
  testcase_testmethod = testcase.attributes['name']

  is_swift = testcase_class.include?('.')
  testcase_class.gsub!(/.*\./, '')
  testcase_testmethod << '()' if is_swift
  "#{testcase_class}/#{testcase_testmethod}"
end