"""Test case implementation"""
strclass, safe_repr, unorderable_list_difference,
_count_diff_all_purpose, _count_diff_hashable
DIFF_OMITTED = ('\nDiff is %s characters long. '
'Set self.maxDiff to None to see it.')
class SkipTest(Exception):
Raise this exception in a test to skip it.
Usually you can use TestCase.skipTest() or one of the skipping decorators
instead of raising this directly.
class _ExpectedFailure(Exception):
Raise this when a test is expected to fail.
This is an implementation detail.
def __init__(self, exc_info):
super(_ExpectedFailure, self).__init__()
class _UnexpectedSuccess(Exception):
The test was supposed to fail, but it didn't!
Unconditionally skip a test.
def decorator(test_item):
if not isinstance(test_item, (type, types.ClassType)):
@functools.wraps(test_item)
def skip_wrapper(*args, **kwargs):
test_item.__unittest_skip__ = True
test_item.__unittest_skip_why__ = reason
def skipIf(condition, reason):
Skip a test if the condition is true.
def skipUnless(condition, reason):
Skip a test unless the condition is true.
def expectedFailure(func):
def wrapper(*args, **kwargs):
raise _ExpectedFailure(sys.exc_info())
# Non-standard/downstream-only hooks for handling issues with specific test
def _skipInRpmBuild(reason):
Non-standard/downstream-only decorator for marking a specific unit test
to be skipped when run within the %check of an rpmbuild.
Specifically, this takes effect when WITHIN_PYTHON_RPM_BUILD is set within
the environment, and has no effect otherwise.
if 'WITHIN_PYTHON_RPM_BUILD' in os.environ:
def _expectedFailureInRpmBuild(func):
Non-standard/downstream-only decorator for marking a specific unit test
as expected to fail within the %check of an rpmbuild.
Specifically, this takes effect when WITHIN_PYTHON_RPM_BUILD is set within
the environment, and has no effect otherwise.
def wrapper(*args, **kwargs):
if 'WITHIN_PYTHON_RPM_BUILD' in os.environ:
raise _ExpectedFailure(sys.exc_info())
class _AssertRaisesContext(object):
"""A context manager used to implement TestCase.assertRaises* methods."""
def __init__(self, expected, test_case, expected_regexp=None):
self.failureException = test_case.failureException
self.expected_regexp = expected_regexp
def __exit__(self, exc_type, exc_value, tb):
exc_name = self.expected.__name__
exc_name = str(self.expected)
raise self.failureException(
"{0} not raised".format(exc_name))
if not issubclass(exc_type, self.expected):
# let unexpected exceptions pass through
self.exception = exc_value # store for later retrieval
if self.expected_regexp is None:
expected_regexp = self.expected_regexp
if not expected_regexp.search(str(exc_value)):
raise self.failureException('"%s" does not match "%s"' %
(expected_regexp.pattern, str(exc_value)))
"""A class whose instances are single test cases.
By default, the test code itself should be placed in a method named
If the fixture may be used for many test cases, create as
many test methods as are needed. When instantiating such a TestCase
subclass, specify in the constructor arguments the name of the test method
that the instance is to execute.
Test authors should subclass TestCase for their own tests. Construction
and deconstruction of the test's environment ('fixture') can be
implemented by overriding the 'setUp' and 'tearDown' methods respectively.
If it is necessary to override the __init__ method, the base class
__init__ method must always be called. It is important that subclasses
should not change the signature of their __init__ method, since instances
of the classes are instantiated automatically by parts of the framework
When subclassing TestCase, you can set these attributes:
* failureException: determines which exception will be raised when
the instance's assertion methods fail; test methods raising this
exception will be deemed to have 'failed' rather than 'errored'.
* longMessage: determines whether long messages (including repr of
objects used in assert methods) will be printed on failure in *addition*
to any explicit message passed.
* maxDiff: sets the maximum length of a diff in failure messages
by assert methods using difflib. It is looked up as an instance
attribute so can be configured by individual tests if required.
failureException = AssertionError
# If a string is longer than _diffThreshold, use normal comparison instead
# of difflib. See #11763.
# Attribute used by TestSuite for classSetUp
_classSetupFailed = False
def __init__(self, methodName='runTest'):
"""Create an instance of the class that will use the named test
method when executed. Raises a ValueError if the instance does
not have a method with the specified name.
self._testMethodName = methodName
self._resultForDoCleanups = None
testMethod = getattr(self, methodName)
raise ValueError("no such test method in %s: %s" %
(self.__class__, methodName))
self._testMethodDoc = testMethod.__doc__
# Map types to custom assertEqual functions that will compare
# instances of said type in more detail to generate a more useful
self._type_equality_funcs = {}
self.addTypeEqualityFunc(dict, 'assertDictEqual')
self.addTypeEqualityFunc(list, 'assertListEqual')
self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
self.addTypeEqualityFunc(set, 'assertSetEqual')
self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
self.addTypeEqualityFunc(unicode, 'assertMultiLineEqual')
# No unicode support in this build
def addTypeEqualityFunc(self, typeobj, function):
"""Add a type specific assertEqual style function to compare a type.
This method is for use by TestCase subclasses that need to register
their own type equality functions to provide nicer error messages.
typeobj: The data type to call this function on when both values
are of the same type in assertEqual().
function: The callable taking two arguments and an optional
msg= argument that raises self.failureException with a
useful error message when the two arguments are not equal.
self._type_equality_funcs[typeobj] = function
def addCleanup(self, function, *args, **kwargs):
"""Add a function, with arguments, to be called when the test is
completed. Functions added are called on a LIFO basis and are
called after tearDown on test failure or success.
Cleanup items are called even if setUp fails (unlike tearDown)."""
self._cleanups.append((function, args, kwargs))
"Hook method for setting up the test fixture before exercising it."
"Hook method for deconstructing the test fixture after testing it."
"Hook method for setting up class fixture before running tests in the class."
"Hook method for deconstructing the class fixture after running all tests in the class."
def countTestCases(self):
def defaultTestResult(self):
return result.TestResult()
def shortDescription(self):
"""Returns a one-line description of the test, or None if no
description has been provided.
The default implementation of this method returns the first line of
the specified test method's docstring.
doc = self._testMethodDoc
return doc and doc.split("\n")[0].strip() or None
return "%s.%s" % (strclass(self.__class__), self._testMethodName)
if type(self) is not type(other):
return self._testMethodName == other._testMethodName
return hash((type(self), self._testMethodName))
return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
return "<%s testMethod=%s>" % \
(strclass(self.__class__), self._testMethodName)
def _addSkip(self, result, reason):
addSkip = getattr(result, 'addSkip', None)
warnings.warn("TestResult has no addSkip method, skips not reported",
def run(self, result=None):
result = self.defaultTestResult()
startTestRun = getattr(result, 'startTestRun', None)
if startTestRun is not None:
self._resultForDoCleanups = result
testMethod = getattr(self, self._testMethodName)
if (getattr(self.__class__, "__unittest_skip__", False) or
getattr(testMethod, "__unittest_skip__", False)):
# If the class or method was skipped.
skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
or getattr(testMethod, '__unittest_skip_why__', ''))
self._addSkip(result, skip_why)
self._addSkip(result, str(e))
except KeyboardInterrupt:
result.addError(self, sys.exc_info())
except KeyboardInterrupt:
except self.failureException:
result.addFailure(self, sys.exc_info())
except _ExpectedFailure as e:
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
if addExpectedFailure is not None:
addExpectedFailure(self, e.exc_info)
warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
except _UnexpectedSuccess:
addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
if addUnexpectedSuccess is not None:
addUnexpectedSuccess(self)
warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
result.addFailure(self, sys.exc_info())
self._addSkip(result, str(e))
result.addError(self, sys.exc_info())
except KeyboardInterrupt:
result.addError(self, sys.exc_info())
cleanUpSuccess = self.doCleanups()
success = success and cleanUpSuccess
stopTestRun = getattr(result, 'stopTestRun', None)
if stopTestRun is not None:
"""Execute all cleanup functions. Normally called for you after
result = self._resultForDoCleanups
function, args, kwargs = self._cleanups.pop(-1)
function(*args, **kwargs)
except KeyboardInterrupt:
result.addError(self, sys.exc_info())
def __call__(self, *args, **kwds):
return self.run(*args, **kwds)
"""Run the test without collecting errors in a TestResult"""
getattr(self, self._testMethodName)()
function, args, kwargs = self._cleanups.pop(-1)
function(*args, **kwargs)
def skipTest(self, reason):
def fail(self, msg=None):
"""Fail immediately, with the given message."""
raise self.failureException(msg)
def assertFalse(self, expr, msg=None):
"""Check that the expression is false."""
msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
raise self.failureException(msg)
def assertTrue(self, expr, msg=None):
"""Check that the expression is true."""
msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
raise self.failureException(msg)
def _formatMessage(self, msg, standardMsg):
"""Honour the longMessage attribute when generating failure messages.
If longMessage is False this means:
* Use only an explicit message if it is provided
* Otherwise use the standard message for the assert
* Use the standard message
* If an explicit message is provided, plus ' : ' and the explicit message
return msg or standardMsg
# don't switch to '{}' formatting in Python 2.X
# it changes the way unicode input is handled
return '%s : %s' % (standardMsg, msg)
except UnicodeDecodeError:
return '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
"""Fail unless an exception of class excClass is raised
by callableObj when invoked with arguments args and keyword
arguments kwargs. If a different type of exception is
raised, it will not be caught, and the test case will be
deemed to have suffered an error, exactly as for an
If called with callableObj omitted or None, will return a
context object used like this::
with self.assertRaises(SomeException):
The context manager keeps a reference to the exception as
the 'exception' attribute. This allows you to inspect the
exception after the assertion::