Class: Fastlane::Actions::CollateHtmlReportsAction

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

Documentation collapse

Class Method Summary collapse

Class Method Details

.authorsObject



181
182
183
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 181

def self.authors
  ["lyndsey-ferguson/@lyndseydf"]
end

.available_optionsObject



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 140

def self.available_options
  [
    FastlaneCore::ConfigItem.new(
      key: :reports,
      env_name: 'COLLATE_HTML_REPORTS_REPORTS',
      description: 'An array of HTML reports to collate. The first report is used as the base into which other reports are merged in',
      optional: false,
      type: Array,
      verify_block: proc do |reports|
        UI.user_error!('No HTML report files found') if reports.empty?
        reports.each do |report|
          UI.user_error!("Error: HTML report not found: '#{report}'") unless File.exist?(report)
        end
      end
    ),
    FastlaneCore::ConfigItem.new(
      key: :collated_report,
      env_name: 'COLLATE_HTML_REPORTS_COLLATED_REPORT',
      description: 'The final HTML report file where all testcases will be merged into',
      optional: true,
      default_value: 'result.html',
      type: String
    )
  ]
end

.collate_testresult_details(target_testresult, testresult) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 65

def self.collate_testresult_details(target_testresult, testresult)
  target_testdetails = details_for_testresult(target_testresult)
  testdetails = details_for_testresult(testresult)

  if target_testdetails
    if testdetails
      target_testresult.parent.replace_child(target_testdetails, testdetails)
    else
      target_testresult.parent.delete_element(target_testdetails)
    end
  end
end

.collate_testresults(target_testsuite, target_testresult, testresult) ⇒ Object



56
57
58
59
60
61
62
63
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 56

def self.collate_testresults(target_testsuite, target_testresult, testresult)
  if target_testresult
    collate_testresult_details(target_testresult, testresult)
    target_testresult.parent.replace_child(target_testresult, testresult)
  else
    target_testsuite << testresult
  end
end

.collate_testsuite(target_testsuite, testsuite) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 42

def self.collate_testsuite(target_testsuite, testsuite)
  if target_testsuite
    testcases = testcases_from_testsuite(testsuite)
    testcases.each do |testcase|
      testresult = testcase.parent.parent
      target_testresult = testcase_from_testsuite(target_testsuite, testcase.text)
      collate_testresults(target_testsuite, target_testresult, testresult)
    end
  else
    testable = testsuite.parent
    testable << testsuite
  end
end

.descriptionObject



125
126
127
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 125

def self.description
  "Combines and combines tests from multiple html report files"
end

.detailsObject



129
130
131
132
133
134
135
136
137
138
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 129

def self.details
  "The first HTML report is used as the base report. Testcases " \
  "from other reports are added if they do not already exist, or " \
  "if the testcases already exist, they are replaced." \
  "" \
  "This is done because it is assumed that fragile tests, when " \
  "re-run will often succeed due to less interference from other " \
  "tests and the subsequent HTML reports will have more passed tests." \
  ""
end

.details_for_testresult(testresult) ⇒ Object



110
111
112
113
114
115
116
117
118
119
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 110

def self.details_for_testresult(testresult)
  testcase = REXML::XPath.first(testresult, ".//*[contains(@class, 'title')]")

  xpath = "../*[" \
          "contains(@class, 'details') and " \
          "contains(@class, 'failing') and " \
          "contains(@class, '#{testcase.text}')]"

  REXML::XPath.first(testresult, xpath)
end

.example_codeObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 166

def self.example_code
  [
    "
    UI.important(
      'example: ' \\
      'collate the html reports to a temporary file \'result.html\''
    )
    collate_html_reports(
      reports: Dir['./spec/fixtures/*.html'],
      collated_report: File.join(Dir.mktmpdir, 'result.html')
    )
    "
  ]
end

.is_supported?(platform) ⇒ Boolean

Returns:

  • (Boolean)


185
186
187
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 185

def self.is_supported?(platform)
  platform == :ios
end

.run(params) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 4

def self.run(params)
  report_filepaths = params[:reports]
  if report_filepaths.size == 1
    FileUtils.cp(report_filepaths[0], params[:collated_report])
  else
    reports = report_filepaths.map { |report_filepath| REXML::Document.new(File.new(report_filepath)) }

    # copy any missing testsuites
    target_report = reports.shift
    reports.each do |report|
      report.elements.each("//section[contains(@class, 'test-suite')]") do |testsuite|
        collate_testsuite(testsuite_from_report(target_report, testsuite), testsuite)
      end
    end
    update_testsuites_status(target_report)
    update_test_counts(target_report)

    FileUtils.mkdir_p(File.dirname(params[:collated_report]))

    File.open(params[:collated_report], 'w') do |f|
      target_report.write(f, 2)
    end
  end
end

.testcase_from_testsuite(testsuite, testcase_name) ⇒ Object



38
39
40
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 38

def self.testcase_from_testsuite(testsuite, testcase_name)
  REXML::XPath.first(testsuite, "*[contains(@class, 'test')]//*[text()='#{testcase_name}']/../..")
end

.testcases_from_testsuite(testsuite) ⇒ Object



34
35
36
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 34

def self.testcases_from_testsuite(testsuite)
  REXML::XPath.match(testsuite, ".//*[contains(@class, 'tests')]//*[contains(@class, 'test')]//*[contains(@class, 'title')]")
end

.testsuite_from_report(report, testsuite) ⇒ Object



29
30
31
32
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 29

def self.testsuite_from_report(report, testsuite)
  testsuite_name = testsuite.attributes['id']
  REXML::XPath.first(report, "//section[contains(@class, 'test-suite') and @id='#{testsuite_name}']")
end

.update_test_counts(report) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 91

def self.update_test_counts(report)
  tests_xpath = "//*[contains(@class, 'tests')]//*[contains(@class, 'test')]//*[contains(@class, 'title')]"
  tests = REXML::XPath.match(report, tests_xpath)

  failing_tests_xpath = "//*[contains(@class, 'tests')]//*[" \
          "contains(@class, 'details') and " \
          "contains(@class, 'failing')]"

  test_failures = REXML::XPath.match(report, failing_tests_xpath)
  test_count = REXML::XPath.first(report, ".//*[@id='test-count']/span")
  if test_count
    test_count.text = tests.size
  end
  fail_count = REXML::XPath.first(report, ".//*[@id='fail-count']/span")
  if fail_count
    fail_count.text = test_failures.size
  end
end

.update_testsuites_status(report) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/fastlane/plugin/test_center/actions/collate_html_reports.rb', line 78

def self.update_testsuites_status(report)
  report.elements.each("//section[contains(@class, 'test-suite')]") do |testsuite|
    failing_tests_xpath = "./*[contains(@class, 'tests')]//*[" \
          "contains(@class, 'failing')]"

    class_attributes = testsuite.attributes['class']
    test_failures = REXML::XPath.match(testsuite, failing_tests_xpath)
    test_status = test_failures.size.zero? ? 'passing' : 'failing'

    testsuite.attributes['class'] = class_attributes.sub('failing', test_status)
  end
end