From fb71e16fe108055e283e97cf57662e407649e910 Mon Sep 17 00:00:00 2001 From: bmcorser Date: Thu, 21 May 2015 14:26:40 +0100 Subject: [PATCH 1/3] Handle XML namespaces --- xunitparser.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/xunitparser.py b/xunitparser.py index d72fe2b..07e5220 100644 --- a/xunitparser.py +++ b/xunitparser.py @@ -1,8 +1,16 @@ import math +import re import unittest from datetime import timedelta from xml.etree import ElementTree +TAG_RE = re.compile(r'(?P{.*})?(?P\w+)') + + +def get_tagname(tag): + match = re.search(TAG_RE, tag) + return match.group('name') + def to_timedelta(val): if val is None: @@ -142,7 +150,7 @@ def parse(self, source): def parse_root(self, root): ts = self.TS_CLASS() - if root.tag == 'testsuites': + if get_tagname(root.tag) == 'testsuites': for subroot in root: self.parse_testsuite(subroot, ts) else: @@ -165,17 +173,18 @@ def parse_root(self, root): return (ts, tr) def parse_testsuite(self, root, ts): - assert root.tag == 'testsuite' + assert get_tagname(root.tag) == 'testsuite' ts.name = root.attrib.get('name') ts.package = root.attrib.get('package') for el in root: - if el.tag == 'testcase': + tagname = get_tagname(el.tag) + if tagname == 'testcase': self.parse_testcase(el, ts) - if el.tag == 'properties': + if tagname == 'properties': self.parse_properties(el, ts) - if el.tag == 'system-out' and el.text: + if tagname == 'system-out' and el.text: ts.stdout = el.text.strip() - if el.tag == 'system-err' and el.text: + if tagname == 'system-err' and el.text: ts.stderr = el.text.strip() def parse_testcase(self, el, ts): @@ -186,10 +195,11 @@ def parse_testcase(self, el, ts): message = None text = None for e in el: + tagname = get_tagname(e.tag) # error takes over failure in JUnit 4 - if e.tag in ('failure', 'error', 'skipped'): + if tagname in ('failure', 'error', 'skipped'): tc = self.TC_CLASS(tc_classname, el.attrib['name']) - result = e.tag + result = tagname typename = e.attrib.get('type') # reuse old if empty @@ -198,9 +208,9 @@ def parse_testcase(self, el, ts): tc.seed(result, typename, message, text) tc.time = to_timedelta(el.attrib.get('time')) - if e.tag == 'system-out' and e.text: + if tagname == 'system-out' and e.text: tc.stdout = e.text.strip() - if e.tag == 'system-err' and e.text: + if tagname == 'system-err' and e.text: tc.stderr = e.text.strip() # add either the original "success" tc or a tc created by elements @@ -208,7 +218,7 @@ def parse_testcase(self, el, ts): def parse_properties(self, el, ts): for e in el: - if e.tag == 'property': + if get_tagname(e.tag) == 'property': assert e.attrib['name'] not in ts.properties ts.properties[e.attrib['name']] = e.attrib['value'] From d59a6e8770446b814b349f74d369a126d679411a Mon Sep 17 00:00:00 2001 From: bmcorser Date: Thu, 21 May 2015 14:34:37 +0100 Subject: [PATCH 2/3] Add test for namespaced XML --- test.py | 12 ++++++++++++ tests/casperjs.xml | 1 + 2 files changed, 13 insertions(+) create mode 100644 tests/casperjs.xml diff --git a/test.py b/test.py index 997664d..66d64aa 100644 --- a/test.py +++ b/test.py @@ -132,3 +132,15 @@ class Test8(X, TestCase): def test_bad_suite_time(self): assert self.tr.time is None + + +class TestNamespaced(TestCase): + + def setUp(self): + with open(os.path.join('tests', 'casperjs.xml')) as f: + self.ts, self.tr = parse(f) + + def test_nocrash(self): + 'We do not crash when the XML is namespaced, such as CasperJS results' + assert self.ts + assert self.tr diff --git a/tests/casperjs.xml b/tests/casperjs.xml new file mode 100644 index 0000000..b50a6e8 --- /dev/null +++ b/tests/casperjs.xml @@ -0,0 +1 @@ +".fffff" still did not exist in 5000ms \ No newline at end of file From 9e363e37b3729abeea821f46723dd148a72ff9a3 Mon Sep 17 00:00:00 2001 From: B M Corser Date: Tue, 1 Sep 2015 15:48:01 +0100 Subject: [PATCH 3/3] Patch for CI server --- xunitparser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xunitparser.py b/xunitparser.py index 07e5220..b514aba 100644 --- a/xunitparser.py +++ b/xunitparser.py @@ -219,7 +219,7 @@ def parse_testcase(self, el, ts): def parse_properties(self, el, ts): for e in el: if get_tagname(e.tag) == 'property': - assert e.attrib['name'] not in ts.properties + # assert e.attrib['name'] not in ts.properties # TODO: Care about this ts.properties[e.attrib['name']] = e.attrib['value']