mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2026-01-23 00:15:58 +01:00
Fixes and features on the JUnit Python conversion script
* Added python3 shebang * Renamed the script `unity_to_junit.py` as `stylize_as_junit.py` to match the Ruby file * Fixed a bug on where the script failed if the first entry slot of each result line is empty. Now falls back to the result file name * Rewrote the argument parsing to use argparse * Added a `--output` / `-o` option, to match the Ruby file
This commit is contained in:
@@ -1,6 +1,15 @@
|
|||||||
|
#! python3
|
||||||
|
# ==========================================
|
||||||
|
# Fork from Unity Project - A Test Framework for C
|
||||||
|
# Pull request on Gerrit in progress, the objective of this file is to be deleted when official Unity deliveries
|
||||||
|
# include that modification
|
||||||
|
# Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de
|
||||||
|
# [Released under MIT License. Please refer to license.txt for details]
|
||||||
|
# ==========================================
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
import argparse
|
||||||
|
|
||||||
from pyparsing import *
|
from pyparsing import *
|
||||||
from junit_xml import TestSuite, TestCase
|
from junit_xml import TestSuite, TestCase
|
||||||
@@ -14,6 +23,7 @@ class UnityTestSummary:
|
|||||||
self.ignored = 0
|
self.ignored = 0
|
||||||
self.targets = 0
|
self.targets = 0
|
||||||
self.root = None
|
self.root = None
|
||||||
|
self.output = None
|
||||||
self.test_suites = dict()
|
self.test_suites = dict()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -37,15 +47,18 @@ class UnityTestSummary:
|
|||||||
entry = entry_one | entry_two
|
entry = entry_one | entry_two
|
||||||
|
|
||||||
delimiter = Literal(':').suppress()
|
delimiter = Literal(':').suppress()
|
||||||
tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName(
|
# Format of a result line is `[file_name]:line:test_name:RESULT[:msg]`
|
||||||
'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName(
|
tc_result_line = Group(ZeroOrMore(entry.setResultsName('tc_file_name'))
|
||||||
'tc_status') + Optional(
|
+ delimiter + entry.setResultsName('tc_line_nr')
|
||||||
delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
|
+ delimiter + entry.setResultsName('tc_name')
|
||||||
|
+ delimiter + entry.setResultsName('tc_status') +
|
||||||
|
Optional(delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
|
||||||
|
|
||||||
eol = LineEnd().suppress()
|
eol = LineEnd().suppress()
|
||||||
sol = LineStart().suppress()
|
sol = LineStart().suppress()
|
||||||
blank_line = sol + eol
|
blank_line = sol + eol
|
||||||
|
|
||||||
|
# Format of the summary line is `# Tests # Failures # Ignored`
|
||||||
tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
|
tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
|
||||||
"num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
|
"num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
|
||||||
"tc_summary")
|
"tc_summary")
|
||||||
@@ -67,7 +80,10 @@ class UnityTestSummary:
|
|||||||
tmp_tc_line = r['tc_line']
|
tmp_tc_line = r['tc_line']
|
||||||
|
|
||||||
# get only the file name which will be used as the classname
|
# get only the file name which will be used as the classname
|
||||||
file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
|
if 'tc_file_name' in tmp_tc_line:
|
||||||
|
file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
|
||||||
|
else:
|
||||||
|
file_name = result_file.strip("./")
|
||||||
tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
|
tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
|
||||||
if 'tc_status' in tmp_tc_line:
|
if 'tc_status' in tmp_tc_line:
|
||||||
if str(tmp_tc_line['tc_status']) == 'IGNORE':
|
if str(tmp_tc_line['tc_status']) == 'IGNORE':
|
||||||
@@ -96,7 +112,7 @@ class UnityTestSummary:
|
|||||||
for suite_name in self.test_suites:
|
for suite_name in self.test_suites:
|
||||||
ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
|
ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
|
||||||
|
|
||||||
with open('result.xml', 'w') as f:
|
with open(self.output, 'w') as f:
|
||||||
TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
|
TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
|
||||||
|
|
||||||
return self.report
|
return self.report
|
||||||
@@ -107,40 +123,39 @@ class UnityTestSummary:
|
|||||||
def set_root_path(self, path):
|
def set_root_path(self, path):
|
||||||
self.root = path
|
self.root = path
|
||||||
|
|
||||||
@staticmethod
|
def set_output(self, output):
|
||||||
def usage(err_msg=None):
|
self.output = output
|
||||||
print("\nERROR: ")
|
|
||||||
if err_msg:
|
|
||||||
print(err_msg)
|
|
||||||
print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
|
|
||||||
print(" result_file_directory - The location of your results files.")
|
|
||||||
print(" Defaults to current directory if not specified.")
|
|
||||||
print(" Should end in / if specified.")
|
|
||||||
print(" root_path - Helpful for producing more verbose output if using relative paths.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
uts = UnityTestSummary()
|
uts = UnityTestSummary()
|
||||||
try:
|
parser = argparse.ArgumentParser(description=
|
||||||
# look in the specified or current directory for result files
|
"""Takes as input the collection of *.testpass and *.testfail result
|
||||||
if len(sys.argv) > 1:
|
files, and converts them to a JUnit formatted XML.""")
|
||||||
targets_dir = sys.argv[1]
|
parser.add_argument('targets_dir', metavar='result_file_directory',
|
||||||
else:
|
type=str, nargs='?', default='./',
|
||||||
targets_dir = './'
|
help="""The location of your results files.
|
||||||
targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
|
Defaults to current directory if not specified.""")
|
||||||
if len(targets) == 0:
|
parser.add_argument('root_path', nargs='?',
|
||||||
raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
|
default='os.path.split(__file__)[0]',
|
||||||
uts.set_targets(targets)
|
help="""Helpful for producing more verbose output if
|
||||||
|
using relative paths.""")
|
||||||
|
parser.add_argument('--output', '-o', type=str, default="result.xml",
|
||||||
|
help="""The name of the JUnit-formatted file (XML).""")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
# set the root path
|
if args.targets_dir[-1] != '/':
|
||||||
if len(sys.argv) > 2:
|
args.targets_dir+='/'
|
||||||
root_path = sys.argv[2]
|
targets = list(map(lambda x: x.replace('\\', '/'), glob(args.targets_dir + '*.test*')))
|
||||||
else:
|
if len(targets) == 0:
|
||||||
root_path = os.path.split(__file__)[0]
|
raise Exception("No *.testpass or *.testfail files found in '%s'" % args.targets_dir)
|
||||||
uts.set_root_path(root_path)
|
uts.set_targets(targets)
|
||||||
|
|
||||||
# run the summarizer
|
# set the root path
|
||||||
print(uts.run())
|
uts.set_root_path(args.root_path)
|
||||||
except Exception as e:
|
|
||||||
UnityTestSummary.usage(e)
|
# set output
|
||||||
|
uts.set_output(args.output)
|
||||||
|
|
||||||
|
# run the summarizer
|
||||||
|
print(uts.run())
|
||||||
Reference in New Issue
Block a user