diff options
Diffstat (limited to 'lib/gitlab/ci/parsers/test/junit.rb')
-rw-r--r-- | lib/gitlab/ci/parsers/test/junit.rb | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/gitlab/ci/parsers/test/junit.rb b/lib/gitlab/ci/parsers/test/junit.rb index 5746f38ae5b..50cd703da4a 100644 --- a/lib/gitlab/ci/parsers/test/junit.rb +++ b/lib/gitlab/ci/parsers/test/junit.rb @@ -8,12 +8,17 @@ module Gitlab JunitParserError = Class.new(Gitlab::Ci::Parsers::ParserError) ATTACHMENT_TAG_REGEX = /\[\[ATTACHMENT\|(?<path>.+?)\]\]/.freeze - def parse!(xml_data, test_suite, **args) + def parse!(xml_data, test_suite, job:) root = Hash.from_xml(xml_data) + total_parsed = 0 + max_test_cases = job.max_test_cases_per_report all_cases(root) do |test_case| - test_case = create_test_case(test_case, args) + test_case = create_test_case(test_case, test_suite, job) test_suite.add_test_case(test_case) + total_parsed += 1 + + ensure_test_cases_limited!(total_parsed, max_test_cases) end rescue Nokogiri::XML::SyntaxError => e test_suite.set_suite_error("JUnit XML parsing failed: #{e}") @@ -23,6 +28,12 @@ module Gitlab private + def ensure_test_cases_limited!(total_parsed, limit) + return unless limit > 0 && total_parsed > limit + + raise JunitParserError.new("number of test cases exceeded the limit of #{limit}") + end + def all_cases(root, parent = nil, &blk) return unless root.present? @@ -33,20 +44,24 @@ module Gitlab all_cases(node['testsuites'], root, &blk) unless parent # we require at least one level of testsuites or testsuite - each_case(node['testcase'], &blk) if parent + each_case(node['testcase'], node['name'], &blk) if parent # we allow multiple nested 'testsuite' (eg. PHPUnit) all_cases(node['testsuite'], root, &blk) end end - def each_case(testcase, &blk) + def each_case(testcase, testsuite_name, &blk) return unless testcase.present? - [testcase].flatten.compact.map(&blk) + [testcase].flatten.compact.each do |tc| + tc['suite_name'] = testsuite_name + + yield(tc) + end end - def create_test_case(data, args) + def create_test_case(data, test_suite, job) if data.key?('failure') status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED system_output = data['failure'] @@ -63,6 +78,7 @@ module Gitlab end ::Gitlab::Ci::Reports::TestCase.new( + suite_name: data['suite_name'] || test_suite.name, classname: data['classname'], name: data['name'], file: data['file'], @@ -70,10 +86,14 @@ module Gitlab status: status, system_output: system_output, attachment: attachment, - job: args.fetch(:job) + job: job ) end + def suite_name(parent, test_suite) + parent.dig('testsuite', 'name') || test_suite.name + end + def attachment_path(data) return unless data |