Skip to content

Commit 191df2f

Browse files
committed
Merge branch 'danchr-expected'
2 parents 669f204 + 2752f94 commit 191df2f

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
@@ -323,7 +330,7 @@ def addSuccess(self, test):
323330
"""
324331
self._save_output_data()
325332
self._prepare_callback(
326-
self.infoclass(self, test), self.successes, 'OK', '.'
333+
self.infoclass(self, test), self.successes, 'ok', '.'
327334
)
328335

329336
@failfast
@@ -390,21 +397,23 @@ def addSkip(self, test, reason):
390397
self._save_output_data()
391398
testinfo = self.infoclass(
392399
self, test, self.infoclass.SKIP, reason)
400+
testinfo.test_exception_name = 'skip'
401+
testinfo.test_exception_message = reason
393402
self.skipped.append((testinfo, reason))
394-
self._prepare_callback(testinfo, [], 'SKIP', 'S')
403+
self._prepare_callback(testinfo, [], 'skip', 's')
395404

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

402-
testinfo = self.infoclass(self, test, self.infoclass.ERROR, err)
403-
testinfo.test_exception_name = 'ExpectedFailure'
404-
testinfo.test_exception_message = 'EXPECTED FAILURE: {}'.format(testinfo.test_exception_message)
411+
testinfo = self.infoclass(self, test, self.infoclass.SKIP, err)
412+
testinfo.test_exception_name = 'XFAIL'
413+
testinfo.test_exception_message = 'expected failure: {}'.format(testinfo.test_exception_message)
405414

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

409418
@failfast
410419
def addUnexpectedSuccess(self, test):
@@ -417,11 +426,11 @@ def addUnexpectedSuccess(self, test):
417426
testinfo.outcome = self.infoclass.ERROR
418427
# But since we want to have error outcome, we need to provide additional fields:
419428
testinfo.test_exception_name = 'UnexpectedSuccess'
420-
testinfo.test_exception_message = ('UNEXPECTED SUCCESS: This test was marked as expected failure but passed, '
429+
testinfo.test_exception_message = ('Unexpected success: This test was marked as expected failure but passed, '
421430
'please review it')
422431

423-
self.unexpectedSuccesses.append(testinfo)
424-
self._prepare_callback(testinfo, [], 'UNEXPECTED SUCCESS', 'U')
432+
self.unexpectedSuccesses.append((testinfo, 'unexpected success'))
433+
self._prepare_callback(testinfo, [], 'unexpected success', 'u')
425434

426435
def printErrorList(self, flavour, errors):
427436
"""
@@ -557,33 +566,32 @@ def _report_testcase(test_result, xml_testsuite, xml_document):
557566
if test_result.lineno is not None:
558567
testcase.setAttribute('line', str(test_result.lineno))
559568

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

580-
if test_result.stdout:
588+
if test_result.stdout is not None:
581589
systemout = xml_document.createElement('system-out')
582590
testcase.appendChild(systemout)
583591
_XMLTestResult._createCDATAsections(
584592
xml_document, systemout, test_result.stdout)
585593

586-
if test_result.stderr:
594+
if test_result.stderr is not None:
587595
systemout = xml_document.createElement('system-err')
588596
testcase.appendChild(systemout)
589597
_XMLTestResult._createCDATAsections(

0 commit comments

Comments
 (0)