Skip to content

Commit

Permalink
Removed nokogiri dependency.
Browse files Browse the repository at this point in the history
  • Loading branch information
dyang committed Apr 17, 2017
1 parent 4a0ec23 commit ba4df49
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 54 deletions.
4 changes: 0 additions & 4 deletions fastlane-plugin-merge_junit_report.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@ Gem::Specification.new do |spec|
# Don't add a dependency to fastlane or fastlane_re
# since this would cause a circular dependency

# spec.add_dependency 'your-dependency', '~> 1.0.0'
spec.add_dependency 'nokogiri', '~> 1.7'

spec.add_development_dependency 'pry'
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rubocop'
spec.add_development_dependency 'fastlane', '>= 2.14.2'
spec.add_development_dependency 'equivalent-xml'
spec.add_development_dependency 'simplecov'
spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0.0'
end
2 changes: 1 addition & 1 deletion lib/fastlane/plugin/merge_junit_report.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'fastlane_core'
require 'fastlane/plugin/merge_junit_report/version'
require 'fastlane/plugin/merge_junit_report/merger'
require 'nokogiri'
require 'rexml/document'

module Fastlane
module MergeJunitReport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ def self.run(params)
)
input_files = params[:input_files]

xml_docs = input_files.map { |file| Nokogiri::XML(File.open(file)) }
xml_docs = input_files.map { |file| REXML::Document.new(File.new(file)) }
merger = Fastlane::Plugin::MergeJunitReport::Merger.new(xml_docs)
merged = merger.merge

# write to output_file
output_file = File.absolute_path(params[:output_file])
FileUtils.mkdir_p(File.dirname(output_file))
File.write(output_file, merged.to_xml)

File.open(output_file, 'w') { |f| merged.write(f, 2) }
UI.success("Reports merged to #{output_file} successfully")
end

Expand All @@ -30,10 +29,6 @@ def self.authors
['Derek Yang']
end

def self.return_value
# If your method provides a return value, you can describe here what it does
end

def self.available_options
[
FastlaneCore::ConfigItem.new(key: :input_files,
Expand Down
35 changes: 19 additions & 16 deletions lib/fastlane/plugin/merge_junit_report/merger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,31 @@ module MergeJunitReport
# Merge several junit reports into one single report
class Merger
# Initializes an instance of Merger
# @param [Array<Nokogiri::XML::Document>] junit reports the junit reports to merge from
# @param [Array<REXML::Document>] junit reports the junit reports to merge from
# @return [Merger]
def initialize(reports)
@reports = reports
end

# Merges reports passed in via constructor
# @return [Nokogiri::XML::Document] merged junit report
# @return [REXML::Document] merged junit report
def merge
baseline = @reports.first

@reports.drop(1).each do |report|
report.xpath('//testsuite').each do |suite_to_merge|
suite_name = suite_to_merge.attr('name')
baseline_suite = baseline.xpath("//testsuite[@name='#{suite_name}']")
report.elements.each('//testsuite') do |suite_to_merge|
suite_name = suite_to_merge.attributes['name']
baseline_suite = REXML::XPath.first(baseline, "//testsuite[@name='#{suite_name}']")

next unless baseline_suite
suite_to_merge.xpath('testcase').each do |case_to_merge|
classname = case_to_merge.attr('classname')
name = case_to_merge.attr('name')
baseline_case = baseline_suite.at_xpath("testcase[@name='#{name}' and @classname='#{classname}']")
baseline_case.swap(case_to_merge.to_xml) if baseline_case
suite_to_merge.elements.each('testcase') do |case_to_merge|
classname = case_to_merge.attributes['classname']
name = case_to_merge.attributes['name']
baseline_case = REXML::XPath.first(baseline_suite, "testcase[@name='#{name}' and @classname='#{classname}']")
# Replace baseline_case with case_to_merge
if baseline_case
baseline_case.parent.insert_after(baseline_case, case_to_merge)
baseline_case.parent.delete_element(baseline_case)
end
end
end
end
Expand All @@ -36,20 +39,20 @@ def merge

def recalculate_failures(baseline)
total_failures = 0
baseline.xpath('//testsuite').each do |suite|
baseline.elements.each('//testsuite') do |suite|
failures = 0
suite.xpath('testcase').each { |testcase| failures += 1 unless testcase.xpath('failure').empty? }
suite.elements.each('testcase') { |testcase| failures += 1 unless REXML::XPath.match(testcase, 'failure').empty? }
remove_or_update_failures(failures, suite)
total_failures += failures
end
remove_or_update_failures(total_failures, baseline.at_xpath('/testsuites'))
remove_or_update_failures(total_failures, REXML::XPath.first(baseline, '/testsuites'))
end

def remove_or_update_failures(failures, node)
if failures.zero?
node.remove_attribute('failures')
node.delete_attribute('failures')
else
node['failures'] = failures.to_s
node.attributes['failures'] = failures.to_s
end
end

Expand Down
7 changes: 5 additions & 2 deletions spec/merge_junit_report_action_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@
expect(File.exist?(output_file)).to be true
end

it 'should not insert xml declaration when saving to output file' do
it 'should not duplicate xml declaration when saving to output file (nokogiri config test)' do
Fastlane::FastFile.new.parse("lane :merge do
merge_junit_report(input_files: ['../spec/fixtures/report0.xml', '../spec/fixtures/report1.xml'])
end").runner.execute(:merge)

File.open(default_output) { |f| expect(f.readline).not_to eql('<?xml version="1.0"?>\n') }
File.open(default_output) do |file|
file.readline
expect(file.readline).not_to eql('<?xml version="1.0"?>\n')
end
end
end
end
53 changes: 29 additions & 24 deletions spec/merger_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require 'nokogiri'
require 'equivalent-xml'
require 'rexml/document'

describe Fastlane::Plugin::MergeJunitReport::Merger do
report0 = "
Expand All @@ -21,52 +20,58 @@

describe '#merge' do
it 'should merge testsuites with name and tests' do
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([Nokogiri::XML(report0), Nokogiri::XML(report1)])
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([REXML::Document.new(report0), REXML::Document.new(report1)])
merged_report_doc = merger.merge
expect(merged_report_doc.root.attr('name')).to eql('FooUITests.xctest')
expect(merged_report_doc.root.attr('tests')).to eql('3')
expect(merged_report_doc.root.attr('failures')).to be nil
expect(merged_report_doc.root.attributes['name']).to eql('FooUITests.xctest')
expect(merged_report_doc.root.attributes['tests']).to eql('3')
expect(merged_report_doc.root.attributes['failures']).to be nil
end

it 'should recalculate failures after merging testsuites' do
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([Nokogiri::XML(report0), Nokogiri::XML(report1)])
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([REXML::Document.new(report0), REXML::Document.new(report1)])
merged_report_doc = merger.merge
expect(merged_report_doc.root.attr('failures')).to be nil
expect(merged_report_doc.root.attributes['failures']).to be nil
end

it 'should merge testcases' do
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([Nokogiri::XML(report0), Nokogiri::XML(report1)])
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([REXML::Document.new(report0), REXML::Document.new(report1)])
merged_report = merger.merge
testcases = merged_report.xpath('//testsuite/testcase')
testcases = REXML::XPath.match(merged_report, '//testsuite/testcase')

expect(testcases.size).to eql(3)

expect(testcases[0].attr('classname')).to eql('FooUITests.FooUITests')
expect(testcases[0].attr('name')).to eql('test1')
expect(testcases[0].attr('time')).to eql('6.825')
expect(testcases[0].attributes['classname']).to eql('FooUITests.FooUITests')
expect(testcases[0].attributes['name']).to eql('test1')
expect(testcases[0].attributes['time']).to eql('6.825')

expect(testcases[1].attr('classname')).to eql('FooUITests.FooUITests')
expect(testcases[1].attr('name')).to eql('test2')
expect(testcases[1].attr('time')).to eql('7.679')
expect(testcases[1].attributes['classname']).to eql('FooUITests.FooUITests')
expect(testcases[1].attributes['name']).to eql('test2')
expect(testcases[1].attributes['time']).to eql('7.679')

expect(testcases[2].attr('classname')).to eql('FooUITests.FooUITests')
expect(testcases[2].attr('name')).to eql('test3')
expect(testcases[2].attr('time')).to eql('9.125')
expect(testcases[2].attributes['classname']).to eql('FooUITests.FooUITests')
expect(testcases[2].attributes['name']).to eql('test3')
expect(testcases[2].attributes['time']).to eql('9.125')
expect(testcases[2].children.size).to eql(0)
end

it 'should recalculate failures after merge' do
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([Nokogiri::XML(report0), Nokogiri::XML(report1)])
merger = Fastlane::Plugin::MergeJunitReport::Merger.new([REXML::Document.new(report0), REXML::Document.new(report1)])
merged_report = merger.merge
suite = merged_report.xpath('//testsuite').first
expect(suite.attr('failures')).to be nil
suite = REXML::XPath.first(merged_report, '//testsuite')
expect(suite.attributes['failures']).to be nil
end

it 'should yield the same report if just one report is given' do
original = Nokogiri::XML(report0)
original = REXML::Document.new(report0)
str_orig = ''
original.write(str_orig, 2)

merger = Fastlane::Plugin::MergeJunitReport::Merger.new([original])
merged_report = merger.merge
expect(merged_report).to be_equivalent_to(original)
str_merged = ''
merged_report.write(str_merged, 2)

expect(str_orig).to eql(str_merged)
end
end
end

0 comments on commit ba4df49

Please sign in to comment.