From 186b310c767567f6f46e7fca45be2294b7aa7271 Mon Sep 17 00:00:00 2001 From: ganesann Date: Thu, 23 Mar 2017 23:07:08 +0000 Subject: [PATCH 1/6] xunit2subunit filter to convert xunitxml to subunit --- Makefile.am | 3 +- filters/xunit2subunit | 76 +++++++++++++++++++++++++++++++++++++++++++ setup.py | 1 + 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100755 filters/xunit2subunit diff --git a/Makefile.am b/Makefile.am index 10533487..b48b6a79 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,8 @@ dist_bin_SCRIPTS = \ filters/subunit2gtk \ filters/subunit2junitxml \ filters/subunit2pyunit \ - filters/tap2subunit + filters/tap2subunit \ + filters/xunit2subunit TESTS = $(check_PROGRAMS) diff --git a/filters/xunit2subunit b/filters/xunit2subunit new file mode 100755 index 00000000..a3466dbb --- /dev/null +++ b/filters/xunit2subunit @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# subunit: extensions to python unittest to get test results from subprocesses. +# Hewlett Packard Enterprise (c) 2017 +# +# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause +# license at the users choice. A copy of both licenses are available in the +# project source as Apache-2.0 and BSD. You may not use this file except in +# compliance with one of these two licences. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# license you chose for the specific language governing permissions and +# limitations under that license. +# + +"""A filter that reads a xunitXML stream and outputs a subunit stream. +""" + +import sys + +from subunit.v2 import StreamResultToBytes + +STATUS_CODES = frozenset([ + 'exists', + 'fail', + 'skip', + 'success', + 'uxsuccess', + 'xfail', +]) + +try: + import xunitparser +except ImportError: + sys.stderr.write("xunitparser (https://pypi.python.org/pypi/xunitparser)" + "is required for this filter.") + raise + +def xunit2subunit(xunitxml_input=sys.stdin, output=sys.stdout): + output = StreamResultToBytes(output) + output.startTestRun() + ts, tr = xunitparser.parse(xunitxml_input) + for tc in ts: + print vars(tc) + test_id = tc.methodname + test_metadata = None + test_status = None + if tc.good: + if tc.result == "skipped": + test_status = "skip" + else: + test_status = "success" + else: + test_status = "fail" + write_test(output, test_id, test_status, test_metadata) + output.stopTestRun() + +def write_test(output, test_id, test_status, metadatas): + write_status = output.status + kwargs = {} + if metadatas: + if 'tags' in metadatas: + tags = metadatas['tags'] + kwargs['test_tags'] = tags.split(',') + if 'attrs' in metadatas: + test_id = test_id + '[' + metadatas['attrs'] + ']' + kwargs['test_id'] = test_id + write_status(**kwargs) + if test_status in STATUS_CODES: + kwargs['test_status'] = test_status + write_status(**kwargs) + +if __name__ == '__main__': + sys.exit(xunit2subunit(sys.stdin, sys.stdout)) + diff --git a/setup.py b/setup.py index 54b1a324..56d2c923 100755 --- a/setup.py +++ b/setup.py @@ -78,6 +78,7 @@ def _get_version_from_file(filename, start_of_line, split_marker): 'filters/subunit2junitxml', 'filters/subunit2pyunit', 'filters/tap2subunit', + 'filters/xunit2subunit', ], **extra ) From 4a15ed13f69a46a6ed195d33461e858af514ddaf Mon Sep 17 00:00:00 2001 From: ganesann Date: Thu, 23 Mar 2017 23:07:08 +0000 Subject: [PATCH 2/6] xunit2subunit filter to convert xunitxml to subunit --- Makefile.am | 3 +- filters/xunit2subunit | 84 +++++++++++++++++++++++++++++++++++++++++++ setup.py | 1 + 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100755 filters/xunit2subunit diff --git a/Makefile.am b/Makefile.am index 10533487..b48b6a79 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,8 @@ dist_bin_SCRIPTS = \ filters/subunit2gtk \ filters/subunit2junitxml \ filters/subunit2pyunit \ - filters/tap2subunit + filters/tap2subunit \ + filters/xunit2subunit TESTS = $(check_PROGRAMS) diff --git a/filters/xunit2subunit b/filters/xunit2subunit new file mode 100755 index 00000000..35d8787f --- /dev/null +++ b/filters/xunit2subunit @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# subunit: extensions to python unittest to get test results from subprocesses. +# Hewlett Packard Enterprise (c) 2017 +# +# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause +# license at the users choice. A copy of both licenses are available in the +# project source as Apache-2.0 and BSD. You may not use this file except in +# compliance with one of these two licences. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# license you chose for the specific language governing permissions and +# limitations under that license. +# + +"""A filter that reads a xunitXML stream and outputs a subunit stream. +""" + +import datetime +import sys + +from subunit.iso8601 import UTC +from subunit.v2 import StreamResultToBytes + +STATUS_CODES = frozenset([ + 'exists', + 'fail', + 'skip', + 'success', + 'uxsuccess', + 'xfail', +]) + +try: + import xunitparser +except ImportError: + sys.stderr.write("xunitparser (https://pypi.python.org/pypi/xunitparser)" + "is required for this filter.") + raise + +def xunit2subunit(xunitxml_input=sys.stdin, output=sys.stdout): + output = StreamResultToBytes(output) + output.startTestRun() + ts, tr = xunitparser.parse(xunitxml_input) + for tc in ts: + test_id = tc.methodname + test_metadata = None + test_status = None + test_time = tc.time + if tc.good: + if tc.result == "skipped": + test_status = "skip" + else: + test_status = "success" + else: + test_status = "fail" + write_test(output, test_id, test_status, test_metadata, test_time) + output.stopTestRun() + +def write_test(output, test_id, test_status, metadatas, test_time): + write_status = output.status + kwargs = {} + if metadatas: + if 'tags' in metadatas: + tags = metadatas['tags'] + kwargs['test_tags'] = tags.split(',') + if 'attrs' in metadatas: + test_id = test_id + '[' + metadatas['attrs'] + ']' + kwargs['test_id'] = test_id + if test_status in STATUS_CODES: + kwargs['test_status'] = test_status + kwargs['timestamp'] = create_timestamp() + write_status(**kwargs) + kwargs['timestamp'] = create_timestamp() + test_time + +def create_timestamp(): + return datetime.datetime.now(UTC) + + +if __name__ == '__main__': + sys.exit(xunit2subunit(sys.stdin, sys.stdout)) + + diff --git a/setup.py b/setup.py index 54b1a324..56d2c923 100755 --- a/setup.py +++ b/setup.py @@ -78,6 +78,7 @@ def _get_version_from_file(filename, start_of_line, split_marker): 'filters/subunit2junitxml', 'filters/subunit2pyunit', 'filters/tap2subunit', + 'filters/xunit2subunit', ], **extra ) From 5e8e031c9f392fad06fe85f6a01da7ccfc47c45f Mon Sep 17 00:00:00 2001 From: ganesann Date: Sun, 14 May 2017 22:43:15 +0000 Subject: [PATCH 3/6] Revert "xunit2subunit filter to convert xunitxml to subunit" This reverts commit 4a15ed13f69a46a6ed195d33461e858af514ddaf. Conflicts: filters/xunit2subunit --- Makefile.am | 3 +- filters/xunit2subunit | 82 ------------------------------------------- setup.py | 1 - 3 files changed, 1 insertion(+), 85 deletions(-) delete mode 100755 filters/xunit2subunit diff --git a/Makefile.am b/Makefile.am index b48b6a79..10533487 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,8 +63,7 @@ dist_bin_SCRIPTS = \ filters/subunit2gtk \ filters/subunit2junitxml \ filters/subunit2pyunit \ - filters/tap2subunit \ - filters/xunit2subunit + filters/tap2subunit TESTS = $(check_PROGRAMS) diff --git a/filters/xunit2subunit b/filters/xunit2subunit deleted file mode 100755 index 3a42ab27..00000000 --- a/filters/xunit2subunit +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python -# subunit: extensions to python unittest to get test results from subprocesses. -# Hewlett Packard Enterprise (c) 2017 -# -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause -# license at the users choice. A copy of both licenses are available in the -# project source as Apache-2.0 and BSD. You may not use this file except in -# compliance with one of these two licences. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# license you chose for the specific language governing permissions and -# limitations under that license. -# - -"""A filter that reads a xunitXML stream and outputs a subunit stream. -""" - -import datetime -import sys - -from subunit.iso8601 import UTC - -from subunit.v2 import StreamResultToBytes - -STATUS_CODES = frozenset([ - 'exists', - 'fail', - 'skip', - 'success', - 'uxsuccess', - 'xfail', -]) - -try: - import xunitparser -except ImportError: - sys.stderr.write("xunitparser (https://pypi.python.org/pypi/xunitparser)" - "is required for this filter.") - raise - -def xunit2subunit(xunitxml_input=sys.stdin, output=sys.stdout): - output = StreamResultToBytes(output) - output.startTestRun() - ts, tr = xunitparser.parse(xunitxml_input) - for tc in ts: - test_id = tc.methodname - test_metadata = None - test_status = None - test_time = tc.time - if tc.good: - if tc.result == "skipped": - test_status = "skip" - else: - test_status = "success" - else: - test_status = "fail" - write_test(output, test_id, test_status, test_metadata, test_time) - output.stopTestRun() - -def write_test(output, test_id, test_status, metadatas, test_time): - write_status = output.status - kwargs = {} - if metadatas: - if 'tags' in metadatas: - tags = metadatas['tags'] - kwargs['test_tags'] = tags.split(',') - if 'attrs' in metadatas: - test_id = test_id + '[' + metadatas['attrs'] + ']' - kwargs['test_id'] = test_id - if test_status in STATUS_CODES: - kwargs['test_status'] = test_status - kwargs['timestamp'] = create_timestamp() - write_status(**kwargs) - kwargs['timestamp'] = create_timestamp() + test_time - -def create_timestamp(): - return datetime.datetime.now(UTC) - -if __name__ == '__main__': - sys.exit(xunit2subunit(sys.stdin, sys.stdout)) diff --git a/setup.py b/setup.py index 56d2c923..54b1a324 100755 --- a/setup.py +++ b/setup.py @@ -78,7 +78,6 @@ def _get_version_from_file(filename, start_of_line, split_marker): 'filters/subunit2junitxml', 'filters/subunit2pyunit', 'filters/tap2subunit', - 'filters/xunit2subunit', ], **extra ) From 7336effedcaf7cef8732ed2352b669f0c6c7e549 Mon Sep 17 00:00:00 2001 From: ganesann Date: Sun, 14 May 2017 22:50:38 +0000 Subject: [PATCH 4/6] Adding a subunit filter to convert xunitxml files to subunit format --- Makefile.am | 3 +- filters/xunit2subunit | 82 +++++++++++++++++++++++++++++++++++++++++++ setup.py | 1 + 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100755 filters/xunit2subunit diff --git a/Makefile.am b/Makefile.am index 10533487..204d8316 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,8 @@ dist_bin_SCRIPTS = \ filters/subunit2gtk \ filters/subunit2junitxml \ filters/subunit2pyunit \ - filters/tap2subunit + filters/tap2subunit \ + filters/xunit2subunit TESTS = $(check_PROGRAMS) diff --git a/filters/xunit2subunit b/filters/xunit2subunit new file mode 100755 index 00000000..3a42ab27 --- /dev/null +++ b/filters/xunit2subunit @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# subunit: extensions to python unittest to get test results from subprocesses. +# Hewlett Packard Enterprise (c) 2017 +# +# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause +# license at the users choice. A copy of both licenses are available in the +# project source as Apache-2.0 and BSD. You may not use this file except in +# compliance with one of these two licences. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# license you chose for the specific language governing permissions and +# limitations under that license. +# + +"""A filter that reads a xunitXML stream and outputs a subunit stream. +""" + +import datetime +import sys + +from subunit.iso8601 import UTC + +from subunit.v2 import StreamResultToBytes + +STATUS_CODES = frozenset([ + 'exists', + 'fail', + 'skip', + 'success', + 'uxsuccess', + 'xfail', +]) + +try: + import xunitparser +except ImportError: + sys.stderr.write("xunitparser (https://pypi.python.org/pypi/xunitparser)" + "is required for this filter.") + raise + +def xunit2subunit(xunitxml_input=sys.stdin, output=sys.stdout): + output = StreamResultToBytes(output) + output.startTestRun() + ts, tr = xunitparser.parse(xunitxml_input) + for tc in ts: + test_id = tc.methodname + test_metadata = None + test_status = None + test_time = tc.time + if tc.good: + if tc.result == "skipped": + test_status = "skip" + else: + test_status = "success" + else: + test_status = "fail" + write_test(output, test_id, test_status, test_metadata, test_time) + output.stopTestRun() + +def write_test(output, test_id, test_status, metadatas, test_time): + write_status = output.status + kwargs = {} + if metadatas: + if 'tags' in metadatas: + tags = metadatas['tags'] + kwargs['test_tags'] = tags.split(',') + if 'attrs' in metadatas: + test_id = test_id + '[' + metadatas['attrs'] + ']' + kwargs['test_id'] = test_id + if test_status in STATUS_CODES: + kwargs['test_status'] = test_status + kwargs['timestamp'] = create_timestamp() + write_status(**kwargs) + kwargs['timestamp'] = create_timestamp() + test_time + +def create_timestamp(): + return datetime.datetime.now(UTC) + +if __name__ == '__main__': + sys.exit(xunit2subunit(sys.stdin, sys.stdout)) diff --git a/setup.py b/setup.py index 54b1a324..56d2c923 100755 --- a/setup.py +++ b/setup.py @@ -78,6 +78,7 @@ def _get_version_from_file(filename, start_of_line, split_marker): 'filters/subunit2junitxml', 'filters/subunit2pyunit', 'filters/tap2subunit', + 'filters/xunit2subunit', ], **extra ) From df474a598d25cae73a55b09dd03b597ea31d2e6b Mon Sep 17 00:00:00 2001 From: Navya Rao Date: Mon, 7 Aug 2017 00:12:05 -0400 Subject: [PATCH 5/6] xunit2subunit function modified, xunitparser replaced with xml.etree --- filters/xunit2subunit | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/filters/xunit2subunit b/filters/xunit2subunit index 3a42ab27..0c6183ea 100755 --- a/filters/xunit2subunit +++ b/filters/xunit2subunit @@ -19,10 +19,12 @@ import datetime import sys +import math from subunit.iso8601 import UTC - from subunit.v2 import StreamResultToBytes +from datetime import timedelta +from xml.etree import ElementTree as ET STATUS_CODES = frozenset([ 'exists', @@ -33,31 +35,23 @@ STATUS_CODES = frozenset([ 'xfail', ]) -try: - import xunitparser -except ImportError: - sys.stderr.write("xunitparser (https://pypi.python.org/pypi/xunitparser)" - "is required for this filter.") - raise def xunit2subunit(xunitxml_input=sys.stdin, output=sys.stdout): output = StreamResultToBytes(output) - output.startTestRun() - ts, tr = xunitparser.parse(xunitxml_input) - for tc in ts: - test_id = tc.methodname + tree = ET.parse(xunitxml_input) + for testcase in tree.findall('.//testcase'): + test_id = testcase.attrib.get('name') test_metadata = None test_status = None - test_time = tc.time - if tc.good: - if tc.result == "skipped": - test_status = "skip" - else: - test_status = "success" - else: - test_status = "fail" + skipped = None + failure = None + test_time = to_timedelta(testcase.attrib.get('time')) + skipped = testcase.find('.//skipped') + failure = testcase.find('.//failure') + if skipped is not None : test_status = "skip" + elif failure is not None :test_status = "fail" + else : test_status = "success" write_test(output, test_id, test_status, test_metadata, test_time) - output.stopTestRun() def write_test(output, test_id, test_status, metadatas, test_time): write_status = output.status @@ -75,6 +69,14 @@ def write_test(output, test_id, test_status, metadatas, test_time): write_status(**kwargs) kwargs['timestamp'] = create_timestamp() + test_time +def to_timedelta(value): + if value is None: + return None + sec = float(value) + if math.isnan(sec): + return None + return timedelta(seconds=sec) + def create_timestamp(): return datetime.datetime.now(UTC) From 974c68eeba6a826050cd808b9858855ab59cb000 Mon Sep 17 00:00:00 2001 From: msiv Date: Tue, 6 Feb 2018 14:51:51 +0530 Subject: [PATCH 6/6] Modify xunit2subunit test time with proper duration --- filters/xunit2subunit | 3 +++ 1 file changed, 3 insertions(+) diff --git a/filters/xunit2subunit b/filters/xunit2subunit index 0c6183ea..02967b62 100755 --- a/filters/xunit2subunit +++ b/filters/xunit2subunit @@ -66,8 +66,11 @@ def write_test(output, test_id, test_status, metadatas, test_time): if test_status in STATUS_CODES: kwargs['test_status'] = test_status kwargs['timestamp'] = create_timestamp() + kwargs['test_status'] = "inprogress" write_status(**kwargs) kwargs['timestamp'] = create_timestamp() + test_time + kwargs['test_status'] = test_status + write_status(**kwargs) def to_timedelta(value): if value is None: