Skip to content

Commit 2752f94

Browse files
committed
Merge branch 'expected' of https://github.com/danchr/unittest-xml-reporting into danchr-expected
2 parents fffff9a + 7c4d6a2 commit 2752f94

File tree

2 files changed

+83
-32
lines changed

2 files changed

+83
-32
lines changed

tests/testsuite.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,18 +200,25 @@ def setUp(self):
200200
self.runner_kwargs = {}
201201
self.addCleanup(rmtree, self.outdir)
202202

203-
def _test_xmlrunner(self, suite, runner=None):
204-
outdir = self.outdir
203+
def _test_xmlrunner(self, suite, runner=None, outdir=None):
204+
if outdir is None:
205+
outdir = self.outdir
205206
stream = self.stream
206207
verbosity = self.verbosity
207208
runner_kwargs = self.runner_kwargs
208209
if runner is None:
209210
runner = xmlrunner.XMLTestRunner(
210211
stream=stream, output=outdir, verbosity=verbosity,
211212
**runner_kwargs)
212-
self.assertEqual(0, len(glob(os.path.join(outdir, '*xml'))))
213+
if isinstance(outdir, BytesIO):
214+
self.assertFalse(outdir.getvalue())
215+
else:
216+
self.assertEqual(0, len(glob(os.path.join(outdir, '*xml'))))
213217
runner.run(suite)
214-
self.assertEqual(1, len(glob(os.path.join(outdir, '*xml'))))
218+
if isinstance(outdir, BytesIO):
219+
self.assertTrue(outdir.getvalue())
220+
else:
221+
self.assertEqual(1, len(glob(os.path.join(outdir, '*xml'))))
215222
return runner
216223

217224
def test_basic_unittest_constructs(self):
@@ -251,6 +258,42 @@ def test_classnames(self):
251258
r'DummySubTest" name="test_subTest_pass"'.encode('utf8'),
252259
)
253260

261+
def test_expected_failure(self):
262+
suite = unittest.TestSuite()
263+
suite.addTest(self.DummyTest('test_expected_failure'))
264+
outdir = BytesIO()
265+
266+
self._test_xmlrunner(suite, outdir=outdir)
267+
268+
self.assertNotIn(b'<failure', outdir.getvalue())
269+
self.assertNotIn(b'<error', outdir.getvalue())
270+
self.assertIn(b'<skip', outdir.getvalue())
271+
272+
def test_unexpected_success(self):
273+
suite = unittest.TestSuite()
274+
suite.addTest(self.DummyTest('test_unexpected_success'))
275+
outdir = BytesIO()
276+
277+
self._test_xmlrunner(suite, outdir=outdir)
278+
279+
self.assertNotIn(b'<failure', outdir.getvalue())
280+
self.assertIn(b'<error', outdir.getvalue())
281+
self.assertNotIn(b'<skip', outdir.getvalue())
282+
283+
def test_xmlrunner_safe_xml_encoding_name(self):
284+
suite = unittest.TestSuite()
285+
suite.addTest(self.DummyTest('test_pass'))
286+
outdir = BytesIO()
287+
runner = xmlrunner.XMLTestRunner(
288+
stream=self.stream, output=outdir, verbosity=self.verbosity,
289+
**self.runner_kwargs)
290+
runner.run(suite)
291+
outdir.seek(0)
292+
output = outdir.read()
293+
firstline = output.splitlines()[0]
294+
# test for issue #74
295+
self.assertIn('encoding="UTF-8"'.encode('utf8'), firstline)
296+
254297
def test_xmlrunner_non_ascii(self):
255298
suite = unittest.TestSuite()
256299
suite.addTest(self.DummyTest('test_non_ascii_skip'))

xmlrunner/result.py

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ class _TestInfo(object):
134134
# Possible test outcomes
135135
(SUCCESS, FAILURE, ERROR, SKIP) = range(4)
136136

137+
OUTCOME_ELEMENTS = {
138+
SUCCESS: None,
139+
FAILURE: 'failure',
140+
ERROR: 'error',
141+
SKIP: 'skipped',
142+
}
143+
137144
def __init__(self, test_result, test_method, outcome=SUCCESS, err=None, subTest=None, filename=None, lineno=None):
138145
self.test_result = test_result
139146
self.outcome = outcome
@@ -321,7 +328,7 @@ def addSuccess(self, test):
321328
"""
322329
self._save_output_data()
323330
self._prepare_callback(
324-
self.infoclass(self, test), self.successes, 'OK', '.'
331+
self.infoclass(self, test), self.successes, 'ok', '.'
325332
)
326333

327334
@failfast
@@ -388,21 +395,23 @@ def addSkip(self, test, reason):
388395
self._save_output_data()
389396
testinfo = self.infoclass(
390397
self, test, self.infoclass.SKIP, reason)
398+
testinfo.test_exception_name = 'skip'
399+
testinfo.test_exception_message = reason
391400
self.skipped.append((testinfo, reason))
392-
self._prepare_callback(testinfo, [], 'SKIP', 'S')
401+
self._prepare_callback(testinfo, [], 'skip', 's')
393402

394403
def addExpectedFailure(self, test, err):
395404
"""
396405
Missing in xmlrunner, copy-pasted from xmlrunner addError.
397406
"""
398407
self._save_output_data()
399408

400-
testinfo = self.infoclass(self, test, self.infoclass.ERROR, err)
401-
testinfo.test_exception_name = 'ExpectedFailure'
402-
testinfo.test_exception_message = 'EXPECTED FAILURE: {}'.format(testinfo.test_exception_message)
409+
testinfo = self.infoclass(self, test, self.infoclass.SKIP, err)
410+
testinfo.test_exception_name = 'XFAIL'
411+
testinfo.test_exception_message = 'expected failure: {}'.format(testinfo.test_exception_message)
403412

404413
self.expectedFailures.append((testinfo, self._exc_info_to_string(err, test)))
405-
self._prepare_callback(testinfo, [], 'EXPECTED FAILURE', 'X')
414+
self._prepare_callback(testinfo, [], 'expected failure', 'x')
406415

407416
@failfast
408417
def addUnexpectedSuccess(self, test):
@@ -415,11 +424,11 @@ def addUnexpectedSuccess(self, test):
415424
testinfo.outcome = self.infoclass.ERROR
416425
# But since we want to have error outcome, we need to provide additional fields:
417426
testinfo.test_exception_name = 'UnexpectedSuccess'
418-
testinfo.test_exception_message = ('UNEXPECTED SUCCESS: This test was marked as expected failure but passed, '
427+
testinfo.test_exception_message = ('Unexpected success: This test was marked as expected failure but passed, '
419428
'please review it')
420429

421-
self.unexpectedSuccesses.append(testinfo)
422-
self._prepare_callback(testinfo, [], 'UNEXPECTED SUCCESS', 'U')
430+
self.unexpectedSuccesses.append((testinfo, 'unexpected success'))
431+
self._prepare_callback(testinfo, [], 'unexpected success', 'u')
423432

424433
def printErrorList(self, flavour, errors):
425434
"""
@@ -555,33 +564,32 @@ def _report_testcase(test_result, xml_testsuite, xml_document):
555564
if test_result.lineno is not None:
556565
testcase.setAttribute('line', str(test_result.lineno))
557566

558-
if (test_result.outcome != test_result.SUCCESS):
559-
elem_name = ('failure', 'error', 'skipped')[test_result.outcome-1]
560-
failure = xml_document.createElement(elem_name)
561-
testcase.appendChild(failure)
562-
if test_result.outcome != test_result.SKIP:
563-
failure.setAttribute(
564-
'type',
565-
test_result.test_exception_name
566-
)
567-
failure.setAttribute(
568-
'message',
569-
test_result.test_exception_message
570-
)
567+
result_elem_name = test_result.OUTCOME_ELEMENTS[test_result.outcome]
568+
569+
if result_elem_name is not None:
570+
result_elem = xml_document.createElement(result_elem_name)
571+
testcase.appendChild(result_elem)
572+
573+
result_elem.setAttribute(
574+
'type',
575+
test_result.test_exception_name
576+
)
577+
result_elem.setAttribute(
578+
'message',
579+
test_result.test_exception_message
580+
)
581+
if test_result.get_error_info():
571582
error_info = safe_unicode(test_result.get_error_info())
572583
_XMLTestResult._createCDATAsections(
573-
xml_document, failure, error_info)
574-
else:
575-
failure.setAttribute('type', 'skip')
576-
failure.setAttribute('message', test_result.test_exception_message)
584+
xml_document, result_elem, error_info)
577585

578-
if test_result.stdout:
586+
if test_result.stdout is not None:
579587
systemout = xml_document.createElement('system-out')
580588
testcase.appendChild(systemout)
581589
_XMLTestResult._createCDATAsections(
582590
xml_document, systemout, test_result.stdout)
583591

584-
if test_result.stderr:
592+
if test_result.stderr is not None:
585593
systemout = xml_document.createElement('system-err')
586594
testcase.appendChild(systemout)
587595
_XMLTestResult._createCDATAsections(

0 commit comments

Comments
 (0)