(fixes issue85) correctly write non-ascii test output to junitxml files, refine some internal methods for it
--HG-- branch : trunk
This commit is contained in:
parent
f6a04b92d2
commit
c8d78177b9
|
@ -2,6 +2,7 @@ Changes between 1.2.1 and 1.2.2 (release pending)
|
|||
==================================================
|
||||
|
||||
- new mechanism to allow plugins to register new hooks
|
||||
- (issue85) fix junitxml plugin to handle tests with non-ascii output
|
||||
- fixes for handling of unicode exception values
|
||||
- added links to the new capturelog and coverage plugins
|
||||
- (issue87) fix unboundlocal error in assertionold code
|
||||
|
|
|
@ -417,6 +417,12 @@ class ExceptionInfo(object):
|
|||
loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
|
||||
return str(loc)
|
||||
|
||||
def __unicode__(self):
|
||||
entry = self.traceback[-1]
|
||||
loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
|
||||
return unicode(loc)
|
||||
|
||||
|
||||
class FormattedExcinfo(object):
|
||||
""" presenting information about failing Functions and Generators. """
|
||||
# for traceback entries
|
||||
|
@ -579,11 +585,15 @@ class FormattedExcinfo(object):
|
|||
|
||||
class TerminalRepr:
|
||||
def __str__(self):
|
||||
s = self.__unicode__()
|
||||
if sys.version_info[0] < 3:
|
||||
s = s.encode('utf-8')
|
||||
return s
|
||||
|
||||
def __unicode__(self):
|
||||
tw = py.io.TerminalWriter(stringio=True)
|
||||
self.toterminal(tw)
|
||||
s = tw.stringio.getvalue().strip()
|
||||
if sys.version_info[0] < 3:
|
||||
s = s.encode('utf-8')
|
||||
return s
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
@ -43,6 +43,10 @@ class LogXML(object):
|
|||
|
||||
def _closetestcase(self):
|
||||
self.test_logs.append("</testcase>")
|
||||
|
||||
def appendlog(self, fmt, *args):
|
||||
args = tuple([py.xml.escape(arg) for arg in args])
|
||||
self.test_logs.append(fmt % args)
|
||||
|
||||
def append_pass(self, report):
|
||||
self.passed += 1
|
||||
|
@ -51,10 +55,9 @@ class LogXML(object):
|
|||
|
||||
def append_failure(self, report):
|
||||
self._opentestcase(report)
|
||||
s = py.xml.escape(str(report.longrepr))
|
||||
#msg = str(report.longrepr.reprtraceback.extraline)
|
||||
self.test_logs.append(
|
||||
'<failure message="test failure">%s</failure>' % (s))
|
||||
self.appendlog('<failure message="test failure">%s</failure>',
|
||||
report.longrepr)
|
||||
self._closetestcase()
|
||||
self.failed += 1
|
||||
|
||||
|
@ -69,33 +72,30 @@ class LogXML(object):
|
|||
|
||||
def append_collect_failure(self, report):
|
||||
self._opentestcase_collectfailure(report)
|
||||
s = py.xml.escape(str(report.longrepr))
|
||||
#msg = str(report.longrepr.reprtraceback.extraline)
|
||||
self.test_logs.append(
|
||||
'<failure message="collection failure">%s</failure>' % (s))
|
||||
self.appendlog('<failure message="collection failure">%s</failure>',
|
||||
report.longrepr)
|
||||
self._closetestcase()
|
||||
self.errors += 1
|
||||
|
||||
def append_collect_skipped(self, report):
|
||||
self._opentestcase_collectfailure(report)
|
||||
s = py.xml.escape(str(report.longrepr))
|
||||
#msg = str(report.longrepr.reprtraceback.extraline)
|
||||
self.test_logs.append(
|
||||
'<skipped message="collection skipped">%s</skipped>' % (s))
|
||||
self.appendlog('<skipped message="collection skipped">%s</skipped>',
|
||||
report.longrepr)
|
||||
self._closetestcase()
|
||||
self.skipped += 1
|
||||
|
||||
def append_error(self, report):
|
||||
self._opentestcase(report)
|
||||
s = py.xml.escape(str(report.longrepr))
|
||||
self.test_logs.append(
|
||||
'<error message="test setup failure">%s</error>' % s)
|
||||
self.appendlog('<error message="test setup failure">%s</error>',
|
||||
report.longrepr)
|
||||
self._closetestcase()
|
||||
self.errors += 1
|
||||
|
||||
def append_skipped(self, report):
|
||||
self._opentestcase(report)
|
||||
self.test_logs.append("<skipped/>")
|
||||
self.appendlog("<skipped/>")
|
||||
self._closetestcase()
|
||||
self.skipped += 1
|
||||
|
||||
|
@ -126,7 +126,7 @@ class LogXML(object):
|
|||
|
||||
def pytest_internalerror(self, excrepr):
|
||||
self.errors += 1
|
||||
data = py.xml.escape(str(excrepr))
|
||||
data = py.xml.escape(excrepr)
|
||||
self.test_logs.append(
|
||||
'\n<testcase classname="pytest" name="internal">'
|
||||
' <error message="internal error">'
|
||||
|
@ -136,7 +136,11 @@ class LogXML(object):
|
|||
self.suite_start_time = time.time()
|
||||
|
||||
def pytest_sessionfinish(self, session, exitstatus, __multicall__):
|
||||
logfile = open(self.logfile, 'w', 1) # line buffered
|
||||
if py.std.sys.version_info[0] < 3:
|
||||
logfile = py.std.codecs.open(self.logfile, 'w', encoding='utf-8')
|
||||
else:
|
||||
logfile = open(self.logfile, 'w', encoding='utf-8')
|
||||
|
||||
suite_stop_time = time.time()
|
||||
suite_time_delta = suite_stop_time - self.suite_start_time
|
||||
numtests = self.passed + self.failed
|
||||
|
|
|
@ -238,6 +238,7 @@ class _escape:
|
|||
|
||||
def __call__(self, ustring):
|
||||
""" xml-escape the given unicode string. """
|
||||
ustring = unicode(ustring)
|
||||
return self.charef_rex.sub(self._replacer, ustring)
|
||||
|
||||
escape = _escape()
|
||||
|
|
|
@ -199,3 +199,5 @@ def test_unicode_handling(testdir):
|
|||
raise Exception(value)
|
||||
excinfo = py.test.raises(Exception, f)
|
||||
s = str(excinfo)
|
||||
if sys.version_info[0] < 3:
|
||||
u = unicode(excinfo)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
from xml.dom import minidom
|
||||
import py
|
||||
|
||||
def runandparse(testdir, *args):
|
||||
resultpath = testdir.tmpdir.join("junit.xml")
|
||||
|
@ -118,6 +119,19 @@ class TestPython:
|
|||
fnode = tnode.getElementsByTagName("skipped")[0]
|
||||
assert_attr(fnode, message="collection skipped")
|
||||
|
||||
def test_unicode(self, testdir):
|
||||
value = 'hx\xc4\x85\xc4\x87\n'
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
print (%r)
|
||||
assert 0
|
||||
""" % value)
|
||||
result, dom = runandparse(testdir)
|
||||
assert result.ret == 1
|
||||
tnode = dom.getElementsByTagName("testcase")[0]
|
||||
fnode = tnode.getElementsByTagName("failure")[0]
|
||||
assert "hx" in fnode.toxml()
|
||||
|
||||
class TestNonPython:
|
||||
def test_summing_simple(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
|
|
|
@ -5,6 +5,25 @@ from py._xmlgen import unicode, html
|
|||
class ns(py.xml.Namespace):
|
||||
pass
|
||||
|
||||
def test_escape():
|
||||
uvalue = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8')
|
||||
class A:
|
||||
def __unicode__(self):
|
||||
return uvalue
|
||||
def __str__(self):
|
||||
x = self.__unicode__()
|
||||
if py.std.sys.version_info[0] < 3:
|
||||
return x.encode('utf-8')
|
||||
return x
|
||||
y = py.xml.escape(uvalue)
|
||||
assert y == uvalue
|
||||
x = py.xml.escape(A())
|
||||
assert x == uvalue
|
||||
if py.std.sys.version_info[0] < 3:
|
||||
assert isinstance(x, unicode)
|
||||
assert isinstance(y, unicode)
|
||||
|
||||
|
||||
def test_tag_with_text():
|
||||
x = ns.hello("world")
|
||||
u = unicode(x)
|
||||
|
|
Loading…
Reference in New Issue