mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Update unittest from CPython 3.10.5
This commit is contained in:
1 parent
760bda6c50
commit
799c78670b
31 files changed
+6053
-882
No files matched your search
Vendored
+6
-6
@@ -3,14 +3,14 @@ import unittest.test
|
||||
from test import support
|
||||
|
||||
|
||||
def test_main():
|
||||
# used by regrtest
|
||||
support.run_unittest(unittest.test.suite())
|
||||
support.reap_children()
|
||||
|
||||
def load_tests(*_):
|
||||
# used by unittest
|
||||
return unittest.test.suite()
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
support.reap_children()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main()
|
||||
unittest.main()
|
||||
Vendored
+21
-4
@@ -44,11 +44,12 @@ AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
|
||||
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
"""
|
||||
|
||||
__all__ = ['TestResult', 'TestCase', 'TestSuite',
|
||||
__all__ = ['TestResult', 'TestCase', 'IsolatedAsyncioTestCase', 'TestSuite',
|
||||
'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
|
||||
'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
|
||||
'expectedFailure', 'TextTestResult', 'installHandler',
|
||||
'registerResult', 'removeResult', 'removeHandler']
|
||||
'registerResult', 'removeResult', 'removeHandler',
|
||||
'addModuleCleanup']
|
||||
|
||||
# Expose obsolete functions for backwards compatibility
|
||||
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
||||
@@ -56,14 +57,15 @@ __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
||||
__unittest = True
|
||||
|
||||
from .result import TestResult
|
||||
from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf,
|
||||
skipUnless, expectedFailure)
|
||||
from .case import (addModuleCleanup, TestCase, FunctionTestCase, SkipTest, skip,
|
||||
skipIf, skipUnless, expectedFailure)
|
||||
from .suite import BaseTestSuite, TestSuite
|
||||
from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
|
||||
findTestCases)
|
||||
from .main import TestProgram, main
|
||||
from .runner import TextTestRunner, TextTestResult
|
||||
from .signals import installHandler, registerResult, removeResult, removeHandler
|
||||
# IsolatedAsyncioTestCase will be imported lazily.
|
||||
|
||||
# deprecated
|
||||
_TextTestResult = TextTestResult
|
||||
@@ -76,3 +78,18 @@ def load_tests(loader, tests, pattern):
|
||||
# top level directory cached on loader instance
|
||||
this_dir = os.path.dirname(__file__)
|
||||
return loader.discover(start_dir=this_dir, pattern=pattern)
|
||||
|
||||
|
||||
# Lazy import of IsolatedAsyncioTestCase from .async_case
|
||||
# It imports asyncio, which is relatively heavy, but most tests
|
||||
# do not need it.
|
||||
|
||||
def __dir__():
|
||||
return globals().keys() | {'IsolatedAsyncioTestCase'}
|
||||
|
||||
def __getattr__(name):
|
||||
if name == 'IsolatedAsyncioTestCase':
|
||||
global IsolatedAsyncioTestCase
|
||||
from .async_case import IsolatedAsyncioTestCase
|
||||
return IsolatedAsyncioTestCase
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
Vendored
+86
@@ -0,0 +1,86 @@
|
||||
import logging
|
||||
import collections
|
||||
|
||||
from .case import _BaseTestCaseContext
|
||||
|
||||
|
||||
_LoggingWatcher = collections.namedtuple("_LoggingWatcher",
|
||||
["records", "output"])
|
||||
|
||||
class _CapturingHandler(logging.Handler):
|
||||
"""
|
||||
A logging handler capturing all (raw and formatted) logging output.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
logging.Handler.__init__(self)
|
||||
self.watcher = _LoggingWatcher([], [])
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def emit(self, record):
|
||||
self.watcher.records.append(record)
|
||||
msg = self.format(record)
|
||||
self.watcher.output.append(msg)
|
||||
|
||||
|
||||
class _AssertLogsContext(_BaseTestCaseContext):
|
||||
"""A context manager for assertLogs() and assertNoLogs() """
|
||||
|
||||
LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s"
|
||||
|
||||
def __init__(self, test_case, logger_name, level, no_logs):
|
||||
_BaseTestCaseContext.__init__(self, test_case)
|
||||
self.logger_name = logger_name
|
||||
if level:
|
||||
self.level = logging._nameToLevel.get(level, level)
|
||||
else:
|
||||
self.level = logging.INFO
|
||||
self.msg = None
|
||||
self.no_logs = no_logs
|
||||
|
||||
def __enter__(self):
|
||||
if isinstance(self.logger_name, logging.Logger):
|
||||
logger = self.logger = self.logger_name
|
||||
else:
|
||||
logger = self.logger = logging.getLogger(self.logger_name)
|
||||
formatter = logging.Formatter(self.LOGGING_FORMAT)
|
||||
handler = _CapturingHandler()
|
||||
handler.setLevel(self.level)
|
||||
handler.setFormatter(formatter)
|
||||
self.watcher = handler.watcher
|
||||
self.old_handlers = logger.handlers[:]
|
||||
self.old_level = logger.level
|
||||
self.old_propagate = logger.propagate
|
||||
logger.handlers = [handler]
|
||||
logger.setLevel(self.level)
|
||||
logger.propagate = False
|
||||
if self.no_logs:
|
||||
return
|
||||
return handler.watcher
|
||||
|
||||
def __exit__(self, exc_type, exc_value, tb):
|
||||
self.logger.handlers = self.old_handlers
|
||||
self.logger.propagate = self.old_propagate
|
||||
self.logger.setLevel(self.old_level)
|
||||
|
||||
if exc_type is not None:
|
||||
# let unexpected exceptions pass through
|
||||
return False
|
||||
|
||||
if self.no_logs:
|
||||
# assertNoLogs
|
||||
if len(self.watcher.records) > 0:
|
||||
self._raiseFailure(
|
||||
"Unexpected logs found: {!r}".format(
|
||||
self.watcher.output
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
# assertLogs
|
||||
if len(self.watcher.records) == 0:
|
||||
self._raiseFailure(
|
||||
"no logs of level {} or higher triggered on {}"
|
||||
.format(logging.getLevelName(self.level), self.logger.name))
|
||||
Vendored
+170
@@ -0,0 +1,170 @@
|
||||
import asyncio
|
||||
import inspect
|
||||
|
||||
from .case import TestCase
|
||||
|
||||
|
||||
class IsolatedAsyncioTestCase(TestCase):
|
||||
# Names intentionally have a long prefix
|
||||
# to reduce a chance of clashing with user-defined attributes
|
||||
# from inherited test case
|
||||
#
|
||||
# The class doesn't call loop.run_until_complete(self.setUp()) and family
|
||||
# but uses a different approach:
|
||||
# 1. create a long-running task that reads self.setUp()
|
||||
# awaitable from queue along with a future
|
||||
# 2. await the awaitable object passing in and set the result
|
||||
# into the future object
|
||||
# 3. Outer code puts the awaitable and the future object into a queue
|
||||
# with waiting for the future
|
||||
# The trick is necessary because every run_until_complete() call
|
||||
# creates a new task with embedded ContextVar context.
|
||||
# To share contextvars between setUp(), test and tearDown() we need to execute
|
||||
# them inside the same task.
|
||||
|
||||
# Note: the test case modifies event loop policy if the policy was not instantiated
|
||||
# yet.
|
||||
# asyncio.get_event_loop_policy() creates a default policy on demand but never
|
||||
# returns None
|
||||
# I believe this is not an issue in user level tests but python itself for testing
|
||||
# should reset a policy in every test module
|
||||
# by calling asyncio.set_event_loop_policy(None) in tearDownModule()
|
||||
|
||||
def __init__(self, methodName='runTest'):
|
||||
super().__init__(methodName)
|
||||
self._asyncioTestLoop = None
|
||||
self._asyncioCallsQueue = None
|
||||
|
||||
async def asyncSetUp(self):
|
||||
pass
|
||||
|
||||
async def asyncTearDown(self):
|
||||
pass
|
||||
|
||||
def addAsyncCleanup(self, func, /, *args, **kwargs):
|
||||
# A trivial trampoline to addCleanup()
|
||||
# the function exists because it has a different semantics
|
||||
# and signature:
|
||||
# addCleanup() accepts regular functions
|
||||
# but addAsyncCleanup() accepts coroutines
|
||||
#
|
||||
# We intentionally don't add inspect.iscoroutinefunction() check
|
||||
# for func argument because there is no way
|
||||
# to check for async function reliably:
|
||||
# 1. It can be "async def func()" itself
|
||||
# 2. Class can implement "async def __call__()" method
|
||||
# 3. Regular "def func()" that returns awaitable object
|
||||
self.addCleanup(*(func, *args), **kwargs)
|
||||
|
||||
def _callSetUp(self):
|
||||
self.setUp()
|
||||
self._callAsync(self.asyncSetUp)
|
||||
|
||||
def _callTestMethod(self, method):
|
||||
self._callMaybeAsync(method)
|
||||
|
||||
def _callTearDown(self):
|
||||
self._callAsync(self.asyncTearDown)
|
||||
self.tearDown()
|
||||
|
||||
def _callCleanup(self, function, *args, **kwargs):
|
||||
self._callMaybeAsync(function, *args, **kwargs)
|
||||
|
||||
def _callAsync(self, func, /, *args, **kwargs):
|
||||
assert self._asyncioTestLoop is not None, 'asyncio test loop is not initialized'
|
||||
ret = func(*args, **kwargs)
|
||||
assert inspect.isawaitable(ret), f'{func!r} returned non-awaitable'
|
||||
fut = self._asyncioTestLoop.create_future()
|
||||
self._asyncioCallsQueue.put_nowait((fut, ret))
|
||||
return self._asyncioTestLoop.run_until_complete(fut)
|
||||
|
||||
def _callMaybeAsync(self, func, /, *args, **kwargs):
|
||||
assert self._asyncioTestLoop is not None, 'asyncio test loop is not initialized'
|
||||
ret = func(*args, **kwargs)
|
||||
if inspect.isawaitable(ret):
|
||||
fut = self._asyncioTestLoop.create_future()
|
||||
self._asyncioCallsQueue.put_nowait((fut, ret))
|
||||
return self._asyncioTestLoop.run_until_complete(fut)
|
||||
else:
|
||||
return ret
|
||||
|
||||
async def _asyncioLoopRunner(self, fut):
|
||||
self._asyncioCallsQueue = queue = asyncio.Queue()
|
||||
fut.set_result(None)
|
||||
while True:
|
||||
query = await queue.get()
|
||||
queue.task_done()
|
||||
if query is None:
|
||||
return
|
||||
fut, awaitable = query
|
||||
try:
|
||||
ret = await awaitable
|
||||
if not fut.cancelled():
|
||||
fut.set_result(ret)
|
||||
except (SystemExit, KeyboardInterrupt):
|
||||
raise
|
||||
except (BaseException, asyncio.CancelledError) as ex:
|
||||
if not fut.cancelled():
|
||||
fut.set_exception(ex)
|
||||
|
||||
def _setupAsyncioLoop(self):
|
||||
assert self._asyncioTestLoop is None, 'asyncio test loop already initialized'
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
loop.set_debug(True)
|
||||
self._asyncioTestLoop = loop
|
||||
fut = loop.create_future()
|
||||
self._asyncioCallsTask = loop.create_task(self._asyncioLoopRunner(fut))
|
||||
loop.run_until_complete(fut)
|
||||
|
||||
def _tearDownAsyncioLoop(self):
|
||||
assert self._asyncioTestLoop is not None, 'asyncio test loop is not initialized'
|
||||
loop = self._asyncioTestLoop
|
||||
self._asyncioTestLoop = None
|
||||
self._asyncioCallsQueue.put_nowait(None)
|
||||
loop.run_until_complete(self._asyncioCallsQueue.join())
|
||||
|
||||
try:
|
||||
# cancel all tasks
|
||||
to_cancel = asyncio.all_tasks(loop)
|
||||
if not to_cancel:
|
||||
return
|
||||
|
||||
for task in to_cancel:
|
||||
task.cancel()
|
||||
|
||||
loop.run_until_complete(
|
||||
asyncio.gather(*to_cancel, return_exceptions=True))
|
||||
|
||||
for task in to_cancel:
|
||||
if task.cancelled():
|
||||
continue
|
||||
if task.exception() is not None:
|
||||
loop.call_exception_handler({
|
||||
'message': 'unhandled exception during test shutdown',
|
||||
'exception': task.exception(),
|
||||
'task': task,
|
||||
})
|
||||
# shutdown asyncgens
|
||||
loop.run_until_complete(loop.shutdown_asyncgens())
|
||||
finally:
|
||||
# Prevent our executor environment from leaking to future tests.
|
||||
loop.run_until_complete(loop.shutdown_default_executor())
|
||||
asyncio.set_event_loop(None)
|
||||
loop.close()
|
||||
|
||||
def run(self, result=None):
|
||||
self._setupAsyncioLoop()
|
||||
try:
|
||||
return super().run(result)
|
||||
finally:
|
||||
self._tearDownAsyncioLoop()
|
||||
|
||||
def debug(self):
|
||||
self._setupAsyncioLoop()
|
||||
super().debug()
|
||||
self._tearDownAsyncioLoop()
|
||||
|
||||
def __del__(self):
|
||||
if self._asyncioTestLoop is not None:
|
||||
self._tearDownAsyncioLoop()
|
||||
Vendored
+146
-143
@@ -3,7 +3,6 @@
|
||||
import sys
|
||||
import functools
|
||||
import difflib
|
||||
import logging
|
||||
import pprint
|
||||
import re
|
||||
import warnings
|
||||
@@ -85,6 +84,30 @@ class _Outcome(object):
|
||||
def _id(obj):
|
||||
return obj
|
||||
|
||||
|
||||
_module_cleanups = []
|
||||
def addModuleCleanup(function, /, *args, **kwargs):
|
||||
"""Same as addCleanup, except the cleanup items are called even if
|
||||
setUpModule fails (unlike tearDownModule)."""
|
||||
_module_cleanups.append((function, args, kwargs))
|
||||
|
||||
|
||||
def doModuleCleanups():
|
||||
"""Execute all module cleanup functions. Normally called for you after
|
||||
tearDownModule."""
|
||||
exceptions = []
|
||||
while _module_cleanups:
|
||||
function, args, kwargs = _module_cleanups.pop()
|
||||
try:
|
||||
function(*args, **kwargs)
|
||||
except Exception as exc:
|
||||
exceptions.append(exc)
|
||||
if exceptions:
|
||||
# Swallows all but first exception. If a multi-exception handler
|
||||
# gets written we should use that here instead.
|
||||
raise exceptions[0]
|
||||
|
||||
|
||||
def skip(reason):
|
||||
"""
|
||||
Unconditionally skip a test.
|
||||
@@ -99,6 +122,10 @@ def skip(reason):
|
||||
test_item.__unittest_skip__ = True
|
||||
test_item.__unittest_skip_why__ = reason
|
||||
return test_item
|
||||
if isinstance(reason, types.FunctionType):
|
||||
test_item = reason
|
||||
reason = ''
|
||||
return decorator(test_item)
|
||||
return decorator
|
||||
|
||||
def skipIf(condition, reason):
|
||||
@@ -158,16 +185,11 @@ class _AssertRaisesBaseContext(_BaseTestCaseContext):
|
||||
if not _is_subtype(self.expected, self._base_type):
|
||||
raise TypeError('%s() arg 1 must be %s' %
|
||||
(name, self._base_type_str))
|
||||
if args and args[0] is None:
|
||||
warnings.warn("callable is None",
|
||||
DeprecationWarning, 3)
|
||||
args = ()
|
||||
if not args:
|
||||
self.msg = kwargs.pop('msg', None)
|
||||
if kwargs:
|
||||
warnings.warn('%r is an invalid keyword argument for '
|
||||
'this function' % next(iter(kwargs)),
|
||||
DeprecationWarning, 3)
|
||||
raise TypeError('%r is an invalid keyword argument for '
|
||||
'this function' % (next(iter(kwargs)),))
|
||||
return self
|
||||
|
||||
callable_obj, *args = args
|
||||
@@ -230,7 +252,7 @@ class _AssertWarnsContext(_AssertRaisesBaseContext):
|
||||
def __enter__(self):
|
||||
# The __warningregistry__'s need to be in a pristine state for tests
|
||||
# to work properly.
|
||||
for v in sys.modules.values():
|
||||
for v in list(sys.modules.values()):
|
||||
if getattr(v, '__warningregistry__', None):
|
||||
v.__warningregistry__ = {}
|
||||
self.warnings_manager = warnings.catch_warnings(record=True)
|
||||
@@ -273,74 +295,6 @@ class _AssertWarnsContext(_AssertRaisesBaseContext):
|
||||
self._raiseFailure("{} not triggered".format(exc_name))
|
||||
|
||||
|
||||
|
||||
_LoggingWatcher = collections.namedtuple("_LoggingWatcher",
|
||||
["records", "output"])
|
||||
|
||||
|
||||
class _CapturingHandler(logging.Handler):
|
||||
"""
|
||||
A logging handler capturing all (raw and formatted) logging output.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
logging.Handler.__init__(self)
|
||||
self.watcher = _LoggingWatcher([], [])
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def emit(self, record):
|
||||
self.watcher.records.append(record)
|
||||
msg = self.format(record)
|
||||
self.watcher.output.append(msg)
|
||||
|
||||
|
||||
|
||||
class _AssertLogsContext(_BaseTestCaseContext):
|
||||
"""A context manager used to implement TestCase.assertLogs()."""
|
||||
|
||||
LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s"
|
||||
|
||||
def __init__(self, test_case, logger_name, level):
|
||||
_BaseTestCaseContext.__init__(self, test_case)
|
||||
self.logger_name = logger_name
|
||||
if level:
|
||||
self.level = logging._nameToLevel.get(level, level)
|
||||
else:
|
||||
self.level = logging.INFO
|
||||
self.msg = None
|
||||
|
||||
def __enter__(self):
|
||||
if isinstance(self.logger_name, logging.Logger):
|
||||
logger = self.logger = self.logger_name
|
||||
else:
|
||||
logger = self.logger = logging.getLogger(self.logger_name)
|
||||
formatter = logging.Formatter(self.LOGGING_FORMAT)
|
||||
handler = _CapturingHandler()
|
||||
handler.setFormatter(formatter)
|
||||
self.watcher = handler.watcher
|
||||
self.old_handlers = logger.handlers[:]
|
||||
self.old_level = logger.level
|
||||
self.old_propagate = logger.propagate
|
||||
logger.handlers = [handler]
|
||||
logger.setLevel(self.level)
|
||||
logger.propagate = False
|
||||
return handler.watcher
|
||||
|
||||
def __exit__(self, exc_type, exc_value, tb):
|
||||
self.logger.handlers = self.old_handlers
|
||||
self.logger.propagate = self.old_propagate
|
||||
self.logger.setLevel(self.old_level)
|
||||
if exc_type is not None:
|
||||
# let unexpected exceptions pass through
|
||||
return False
|
||||
if len(self.watcher.records) == 0:
|
||||
self._raiseFailure(
|
||||
"no logs of level {} or higher triggered on {}"
|
||||
.format(logging.getLevelName(self.level), self.logger.name))
|
||||
|
||||
|
||||
class _OrderedChainMap(collections.ChainMap):
|
||||
def __iter__(self):
|
||||
seen = set()
|
||||
@@ -398,6 +352,8 @@ class TestCase(object):
|
||||
|
||||
_classSetupFailed = False
|
||||
|
||||
_class_cleanups = []
|
||||
|
||||
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
|
||||
@@ -445,7 +401,7 @@ class TestCase(object):
|
||||
"""
|
||||
self._type_equality_funcs[typeobj] = function
|
||||
|
||||
def addCleanup(self, function, *args, **kwargs):
|
||||
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.
|
||||
@@ -453,6 +409,12 @@ class TestCase(object):
|
||||
Cleanup items are called even if setUp fails (unlike tearDown)."""
|
||||
self._cleanups.append((function, args, kwargs))
|
||||
|
||||
@classmethod
|
||||
def addClassCleanup(cls, function, /, *args, **kwargs):
|
||||
"""Same as addCleanup, except the cleanup items are called even if
|
||||
setUpClass fails (unlike tearDownClass)."""
|
||||
cls._class_cleanups.append((function, args, kwargs))
|
||||
|
||||
def setUp(self):
|
||||
"Hook method for setting up the test fixture before exercising it."
|
||||
pass
|
||||
@@ -483,7 +445,7 @@ class TestCase(object):
|
||||
the specified test method's docstring.
|
||||
"""
|
||||
doc = self._testMethodDoc
|
||||
return doc and doc.split("\n")[0].strip() or None
|
||||
return doc.strip().split("\n")[0].strip() if doc else None
|
||||
|
||||
|
||||
def id(self):
|
||||
@@ -522,7 +484,7 @@ class TestCase(object):
|
||||
case as failed but resumes execution at the end of the enclosed
|
||||
block, allowing further test code to be executed.
|
||||
"""
|
||||
if not self._outcome.result_supports_subtests:
|
||||
if self._outcome is None or not self._outcome.result_supports_subtests:
|
||||
yield
|
||||
return
|
||||
parent = self._subtest
|
||||
@@ -580,74 +542,84 @@ class TestCase(object):
|
||||
else:
|
||||
addUnexpectedSuccess(self)
|
||||
|
||||
def _callSetUp(self):
|
||||
self.setUp()
|
||||
|
||||
def _callTestMethod(self, method):
|
||||
method()
|
||||
|
||||
def _callTearDown(self):
|
||||
self.tearDown()
|
||||
|
||||
def _callCleanup(self, function, /, *args, **kwargs):
|
||||
function(*args, **kwargs)
|
||||
|
||||
def run(self, result=None):
|
||||
orig_result = result
|
||||
if result is None:
|
||||
result = self.defaultTestResult()
|
||||
startTestRun = getattr(result, 'startTestRun', None)
|
||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||
if startTestRun is not None:
|
||||
startTestRun()
|
||||
else:
|
||||
stopTestRun = None
|
||||
|
||||
result.startTest(self)
|
||||
|
||||
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.
|
||||
try:
|
||||
try:
|
||||
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, self, skip_why)
|
||||
finally:
|
||||
result.stopTest(self)
|
||||
return
|
||||
expecting_failure_method = getattr(testMethod,
|
||||
"__unittest_expecting_failure__", False)
|
||||
expecting_failure_class = getattr(self,
|
||||
"__unittest_expecting_failure__", False)
|
||||
expecting_failure = expecting_failure_class or expecting_failure_method
|
||||
outcome = _Outcome(result)
|
||||
try:
|
||||
self._outcome = outcome
|
||||
return result
|
||||
|
||||
expecting_failure = (
|
||||
getattr(self, "__unittest_expecting_failure__", False) or
|
||||
getattr(testMethod, "__unittest_expecting_failure__", False)
|
||||
)
|
||||
outcome = _Outcome(result)
|
||||
try:
|
||||
self._outcome = outcome
|
||||
|
||||
with outcome.testPartExecutor(self):
|
||||
self.setUp()
|
||||
if outcome.success:
|
||||
outcome.expecting_failure = expecting_failure
|
||||
with outcome.testPartExecutor(self, isTest=True):
|
||||
testMethod()
|
||||
outcome.expecting_failure = False
|
||||
with outcome.testPartExecutor(self):
|
||||
self.tearDown()
|
||||
self._callSetUp()
|
||||
if outcome.success:
|
||||
outcome.expecting_failure = expecting_failure
|
||||
with outcome.testPartExecutor(self, isTest=True):
|
||||
self._callTestMethod(testMethod)
|
||||
outcome.expecting_failure = False
|
||||
with outcome.testPartExecutor(self):
|
||||
self._callTearDown()
|
||||
|
||||
self.doCleanups()
|
||||
for test, reason in outcome.skipped:
|
||||
self._addSkip(result, test, reason)
|
||||
self._feedErrorsToResult(result, outcome.errors)
|
||||
if outcome.success:
|
||||
if expecting_failure:
|
||||
if outcome.expectedFailure:
|
||||
self._addExpectedFailure(result, outcome.expectedFailure)
|
||||
self.doCleanups()
|
||||
for test, reason in outcome.skipped:
|
||||
self._addSkip(result, test, reason)
|
||||
self._feedErrorsToResult(result, outcome.errors)
|
||||
if outcome.success:
|
||||
if expecting_failure:
|
||||
if outcome.expectedFailure:
|
||||
self._addExpectedFailure(result, outcome.expectedFailure)
|
||||
else:
|
||||
self._addUnexpectedSuccess(result)
|
||||
else:
|
||||
self._addUnexpectedSuccess(result)
|
||||
else:
|
||||
result.addSuccess(self)
|
||||
return result
|
||||
result.addSuccess(self)
|
||||
return result
|
||||
finally:
|
||||
# explicitly break reference cycles:
|
||||
# outcome.errors -> frame -> outcome -> outcome.errors
|
||||
# outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
|
||||
outcome.errors.clear()
|
||||
outcome.expectedFailure = None
|
||||
|
||||
# clear the outcome, no more needed
|
||||
self._outcome = None
|
||||
|
||||
finally:
|
||||
result.stopTest(self)
|
||||
if orig_result is None:
|
||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||
if stopTestRun is not None:
|
||||
stopTestRun()
|
||||
|
||||
# explicitly break reference cycles:
|
||||
# outcome.errors -> frame -> outcome -> outcome.errors
|
||||
# outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
|
||||
outcome.errors.clear()
|
||||
outcome.expectedFailure = None
|
||||
|
||||
# clear the outcome, no more needed
|
||||
self._outcome = None
|
||||
if stopTestRun is not None:
|
||||
stopTestRun()
|
||||
|
||||
def doCleanups(self):
|
||||
"""Execute all cleanup functions. Normally called for you after
|
||||
@@ -656,23 +628,43 @@ class TestCase(object):
|
||||
while self._cleanups:
|
||||
function, args, kwargs = self._cleanups.pop()
|
||||
with outcome.testPartExecutor(self):
|
||||
function(*args, **kwargs)
|
||||
self._callCleanup(function, *args, **kwargs)
|
||||
|
||||
# return this for backwards compatibility
|
||||
# even though we no longer us it internally
|
||||
# even though we no longer use it internally
|
||||
return outcome.success
|
||||
|
||||
@classmethod
|
||||
def doClassCleanups(cls):
|
||||
"""Execute all class cleanup functions. Normally called for you after
|
||||
tearDownClass."""
|
||||
cls.tearDown_exceptions = []
|
||||
while cls._class_cleanups:
|
||||
function, args, kwargs = cls._class_cleanups.pop()
|
||||
try:
|
||||
function(*args, **kwargs)
|
||||
except Exception:
|
||||
cls.tearDown_exceptions.append(sys.exc_info())
|
||||
|
||||
def __call__(self, *args, **kwds):
|
||||
return self.run(*args, **kwds)
|
||||
|
||||
def debug(self):
|
||||
"""Run the test without collecting errors in a TestResult"""
|
||||
self.setUp()
|
||||
getattr(self, self._testMethodName)()
|
||||
self.tearDown()
|
||||
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__', ''))
|
||||
raise SkipTest(skip_why)
|
||||
|
||||
self._callSetUp()
|
||||
self._callTestMethod(testMethod)
|
||||
self._callTearDown()
|
||||
while self._cleanups:
|
||||
function, args, kwargs = self._cleanups.pop(-1)
|
||||
function(*args, **kwargs)
|
||||
function, args, kwargs = self._cleanups.pop()
|
||||
self._callCleanup(function, *args, **kwargs)
|
||||
|
||||
def skipTest(self, reason):
|
||||
"""Skip this test."""
|
||||
@@ -799,7 +791,18 @@ class TestCase(object):
|
||||
self.assertEqual(cm.output, ['INFO:foo:first message',
|
||||
'ERROR:foo.bar:second message'])
|
||||
"""
|
||||
return _AssertLogsContext(self, logger, level)
|
||||
# Lazy import to avoid importing logging if it is not needed.
|
||||
from ._log import _AssertLogsContext
|
||||
return _AssertLogsContext(self, logger, level, no_logs=False)
|
||||
|
||||
def assertNoLogs(self, logger=None, level=None):
|
||||
""" Fail unless no log messages of level *level* or higher are emitted
|
||||
on *logger_name* or its children.
|
||||
|
||||
This method must be used as a context manager.
|
||||
"""
|
||||
from ._log import _AssertLogsContext
|
||||
return _AssertLogsContext(self, logger, level, no_logs=True)
|
||||
|
||||
def _getAssertEqualityFunc(self, first, second):
|
||||
"""Get a detailed comparison function for the types of the two args.
|
||||
@@ -1143,7 +1146,8 @@ class TestCase(object):
|
||||
def assertDictContainsSubset(self, subset, dictionary, msg=None):
|
||||
"""Checks whether dictionary is a superset of subset."""
|
||||
warnings.warn('assertDictContainsSubset is deprecated',
|
||||
DeprecationWarning)
|
||||
DeprecationWarning,
|
||||
stacklevel=2)
|
||||
missing = []
|
||||
mismatched = []
|
||||
for key, value in subset.items():
|
||||
@@ -1170,9 +1174,8 @@ class TestCase(object):
|
||||
|
||||
|
||||
def assertCountEqual(self, first, second, msg=None):
|
||||
"""An unordered sequence comparison asserting that the same elements,
|
||||
regardless of order. If the same element occurs more than once,
|
||||
it verifies that the elements occur the same number of times.
|
||||
"""Asserts that two iterables have the same elements, the same number of
|
||||
times, without regard to order.
|
||||
|
||||
self.assertEqual(Counter(list(first)),
|
||||
Counter(list(second)))
|
||||
|
||||
Vendored
+3
-1
@@ -229,7 +229,9 @@ class TestLoader(object):
|
||||
testFunc = getattr(testCaseClass, attrname)
|
||||
if not callable(testFunc):
|
||||
return False
|
||||
fullName = '%s.%s' % (testCaseClass.__module__, testFunc.__qualname__)
|
||||
fullName = f'%s.%s.%s' % (
|
||||
testCaseClass.__module__, testCaseClass.__qualname__, attrname
|
||||
)
|
||||
return self.testNamePatterns is None or \
|
||||
any(fnmatchcase(fullName, pattern) for pattern in self.testNamePatterns)
|
||||
testFnNames = list(filter(shouldIncludeMethod, dir(testCaseClass)))
|
||||
|
||||
Vendored
+1
-1
@@ -39,7 +39,7 @@ def _convert_name(name):
|
||||
name = rel_path
|
||||
# on Windows both '\' and '/' are used as path
|
||||
# separators. Better to replace both than rely on os.path.sep
|
||||
return name[:-3].replace('\\', '.').replace('/', '.')
|
||||
return os.path.normpath(name)[:-3].replace('\\', '.').replace('/', '.')
|
||||
return name
|
||||
|
||||
def _convert_names(names):
|
||||
|
||||
Vendored
+835
-327
File diff suppressed because it is too large.
Load diff
Vendored
+41
-15
@@ -161,7 +161,7 @@ class TestResult(object):
|
||||
"""Tells whether or not this result was a success."""
|
||||
# The hasattr check is for test_result's OldResult test. That
|
||||
# way this method works on objects that lack the attribute.
|
||||
# (where would such result intances come from? old stored pickles?)
|
||||
# (where would such result instances come from? old stored pickles?)
|
||||
return ((len(self.failures) == len(self.errors) == 0) and
|
||||
(not hasattr(self, 'unexpectedSuccesses') or
|
||||
len(self.unexpectedSuccesses) == 0))
|
||||
@@ -173,17 +173,10 @@ class TestResult(object):
|
||||
def _exc_info_to_string(self, err, test):
|
||||
"""Converts a sys.exc_info()-style tuple of values into a string."""
|
||||
exctype, value, tb = err
|
||||
# Skip test runner traceback levels
|
||||
while tb and self._is_relevant_tb_level(tb):
|
||||
tb = tb.tb_next
|
||||
|
||||
if exctype is test.failureException:
|
||||
# Skip assert*() traceback levels
|
||||
length = self._count_relevant_tb_levels(tb)
|
||||
else:
|
||||
length = None
|
||||
tb = self._clean_tracebacks(exctype, value, tb, test)
|
||||
tb_e = traceback.TracebackException(
|
||||
exctype, value, tb, limit=length, capture_locals=self.tb_locals)
|
||||
exctype, value, tb,
|
||||
capture_locals=self.tb_locals, compact=True)
|
||||
msgLines = list(tb_e.format())
|
||||
|
||||
if self.buffer:
|
||||
@@ -199,16 +192,49 @@ class TestResult(object):
|
||||
msgLines.append(STDERR_LINE % error)
|
||||
return ''.join(msgLines)
|
||||
|
||||
def _clean_tracebacks(self, exctype, value, tb, test):
|
||||
ret = None
|
||||
first = True
|
||||
excs = [(exctype, value, tb)]
|
||||
while excs:
|
||||
(exctype, value, tb) = excs.pop()
|
||||
# Skip test runner traceback levels
|
||||
while tb and self._is_relevant_tb_level(tb):
|
||||
tb = tb.tb_next
|
||||
|
||||
# Skip assert*() traceback levels
|
||||
if exctype is test.failureException:
|
||||
self._remove_unittest_tb_frames(tb)
|
||||
|
||||
if first:
|
||||
ret = tb
|
||||
first = False
|
||||
else:
|
||||
value.__traceback__ = tb
|
||||
|
||||
if value is not None:
|
||||
for c in (value.__cause__, value.__context__):
|
||||
if c is not None:
|
||||
excs.append((type(c), c, c.__traceback__))
|
||||
return ret
|
||||
|
||||
def _is_relevant_tb_level(self, tb):
|
||||
return '__unittest' in tb.tb_frame.f_globals
|
||||
|
||||
def _count_relevant_tb_levels(self, tb):
|
||||
length = 0
|
||||
def _remove_unittest_tb_frames(self, tb):
|
||||
'''Truncates usercode tb at the first unittest frame.
|
||||
|
||||
If the first frame of the traceback is in user code,
|
||||
the prefix up to the first unittest frame is returned.
|
||||
If the first frame is already in the unittest module,
|
||||
the traceback is not modified.
|
||||
'''
|
||||
prev = None
|
||||
while tb and not self._is_relevant_tb_level(tb):
|
||||
length += 1
|
||||
prev = tb
|
||||
tb = tb.tb_next
|
||||
return length
|
||||
if prev is not None:
|
||||
prev.tb_next = None
|
||||
|
||||
def __repr__(self):
|
||||
return ("<%s run=%i errors=%i failures=%i>" %
|
||||
|
||||
Vendored
+11
-2
@@ -59,6 +59,7 @@ class TextTestResult(result.TestResult):
|
||||
super(TextTestResult, self).addSuccess(test)
|
||||
if self.showAll:
|
||||
self.stream.writeln("ok")
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write('.')
|
||||
self.stream.flush()
|
||||
@@ -67,6 +68,7 @@ class TextTestResult(result.TestResult):
|
||||
super(TextTestResult, self).addError(test, err)
|
||||
if self.showAll:
|
||||
self.stream.writeln("ERROR")
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write('E')
|
||||
self.stream.flush()
|
||||
@@ -75,6 +77,7 @@ class TextTestResult(result.TestResult):
|
||||
super(TextTestResult, self).addFailure(test, err)
|
||||
if self.showAll:
|
||||
self.stream.writeln("FAIL")
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write('F')
|
||||
self.stream.flush()
|
||||
@@ -83,6 +86,7 @@ class TextTestResult(result.TestResult):
|
||||
super(TextTestResult, self).addSkip(test, reason)
|
||||
if self.showAll:
|
||||
self.stream.writeln("skipped {0!r}".format(reason))
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write("s")
|
||||
self.stream.flush()
|
||||
@@ -91,6 +95,7 @@ class TextTestResult(result.TestResult):
|
||||
super(TextTestResult, self).addExpectedFailure(test, err)
|
||||
if self.showAll:
|
||||
self.stream.writeln("expected failure")
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write("x")
|
||||
self.stream.flush()
|
||||
@@ -99,6 +104,7 @@ class TextTestResult(result.TestResult):
|
||||
super(TextTestResult, self).addUnexpectedSuccess(test)
|
||||
if self.showAll:
|
||||
self.stream.writeln("unexpected success")
|
||||
self.stream.flush()
|
||||
elif self.dots:
|
||||
self.stream.write("u")
|
||||
self.stream.flush()
|
||||
@@ -106,6 +112,7 @@ class TextTestResult(result.TestResult):
|
||||
def printErrors(self):
|
||||
if self.dots or self.showAll:
|
||||
self.stream.writeln()
|
||||
self.stream.flush()
|
||||
self.printErrorList('ERROR', self.errors)
|
||||
self.printErrorList('FAIL', self.failures)
|
||||
|
||||
@@ -115,6 +122,7 @@ class TextTestResult(result.TestResult):
|
||||
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
|
||||
self.stream.writeln(self.separator2)
|
||||
self.stream.writeln("%s" % err)
|
||||
self.stream.flush()
|
||||
|
||||
|
||||
class TextTestRunner(object):
|
||||
@@ -168,7 +176,7 @@ class TextTestRunner(object):
|
||||
warnings.filterwarnings('module',
|
||||
category=DeprecationWarning,
|
||||
message=r'Please use assert\w+ instead.')
|
||||
startTime = time.time()
|
||||
startTime = time.perf_counter()
|
||||
startTestRun = getattr(result, 'startTestRun', None)
|
||||
if startTestRun is not None:
|
||||
startTestRun()
|
||||
@@ -178,7 +186,7 @@ class TextTestRunner(object):
|
||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||
if stopTestRun is not None:
|
||||
stopTestRun()
|
||||
stopTime = time.time()
|
||||
stopTime = time.perf_counter()
|
||||
timeTaken = stopTime - startTime
|
||||
result.printErrors()
|
||||
if hasattr(result, 'separator2'):
|
||||
@@ -218,4 +226,5 @@ class TextTestRunner(object):
|
||||
self.stream.writeln(" (%s)" % (", ".join(infos),))
|
||||
else:
|
||||
self.stream.write("\n")
|
||||
self.stream.flush()
|
||||
return result
|
||||
Vendored
+96
-38
@@ -149,6 +149,7 @@ class TestSuite(BaseTestSuite):
|
||||
if getattr(currentClass, "__unittest_skip__", False):
|
||||
return
|
||||
|
||||
failed = False
|
||||
try:
|
||||
currentClass._classSetupFailed = False
|
||||
except TypeError:
|
||||
@@ -157,17 +158,30 @@ class TestSuite(BaseTestSuite):
|
||||
pass
|
||||
|
||||
setUpClass = getattr(currentClass, 'setUpClass', None)
|
||||
doClassCleanups = getattr(currentClass, 'doClassCleanups', None)
|
||||
if setUpClass is not None:
|
||||
_call_if_exists(result, '_setupStdout')
|
||||
try:
|
||||
setUpClass()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
currentClass._classSetupFailed = True
|
||||
className = util.strclass(currentClass)
|
||||
errorName = 'setUpClass (%s)' % className
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
try:
|
||||
setUpClass()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
failed = True
|
||||
try:
|
||||
currentClass._classSetupFailed = True
|
||||
except TypeError:
|
||||
pass
|
||||
className = util.strclass(currentClass)
|
||||
self._createClassOrModuleLevelException(result, e,
|
||||
'setUpClass',
|
||||
className)
|
||||
if failed and doClassCleanups is not None:
|
||||
doClassCleanups()
|
||||
for exc_info in currentClass.tearDown_exceptions:
|
||||
self._createClassOrModuleLevelException(
|
||||
result, exc_info[1], 'setUpClass', className,
|
||||
info=exc_info)
|
||||
finally:
|
||||
_call_if_exists(result, '_restoreStdout')
|
||||
|
||||
@@ -197,23 +211,41 @@ class TestSuite(BaseTestSuite):
|
||||
if setUpModule is not None:
|
||||
_call_if_exists(result, '_setupStdout')
|
||||
try:
|
||||
setUpModule()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
result._moduleSetUpFailed = True
|
||||
errorName = 'setUpModule (%s)' % currentModule
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
try:
|
||||
setUpModule()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
result._moduleSetUpFailed = True
|
||||
self._createClassOrModuleLevelException(result, e,
|
||||
'setUpModule',
|
||||
currentModule)
|
||||
if result._moduleSetUpFailed:
|
||||
try:
|
||||
case.doModuleCleanups()
|
||||
except Exception as e:
|
||||
self._createClassOrModuleLevelException(result, e,
|
||||
'setUpModule',
|
||||
currentModule)
|
||||
finally:
|
||||
_call_if_exists(result, '_restoreStdout')
|
||||
|
||||
def _addClassOrModuleLevelException(self, result, exception, errorName):
|
||||
def _createClassOrModuleLevelException(self, result, exc, method_name,
|
||||
parent, info=None):
|
||||
errorName = f'{method_name} ({parent})'
|
||||
self._addClassOrModuleLevelException(result, exc, errorName, info)
|
||||
|
||||
def _addClassOrModuleLevelException(self, result, exception, errorName,
|
||||
info=None):
|
||||
error = _ErrorHolder(errorName)
|
||||
addSkip = getattr(result, 'addSkip', None)
|
||||
if addSkip is not None and isinstance(exception, case.SkipTest):
|
||||
addSkip(error, str(exception))
|
||||
else:
|
||||
result.addError(error, sys.exc_info())
|
||||
if not info:
|
||||
result.addError(error, sys.exc_info())
|
||||
else:
|
||||
result.addError(error, info)
|
||||
|
||||
def _handleModuleTearDown(self, result):
|
||||
previousModule = self._get_previous_module(result)
|
||||
@@ -227,23 +259,33 @@ class TestSuite(BaseTestSuite):
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
tearDownModule = getattr(module, 'tearDownModule', None)
|
||||
if tearDownModule is not None:
|
||||
_call_if_exists(result, '_setupStdout')
|
||||
_call_if_exists(result, '_setupStdout')
|
||||
try:
|
||||
tearDownModule = getattr(module, 'tearDownModule', None)
|
||||
if tearDownModule is not None:
|
||||
try:
|
||||
tearDownModule()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
self._createClassOrModuleLevelException(result, e,
|
||||
'tearDownModule',
|
||||
previousModule)
|
||||
try:
|
||||
tearDownModule()
|
||||
case.doModuleCleanups()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
errorName = 'tearDownModule (%s)' % previousModule
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
finally:
|
||||
_call_if_exists(result, '_restoreStdout')
|
||||
self._createClassOrModuleLevelException(result, e,
|
||||
'tearDownModule',
|
||||
previousModule)
|
||||
finally:
|
||||
_call_if_exists(result, '_restoreStdout')
|
||||
|
||||
def _tearDownPreviousClass(self, test, result):
|
||||
previousClass = getattr(result, '_previousTestClass', None)
|
||||
currentClass = test.__class__
|
||||
if currentClass == previousClass:
|
||||
if currentClass == previousClass or previousClass is None:
|
||||
return
|
||||
if getattr(previousClass, '_classSetupFailed', False):
|
||||
return
|
||||
@@ -253,18 +295,34 @@ class TestSuite(BaseTestSuite):
|
||||
return
|
||||
|
||||
tearDownClass = getattr(previousClass, 'tearDownClass', None)
|
||||
if tearDownClass is not None:
|
||||
_call_if_exists(result, '_setupStdout')
|
||||
try:
|
||||
tearDownClass()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
className = util.strclass(previousClass)
|
||||
errorName = 'tearDownClass (%s)' % className
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
finally:
|
||||
_call_if_exists(result, '_restoreStdout')
|
||||
doClassCleanups = getattr(previousClass, 'doClassCleanups', None)
|
||||
if tearDownClass is None and doClassCleanups is None:
|
||||
return
|
||||
|
||||
_call_if_exists(result, '_setupStdout')
|
||||
try:
|
||||
if tearDownClass is not None:
|
||||
try:
|
||||
tearDownClass()
|
||||
except Exception as e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
className = util.strclass(previousClass)
|
||||
self._createClassOrModuleLevelException(result, e,
|
||||
'tearDownClass',
|
||||
className)
|
||||
if doClassCleanups is not None:
|
||||
doClassCleanups()
|
||||
for exc_info in previousClass.tearDown_exceptions:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise exc_info[1]
|
||||
className = util.strclass(previousClass)
|
||||
self._createClassOrModuleLevelException(result, exc_info[1],
|
||||
'tearDownClass',
|
||||
className,
|
||||
info=exc_info)
|
||||
finally:
|
||||
_call_if_exists(result, '_restoreStdout')
|
||||
|
||||
|
||||
class _ErrorHolder(object):
|
||||
|
||||
Vendored
+3
@@ -2,6 +2,7 @@ import datetime
|
||||
import warnings
|
||||
import weakref
|
||||
import unittest
|
||||
from test.support import gc_collect
|
||||
from itertools import product
|
||||
|
||||
|
||||
@@ -124,8 +125,10 @@ class Test_Assertions(unittest.TestCase):
|
||||
self.foo()
|
||||
|
||||
Foo("test_functional").run()
|
||||
gc_collect() # For PyPy or other GCs.
|
||||
self.assertIsNone(wr())
|
||||
Foo("test_with").run()
|
||||
gc_collect() # For PyPy or other GCs.
|
||||
self.assertIsNone(wr())
|
||||
|
||||
def testAssertNotRegex(self):
|
||||
|
||||
Vendored
+346
@@ -0,0 +1,346 @@
|
||||
import asyncio
|
||||
import unittest
|
||||
from test import support
|
||||
|
||||
|
||||
class MyException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
asyncio.set_event_loop_policy(None)
|
||||
|
||||
|
||||
class TestAsyncCase(unittest.TestCase):
|
||||
maxDiff = None
|
||||
|
||||
def tearDown(self):
|
||||
# Ensure that IsolatedAsyncioTestCase instances are destroyed before
|
||||
# starting a new event loop
|
||||
support.gc_collect()
|
||||
|
||||
def test_full_cycle(self):
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
def setUp(self):
|
||||
self.assertEqual(events, [])
|
||||
events.append('setUp')
|
||||
|
||||
async def asyncSetUp(self):
|
||||
self.assertEqual(events, ['setUp'])
|
||||
events.append('asyncSetUp')
|
||||
self.addAsyncCleanup(self.on_cleanup1)
|
||||
|
||||
async def test_func(self):
|
||||
self.assertEqual(events, ['setUp',
|
||||
'asyncSetUp'])
|
||||
events.append('test')
|
||||
self.addAsyncCleanup(self.on_cleanup2)
|
||||
|
||||
async def asyncTearDown(self):
|
||||
self.assertEqual(events, ['setUp',
|
||||
'asyncSetUp',
|
||||
'test'])
|
||||
events.append('asyncTearDown')
|
||||
|
||||
def tearDown(self):
|
||||
self.assertEqual(events, ['setUp',
|
||||
'asyncSetUp',
|
||||
'test',
|
||||
'asyncTearDown'])
|
||||
events.append('tearDown')
|
||||
|
||||
async def on_cleanup1(self):
|
||||
self.assertEqual(events, ['setUp',
|
||||
'asyncSetUp',
|
||||
'test',
|
||||
'asyncTearDown',
|
||||
'tearDown',
|
||||
'cleanup2'])
|
||||
events.append('cleanup1')
|
||||
|
||||
async def on_cleanup2(self):
|
||||
self.assertEqual(events, ['setUp',
|
||||
'asyncSetUp',
|
||||
'test',
|
||||
'asyncTearDown',
|
||||
'tearDown'])
|
||||
events.append('cleanup2')
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
result = test.run()
|
||||
self.assertEqual(result.errors, [])
|
||||
self.assertEqual(result.failures, [])
|
||||
expected = ['setUp', 'asyncSetUp', 'test',
|
||||
'asyncTearDown', 'tearDown', 'cleanup2', 'cleanup1']
|
||||
self.assertEqual(events, expected)
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
test.debug()
|
||||
self.assertEqual(events, expected)
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, expected)
|
||||
|
||||
def test_exception_in_setup(self):
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def asyncSetUp(self):
|
||||
events.append('asyncSetUp')
|
||||
self.addAsyncCleanup(self.on_cleanup)
|
||||
raise MyException()
|
||||
|
||||
async def test_func(self):
|
||||
events.append('test')
|
||||
|
||||
async def asyncTearDown(self):
|
||||
events.append('asyncTearDown')
|
||||
|
||||
async def on_cleanup(self):
|
||||
events.append('cleanup')
|
||||
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['asyncSetUp', 'cleanup'])
|
||||
self.assertIs(result.errors[0][0], test)
|
||||
self.assertIn('MyException', result.errors[0][1])
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
try:
|
||||
test.debug()
|
||||
except MyException:
|
||||
pass
|
||||
else:
|
||||
self.fail('Expected a MyException exception')
|
||||
self.assertEqual(events, ['asyncSetUp'])
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, ['asyncSetUp', 'cleanup'])
|
||||
|
||||
def test_exception_in_test(self):
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def asyncSetUp(self):
|
||||
events.append('asyncSetUp')
|
||||
|
||||
async def test_func(self):
|
||||
events.append('test')
|
||||
self.addAsyncCleanup(self.on_cleanup)
|
||||
raise MyException()
|
||||
|
||||
async def asyncTearDown(self):
|
||||
events.append('asyncTearDown')
|
||||
|
||||
async def on_cleanup(self):
|
||||
events.append('cleanup')
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup'])
|
||||
self.assertIs(result.errors[0][0], test)
|
||||
self.assertIn('MyException', result.errors[0][1])
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
try:
|
||||
test.debug()
|
||||
except MyException:
|
||||
pass
|
||||
else:
|
||||
self.fail('Expected a MyException exception')
|
||||
self.assertEqual(events, ['asyncSetUp', 'test'])
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'cleanup'])
|
||||
|
||||
def test_exception_in_tear_down(self):
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def asyncSetUp(self):
|
||||
events.append('asyncSetUp')
|
||||
|
||||
async def test_func(self):
|
||||
events.append('test')
|
||||
self.addAsyncCleanup(self.on_cleanup)
|
||||
|
||||
async def asyncTearDown(self):
|
||||
events.append('asyncTearDown')
|
||||
raise MyException()
|
||||
|
||||
async def on_cleanup(self):
|
||||
events.append('cleanup')
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup'])
|
||||
self.assertIs(result.errors[0][0], test)
|
||||
self.assertIn('MyException', result.errors[0][1])
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
try:
|
||||
test.debug()
|
||||
except MyException:
|
||||
pass
|
||||
else:
|
||||
self.fail('Expected a MyException exception')
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown'])
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup'])
|
||||
|
||||
def test_exception_in_tear_clean_up(self):
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def asyncSetUp(self):
|
||||
events.append('asyncSetUp')
|
||||
|
||||
async def test_func(self):
|
||||
events.append('test')
|
||||
self.addAsyncCleanup(self.on_cleanup1)
|
||||
self.addAsyncCleanup(self.on_cleanup2)
|
||||
|
||||
async def asyncTearDown(self):
|
||||
events.append('asyncTearDown')
|
||||
|
||||
async def on_cleanup1(self):
|
||||
events.append('cleanup1')
|
||||
raise MyException('some error')
|
||||
|
||||
async def on_cleanup2(self):
|
||||
events.append('cleanup2')
|
||||
raise MyException('other error')
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1'])
|
||||
self.assertIs(result.errors[0][0], test)
|
||||
self.assertIn('MyException: other error', result.errors[0][1])
|
||||
self.assertIn('MyException: some error', result.errors[1][1])
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
try:
|
||||
test.debug()
|
||||
except MyException:
|
||||
pass
|
||||
else:
|
||||
self.fail('Expected a MyException exception')
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2'])
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1'])
|
||||
|
||||
def test_cleanups_interleave_order(self):
|
||||
events = []
|
||||
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_func(self):
|
||||
self.addAsyncCleanup(self.on_sync_cleanup, 1)
|
||||
self.addAsyncCleanup(self.on_async_cleanup, 2)
|
||||
self.addAsyncCleanup(self.on_sync_cleanup, 3)
|
||||
self.addAsyncCleanup(self.on_async_cleanup, 4)
|
||||
|
||||
async def on_sync_cleanup(self, val):
|
||||
events.append(f'sync_cleanup {val}')
|
||||
|
||||
async def on_async_cleanup(self, val):
|
||||
events.append(f'async_cleanup {val}')
|
||||
|
||||
test = Test("test_func")
|
||||
test.run()
|
||||
self.assertEqual(events, ['async_cleanup 4',
|
||||
'sync_cleanup 3',
|
||||
'async_cleanup 2',
|
||||
'sync_cleanup 1'])
|
||||
|
||||
def test_base_exception_from_async_method(self):
|
||||
events = []
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_base(self):
|
||||
events.append("test_base")
|
||||
raise BaseException()
|
||||
events.append("not it")
|
||||
|
||||
async def test_no_err(self):
|
||||
events.append("test_no_err")
|
||||
|
||||
async def test_cancel(self):
|
||||
raise asyncio.CancelledError()
|
||||
|
||||
test = Test("test_base")
|
||||
output = test.run()
|
||||
self.assertFalse(output.wasSuccessful())
|
||||
|
||||
test = Test("test_no_err")
|
||||
test.run()
|
||||
self.assertEqual(events, ['test_base', 'test_no_err'])
|
||||
|
||||
test = Test("test_cancel")
|
||||
output = test.run()
|
||||
self.assertFalse(output.wasSuccessful())
|
||||
|
||||
def test_cancellation_hanging_tasks(self):
|
||||
cancelled = False
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_leaking_task(self):
|
||||
async def coro():
|
||||
nonlocal cancelled
|
||||
try:
|
||||
await asyncio.sleep(1)
|
||||
except asyncio.CancelledError:
|
||||
cancelled = True
|
||||
raise
|
||||
|
||||
# Leave this running in the background
|
||||
asyncio.create_task(coro())
|
||||
|
||||
test = Test("test_leaking_task")
|
||||
output = test.run()
|
||||
self.assertTrue(cancelled)
|
||||
|
||||
def test_debug_cleanup_same_loop(self):
|
||||
class Test(unittest.IsolatedAsyncioTestCase):
|
||||
async def asyncSetUp(self):
|
||||
async def coro():
|
||||
await asyncio.sleep(0)
|
||||
fut = asyncio.ensure_future(coro())
|
||||
self.addAsyncCleanup(self.cleanup, fut)
|
||||
events.append('asyncSetUp')
|
||||
|
||||
async def test_func(self):
|
||||
events.append('test')
|
||||
raise MyException()
|
||||
|
||||
async def asyncTearDown(self):
|
||||
events.append('asyncTearDown')
|
||||
|
||||
async def cleanup(self, fut):
|
||||
try:
|
||||
# Raises an exception if in different loop
|
||||
await asyncio.wait([fut])
|
||||
events.append('cleanup')
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
raise
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup'])
|
||||
self.assertIn('MyException', result.errors[0][1])
|
||||
|
||||
events = []
|
||||
test = Test("test_func")
|
||||
try:
|
||||
test.debug()
|
||||
except MyException:
|
||||
pass
|
||||
else:
|
||||
self.fail('Expected a MyException exception')
|
||||
self.assertEqual(events, ['asyncSetUp', 'test'])
|
||||
test.doCleanups()
|
||||
self.assertEqual(events, ['asyncSetUp', 'test', 'cleanup'])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Vendored
+7
-10
@@ -1,4 +1,4 @@
|
||||
# import gc
|
||||
import gc
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
@@ -39,16 +39,13 @@ class TestBreak(unittest.TestCase):
|
||||
|
||||
def testRegisterResult(self):
|
||||
result = unittest.TestResult()
|
||||
self.assertNotIn(result, unittest.signals._results)
|
||||
|
||||
unittest.registerResult(result)
|
||||
|
||||
for ref in unittest.signals._results:
|
||||
if ref is result:
|
||||
break
|
||||
elif ref is not result:
|
||||
self.fail("odd object in result set")
|
||||
else:
|
||||
self.fail("result not found")
|
||||
|
||||
try:
|
||||
self.assertIn(result, unittest.signals._results)
|
||||
finally:
|
||||
unittest.removeResult(result)
|
||||
|
||||
def testInterruptCaught(self):
|
||||
default_handler = signal.getsignal(signal.SIGINT)
|
||||
|
||||
Vendored
+142
-14
@@ -8,6 +8,7 @@ import logging
|
||||
import warnings
|
||||
import weakref
|
||||
import inspect
|
||||
import types
|
||||
|
||||
from copy import deepcopy
|
||||
from test import support
|
||||
@@ -18,7 +19,7 @@ from unittest.test.support import (
|
||||
TestEquality, TestHashing, LoggingResult, LegacyLoggingResult,
|
||||
ResultWithNoStartTestRunStopTestRun
|
||||
)
|
||||
from test.support import captured_stderr
|
||||
from test.support import captured_stderr, gc_collect
|
||||
|
||||
|
||||
log_foo = logging.getLogger('foo')
|
||||
@@ -425,6 +426,20 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
expected = ['a1', 'a2', 'b1']
|
||||
self.assertEqual(events, expected)
|
||||
|
||||
def test_subtests_debug(self):
|
||||
# Test debug() with a test that uses subTest() (bpo-34900)
|
||||
events = []
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def test_a(self):
|
||||
events.append('test case')
|
||||
with self.subTest():
|
||||
events.append('subtest 1')
|
||||
|
||||
Foo('test_a').debug()
|
||||
|
||||
self.assertEqual(events, ['test case', 'subtest 1'])
|
||||
|
||||
# "This class attribute gives the exception raised by the test() method.
|
||||
# If a test framework needs to use a specialized exception, possibly to
|
||||
# carry additional information, it must subclass this exception in
|
||||
@@ -596,6 +611,17 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
'Tests shortDescription() for a method with a longer '
|
||||
'docstring.')
|
||||
|
||||
@unittest.skipIf(sys.flags.optimize >= 2,
|
||||
"Docstrings are omitted with -O2 and above")
|
||||
def testShortDescriptionWhitespaceTrimming(self):
|
||||
"""
|
||||
Tests shortDescription() whitespace is trimmed, so that the first
|
||||
line of nonwhite-space text becomes the docstring.
|
||||
"""
|
||||
self.assertEqual(
|
||||
self.shortDescription(),
|
||||
'Tests shortDescription() whitespace is trimmed, so that the first')
|
||||
|
||||
def testAddTypeEqualityFunc(self):
|
||||
class SadSnake(object):
|
||||
"""Dummy class for test_addTypeEqualityFunc."""
|
||||
@@ -606,7 +632,7 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
self.addTypeEqualityFunc(SadSnake, AllSnakesCreatedEqual)
|
||||
self.assertEqual(s1, s2)
|
||||
# No this doesn't clean up and remove the SadSnake equality func
|
||||
# from this TestCase instance but since its a local nothing else
|
||||
# from this TestCase instance but since it's local nothing else
|
||||
# will ever notice that.
|
||||
|
||||
def testAssertIs(self):
|
||||
@@ -682,6 +708,10 @@ class Test_TestCase(unittest.TestCase, TestEquality, TestHashing):
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertDictContainsSubset({'foo': one}, {'foo': '\uFFFD'})
|
||||
|
||||
with self.assertWarns(DeprecationWarning) as warninfo:
|
||||
self.assertDictContainsSubset({}, {})
|
||||
self.assertEqual(warninfo.warnings[0].filename, __file__)
|
||||
|
||||
def testAssertEqual(self):
|
||||
equal_pairs = [
|
||||
((), ()),
|
||||
@@ -1222,7 +1252,7 @@ test case
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertRaises(ExceptionMock, lambda: 0)
|
||||
# Failure when the function is None
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertRaises(ExceptionMock, None)
|
||||
# Failure when another exception is raised
|
||||
with self.assertRaises(ExceptionMock):
|
||||
@@ -1253,8 +1283,7 @@ test case
|
||||
with self.assertRaises(ExceptionMock, msg='foobar'):
|
||||
pass
|
||||
# Invalid keyword argument
|
||||
with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
|
||||
self.assertRaises(AssertionError):
|
||||
with self.assertRaisesRegex(TypeError, 'foobar'):
|
||||
with self.assertRaises(ExceptionMock, foobar=42):
|
||||
pass
|
||||
# Failure when another exception is raised
|
||||
@@ -1295,7 +1324,7 @@ test case
|
||||
|
||||
self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub)
|
||||
self.assertRaisesRegex(ExceptionMock, 'expect$', Stub)
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertRaisesRegex(ExceptionMock, 'expect$', None)
|
||||
|
||||
def testAssertNotRaisesRegex(self):
|
||||
@@ -1312,8 +1341,7 @@ test case
|
||||
with self.assertRaisesRegex(Exception, 'expect', msg='foobar'):
|
||||
pass
|
||||
# Invalid keyword argument
|
||||
with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
|
||||
self.assertRaises(AssertionError):
|
||||
with self.assertRaisesRegex(TypeError, 'foobar'):
|
||||
with self.assertRaisesRegex(Exception, 'expect', foobar=42):
|
||||
pass
|
||||
|
||||
@@ -1329,6 +1357,20 @@ test case
|
||||
pass
|
||||
self.assertRaises(TypeError, self.assertWarnsRegex, MyWarn, lambda: True)
|
||||
|
||||
def testAssertWarnsModifySysModules(self):
|
||||
# bpo-29620: handle modified sys.modules during iteration
|
||||
class Foo(types.ModuleType):
|
||||
@property
|
||||
def __warningregistry__(self):
|
||||
sys.modules['@bar@'] = 'bar'
|
||||
|
||||
sys.modules['@foo@'] = Foo('foo')
|
||||
try:
|
||||
self.assertWarns(UserWarning, warnings.warn, 'expected')
|
||||
finally:
|
||||
del sys.modules['@foo@']
|
||||
del sys.modules['@bar@']
|
||||
|
||||
def testAssertRaisesRegexMismatch(self):
|
||||
def Stub():
|
||||
raise Exception('Unexpected')
|
||||
@@ -1388,7 +1430,7 @@ test case
|
||||
with self.assertRaises(self.failureException):
|
||||
self.assertWarns(RuntimeWarning, lambda: 0)
|
||||
# Failure when the function is None
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertWarns(RuntimeWarning, None)
|
||||
# Failure when another warning is triggered
|
||||
with warnings.catch_warnings():
|
||||
@@ -1433,8 +1475,7 @@ test case
|
||||
with self.assertWarns(RuntimeWarning, msg='foobar'):
|
||||
pass
|
||||
# Invalid keyword argument
|
||||
with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
|
||||
self.assertRaises(AssertionError):
|
||||
with self.assertRaisesRegex(TypeError, 'foobar'):
|
||||
with self.assertWarns(RuntimeWarning, foobar=42):
|
||||
pass
|
||||
# Failure when another warning is triggered
|
||||
@@ -1475,7 +1516,7 @@ test case
|
||||
self.assertWarnsRegex(RuntimeWarning, "o+",
|
||||
lambda: 0)
|
||||
# Failure when the function is None
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
with self.assertRaises(TypeError):
|
||||
self.assertWarnsRegex(RuntimeWarning, "o+", None)
|
||||
# Failure when another warning is triggered
|
||||
with warnings.catch_warnings():
|
||||
@@ -1518,8 +1559,7 @@ test case
|
||||
with self.assertWarnsRegex(RuntimeWarning, 'o+', msg='foobar'):
|
||||
pass
|
||||
# Invalid keyword argument
|
||||
with self.assertWarnsRegex(DeprecationWarning, 'foobar'), \
|
||||
self.assertRaises(AssertionError):
|
||||
with self.assertRaisesRegex(TypeError, 'foobar'):
|
||||
with self.assertWarnsRegex(RuntimeWarning, 'o+', foobar=42):
|
||||
pass
|
||||
# Failure when another warning is triggered
|
||||
@@ -1639,6 +1679,18 @@ test case
|
||||
with self.assertLogs(level='WARNING'):
|
||||
log_foo.info("1")
|
||||
|
||||
def testAssertLogsFailureLevelTooHigh_FilterInRootLogger(self):
|
||||
# Failure due to level too high - message propagated to root
|
||||
with self.assertNoStderr():
|
||||
oldLevel = log_foo.level
|
||||
log_foo.setLevel(logging.INFO)
|
||||
try:
|
||||
with self.assertRaises(self.failureException):
|
||||
with self.assertLogs(level='WARNING'):
|
||||
log_foo.info("1")
|
||||
finally:
|
||||
log_foo.setLevel(oldLevel)
|
||||
|
||||
def testAssertLogsFailureMismatchingLogger(self):
|
||||
# Failure due to mismatching logger (and the logged message is
|
||||
# passed through)
|
||||
@@ -1647,6 +1699,81 @@ test case
|
||||
with self.assertLogs('foo'):
|
||||
log_quux.error("1")
|
||||
|
||||
def testAssertLogsUnexpectedException(self):
|
||||
# Check unexpected exception will go through.
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
with self.assertLogs():
|
||||
raise ZeroDivisionError("Unexpected")
|
||||
|
||||
def testAssertNoLogsDefault(self):
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
with self.assertNoLogs():
|
||||
log_foo.info("1")
|
||||
log_foobar.debug("2")
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"Unexpected logs found: ['INFO:foo:1']",
|
||||
)
|
||||
|
||||
def testAssertNoLogsFailureFoundLogs(self):
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
with self.assertNoLogs():
|
||||
log_quux.error("1")
|
||||
log_foo.error("foo")
|
||||
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"Unexpected logs found: ['ERROR:quux:1', 'ERROR:foo:foo']",
|
||||
)
|
||||
|
||||
def testAssertNoLogsPerLogger(self):
|
||||
with self.assertNoStderr():
|
||||
with self.assertLogs(log_quux):
|
||||
with self.assertNoLogs(logger=log_foo):
|
||||
log_quux.error("1")
|
||||
|
||||
def testAssertNoLogsFailurePerLogger(self):
|
||||
# Failure due to unexpected logs for the given logger or its
|
||||
# children.
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
with self.assertLogs(log_quux):
|
||||
with self.assertNoLogs(logger=log_foo):
|
||||
log_quux.error("1")
|
||||
log_foobar.info("2")
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"Unexpected logs found: ['INFO:foo.bar:2']",
|
||||
)
|
||||
|
||||
def testAssertNoLogsPerLevel(self):
|
||||
# Check per-level filtering
|
||||
with self.assertNoStderr():
|
||||
with self.assertNoLogs(level="ERROR"):
|
||||
log_foo.info("foo")
|
||||
log_quux.debug("1")
|
||||
|
||||
def testAssertNoLogsFailurePerLevel(self):
|
||||
# Failure due to unexpected logs at the specified level.
|
||||
with self.assertRaises(self.failureException) as cm:
|
||||
with self.assertNoLogs(level="DEBUG"):
|
||||
log_foo.debug("foo")
|
||||
log_quux.debug("1")
|
||||
self.assertEqual(
|
||||
str(cm.exception),
|
||||
"Unexpected logs found: ['DEBUG:foo:foo', 'DEBUG:quux:1']",
|
||||
)
|
||||
|
||||
def testAssertNoLogsUnexpectedException(self):
|
||||
# Check unexpected exception will go through.
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
with self.assertNoLogs():
|
||||
raise ZeroDivisionError("Unexpected")
|
||||
|
||||
def testAssertNoLogsYieldsNone(self):
|
||||
with self.assertNoLogs() as value:
|
||||
pass
|
||||
self.assertIsNone(value)
|
||||
|
||||
def testDeprecatedMethodNames(self):
|
||||
"""
|
||||
Test that the deprecated methods raise a DeprecationWarning. See #9424.
|
||||
@@ -1828,6 +1955,7 @@ test case
|
||||
for method_name in ('test1', 'test2'):
|
||||
testcase = TestCase(method_name)
|
||||
testcase.run()
|
||||
gc_collect() # For PyPy or other GCs.
|
||||
self.assertEqual(MyException.ninstance, 0)
|
||||
|
||||
|
||||
|
||||
Vendored
+6
@@ -724,11 +724,13 @@ class TestDiscovery(unittest.TestCase):
|
||||
original_listdir = os.listdir
|
||||
original_isfile = os.path.isfile
|
||||
original_isdir = os.path.isdir
|
||||
original_realpath = os.path.realpath
|
||||
|
||||
def cleanup():
|
||||
os.listdir = original_listdir
|
||||
os.path.isfile = original_isfile
|
||||
os.path.isdir = original_isdir
|
||||
os.path.realpath = original_realpath
|
||||
del sys.modules['foo']
|
||||
if full_path in sys.path:
|
||||
sys.path.remove(full_path)
|
||||
@@ -743,6 +745,10 @@ class TestDiscovery(unittest.TestCase):
|
||||
os.listdir = listdir
|
||||
os.path.isfile = isfile
|
||||
os.path.isdir = isdir
|
||||
if os.name == 'nt':
|
||||
# ntpath.realpath may inject path prefixes when failing to
|
||||
# resolve real files, so we substitute abspath() here instead.
|
||||
os.path.realpath = os.path.abspath
|
||||
return full_path
|
||||
|
||||
def test_detect_module_clash(self):
|
||||
|
||||
Vendored
+16
@@ -1,3 +1,4 @@
|
||||
import functools
|
||||
import sys
|
||||
import types
|
||||
import warnings
|
||||
@@ -1575,5 +1576,20 @@ class Test_TestLoader(unittest.TestCase):
|
||||
self.assertIs(loader.suiteClass, unittest.TestSuite)
|
||||
|
||||
|
||||
def test_partial_functions(self):
|
||||
def noop(arg):
|
||||
pass
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
pass
|
||||
|
||||
setattr(Foo, 'test_partial', functools.partial(noop, None))
|
||||
|
||||
loader = unittest.TestLoader()
|
||||
|
||||
test_names = ['test_partial']
|
||||
self.assertEqual(loader.getTestCaseNames(Foo), test_names)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Vendored
+15
-7
@@ -6,6 +6,7 @@ import subprocess
|
||||
from test import support
|
||||
import unittest
|
||||
import unittest.test
|
||||
from unittest.test.test_result import BufferedWriter
|
||||
|
||||
|
||||
class Test_TestProgram(unittest.TestCase):
|
||||
@@ -57,9 +58,9 @@ class Test_TestProgram(unittest.TestCase):
|
||||
|
||||
class FooBar(unittest.TestCase):
|
||||
def testPass(self):
|
||||
assert True
|
||||
pass
|
||||
def testFail(self):
|
||||
assert False
|
||||
raise AssertionError
|
||||
|
||||
class FooBarLoader(unittest.TestLoader):
|
||||
"""Test loader that returns a suite containing FooBar."""
|
||||
@@ -104,30 +105,39 @@ class Test_TestProgram(unittest.TestCase):
|
||||
program.testNames)
|
||||
|
||||
def test_NonExit(self):
|
||||
stream = BufferedWriter()
|
||||
program = unittest.main(exit=False,
|
||||
argv=["foobar"],
|
||||
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
||||
testRunner=unittest.TextTestRunner(stream=stream),
|
||||
testLoader=self.FooBarLoader())
|
||||
self.assertTrue(hasattr(program, 'result'))
|
||||
self.assertIn('\nFAIL: testFail ', stream.getvalue())
|
||||
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
|
||||
|
||||
|
||||
def test_Exit(self):
|
||||
stream = BufferedWriter()
|
||||
self.assertRaises(
|
||||
SystemExit,
|
||||
unittest.main,
|
||||
argv=["foobar"],
|
||||
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
||||
testRunner=unittest.TextTestRunner(stream=stream),
|
||||
exit=True,
|
||||
testLoader=self.FooBarLoader())
|
||||
self.assertIn('\nFAIL: testFail ', stream.getvalue())
|
||||
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
|
||||
|
||||
|
||||
def test_ExitAsDefault(self):
|
||||
stream = BufferedWriter()
|
||||
self.assertRaises(
|
||||
SystemExit,
|
||||
unittest.main,
|
||||
argv=["foobar"],
|
||||
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
||||
testRunner=unittest.TextTestRunner(stream=stream),
|
||||
testLoader=self.FooBarLoader())
|
||||
self.assertIn('\nFAIL: testFail ', stream.getvalue())
|
||||
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
|
||||
|
||||
|
||||
class InitialisableProgram(unittest.TestProgram):
|
||||
@@ -188,8 +198,6 @@ class TestCommandLineArgs(unittest.TestCase):
|
||||
program = self.program
|
||||
for arg, attr in (('buffer', 'buffer'), ('failfast', 'failfast'),
|
||||
('catch', 'catchbreak')):
|
||||
if attr == 'catch' and not hasInstallHandler:
|
||||
continue
|
||||
|
||||
setattr(program, attr, None)
|
||||
program.parseArgs([None])
|
||||
|
||||
Vendored
+504
-8
@@ -2,10 +2,11 @@ import io
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
from test.support import warnings_helper
|
||||
from test.support import warnings_helper, captured_stdout, captured_stderr
|
||||
|
||||
import traceback
|
||||
import unittest
|
||||
from unittest.util import strclass
|
||||
|
||||
|
||||
class MockTraceback(object):
|
||||
@@ -22,6 +23,32 @@ def restore_traceback():
|
||||
unittest.result.traceback = traceback
|
||||
|
||||
|
||||
def bad_cleanup1():
|
||||
print('do cleanup1')
|
||||
raise TypeError('bad cleanup1')
|
||||
|
||||
|
||||
def bad_cleanup2():
|
||||
print('do cleanup2')
|
||||
raise ValueError('bad cleanup2')
|
||||
|
||||
|
||||
class BufferedWriter:
|
||||
def __init__(self):
|
||||
self.result = ''
|
||||
self.buffer = ''
|
||||
|
||||
def write(self, arg):
|
||||
self.buffer += arg
|
||||
|
||||
def flush(self):
|
||||
self.result += self.buffer
|
||||
self.buffer = ''
|
||||
|
||||
def getvalue(self):
|
||||
return self.result
|
||||
|
||||
|
||||
class Test_TestResult(unittest.TestCase):
|
||||
# Note: there are not separate tests for TestResult.wasSuccessful(),
|
||||
# TestResult.errors, TestResult.failures, TestResult.testsRun or
|
||||
@@ -193,6 +220,61 @@ class Test_TestResult(unittest.TestCase):
|
||||
self.assertIs(test_case, test)
|
||||
self.assertIsInstance(formatted_exc, str)
|
||||
|
||||
def test_addFailure_filter_traceback_frames(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def test_1(self):
|
||||
pass
|
||||
|
||||
test = Foo('test_1')
|
||||
def get_exc_info():
|
||||
try:
|
||||
test.fail("foo")
|
||||
except:
|
||||
return sys.exc_info()
|
||||
|
||||
exc_info_tuple = get_exc_info()
|
||||
|
||||
full_exc = traceback.format_exception(*exc_info_tuple)
|
||||
|
||||
result = unittest.TestResult()
|
||||
result.startTest(test)
|
||||
result.addFailure(test, exc_info_tuple)
|
||||
result.stopTest(test)
|
||||
|
||||
formatted_exc = result.failures[0][1]
|
||||
dropped = [l for l in full_exc if l not in formatted_exc]
|
||||
self.assertEqual(len(dropped), 1)
|
||||
self.assertIn("raise self.failureException(msg)", dropped[0])
|
||||
|
||||
def test_addFailure_filter_traceback_frames_context(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def test_1(self):
|
||||
pass
|
||||
|
||||
test = Foo('test_1')
|
||||
def get_exc_info():
|
||||
try:
|
||||
try:
|
||||
test.fail("foo")
|
||||
except:
|
||||
raise ValueError(42)
|
||||
except:
|
||||
return sys.exc_info()
|
||||
|
||||
exc_info_tuple = get_exc_info()
|
||||
|
||||
full_exc = traceback.format_exception(*exc_info_tuple)
|
||||
|
||||
result = unittest.TestResult()
|
||||
result.startTest(test)
|
||||
result.addFailure(test, exc_info_tuple)
|
||||
result.stopTest(test)
|
||||
|
||||
formatted_exc = result.failures[0][1]
|
||||
dropped = [l for l in full_exc if l not in formatted_exc]
|
||||
self.assertEqual(len(dropped), 1)
|
||||
self.assertIn("raise self.failureException(msg)", dropped[0])
|
||||
|
||||
# "addError(test, err)"
|
||||
# ...
|
||||
# "Called when the test case test raises an unexpected exception err
|
||||
@@ -433,10 +515,13 @@ class Test_TestResult(unittest.TestCase):
|
||||
self.assertTrue(result.shouldStop)
|
||||
|
||||
def testFailFastSetByRunner(self):
|
||||
runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True)
|
||||
stream = BufferedWriter()
|
||||
runner = unittest.TextTestRunner(stream=stream, failfast=True)
|
||||
def test(result):
|
||||
self.assertTrue(result.failfast)
|
||||
result = runner.run(test)
|
||||
stream.flush()
|
||||
self.assertTrue(stream.getvalue().endswith('\n\nOK\n'))
|
||||
|
||||
|
||||
classDict = dict(unittest.TestResult.__dict__)
|
||||
@@ -458,8 +543,8 @@ OldResult = type('OldResult', (object,), classDict)
|
||||
class Test_OldTestResult(unittest.TestCase):
|
||||
|
||||
def assertOldResultWarning(self, test, failures):
|
||||
with warnings_helper.check_warnings(("TestResult has no add.+ method,",
|
||||
RuntimeWarning)):
|
||||
with warnings_helper.check_warnings(
|
||||
("TestResult has no add.+ method,", RuntimeWarning)):
|
||||
result = OldResult()
|
||||
test.run(result)
|
||||
self.assertEqual(len(result.failures), failures)
|
||||
@@ -633,36 +718,320 @@ class TestOutputBuffering(unittest.TestCase):
|
||||
self.assertEqual(result._original_stderr.getvalue(), expectedErrMessage)
|
||||
self.assertMultiLineEqual(message, expectedFullMessage)
|
||||
|
||||
def testBufferSetUp(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
print('set up')
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
description = f'test_foo ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferTearDown(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
print('tear down')
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\ntear down\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
description = f'test_foo ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferDoCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
print('set up')
|
||||
self.addCleanup(bad_cleanup1)
|
||||
self.addCleanup(bad_cleanup2)
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 2)
|
||||
description = f'test_foo ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferSetUp_DoCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
print('set up')
|
||||
self.addCleanup(bad_cleanup1)
|
||||
self.addCleanup(bad_cleanup2)
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 3)
|
||||
description = f'test_foo ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[2]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferTearDown_DoCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
print('set up')
|
||||
self.addCleanup(bad_cleanup1)
|
||||
self.addCleanup(bad_cleanup2)
|
||||
def tearDown(self):
|
||||
print('tear down')
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up\ntear down\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 3)
|
||||
description = f'test_foo ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[2]
|
||||
self.assertEqual(str(test_case), description)
|
||||
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferSetupClass(self):
|
||||
result = unittest.TestResult()
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
print('set up class')
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up class\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
description = f'setUpClass ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferTearDownClass(self):
|
||||
result = unittest.TestResult()
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
print('tear down class')
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\ntear down class\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
description = f'tearDownClass ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferDoClassCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
print('set up class')
|
||||
cls.addClassCleanup(bad_cleanup1)
|
||||
cls.addClassCleanup(bad_cleanup2)
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
print('tear down class')
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\ntear down class\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 2)
|
||||
description = f'tearDownClass ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferSetupClass_DoClassCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
print('set up class')
|
||||
cls.addClassCleanup(bad_cleanup1)
|
||||
cls.addClassCleanup(bad_cleanup2)
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up class\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 3)
|
||||
description = f'setUpClass ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn('\nStdout:\nset up class\n', formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[2]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferTearDownClass_DoClassCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
print('set up class')
|
||||
cls.addClassCleanup(bad_cleanup1)
|
||||
cls.addClassCleanup(bad_cleanup2)
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
print('tear down class')
|
||||
1/0
|
||||
def test_foo(self):
|
||||
pass
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\ntear down class\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 3)
|
||||
description = f'tearDownClass ({strclass(Foo)})'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn('\nStdout:\ntear down class\n', formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
test_case, formatted_exc = result.errors[2]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferSetUpModule(self):
|
||||
result = unittest.TestResult()
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
@@ -671,6 +1040,7 @@ class TestOutputBuffering(unittest.TestCase):
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
print('set up module')
|
||||
1/0
|
||||
|
||||
Foo.__module__ = 'Module'
|
||||
@@ -678,10 +1048,18 @@ class TestOutputBuffering(unittest.TestCase):
|
||||
self.addCleanup(sys.modules.pop, 'Module')
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up module\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
description = 'setUpModule (Module)'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferTearDownModule(self):
|
||||
result = unittest.TestResult()
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
@@ -690,6 +1068,7 @@ class TestOutputBuffering(unittest.TestCase):
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
print('tear down module')
|
||||
1/0
|
||||
|
||||
Foo.__module__ = 'Module'
|
||||
@@ -697,7 +1076,124 @@ class TestOutputBuffering(unittest.TestCase):
|
||||
self.addCleanup(sys.modules.pop, 'Module')
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\ntear down module\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
description = 'tearDownModule (Module)'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferDoModuleCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
print('set up module')
|
||||
unittest.addModuleCleanup(bad_cleanup1)
|
||||
unittest.addModuleCleanup(bad_cleanup2)
|
||||
|
||||
Foo.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
self.addCleanup(sys.modules.pop, 'Module')
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
description = 'tearDownModule (Module)'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferSetUpModule_DoModuleCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
print('set up module')
|
||||
unittest.addModuleCleanup(bad_cleanup1)
|
||||
unittest.addModuleCleanup(bad_cleanup2)
|
||||
1/0
|
||||
|
||||
Foo.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
self.addCleanup(sys.modules.pop, 'Module')
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\nset up module\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 2)
|
||||
description = 'setUpModule (Module)'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn('\nStdout:\nset up module\n', formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
def testBufferTearDownModule_DoModuleCleanups(self):
|
||||
with captured_stdout() as stdout:
|
||||
result = unittest.TestResult()
|
||||
result.buffer = True
|
||||
|
||||
class Foo(unittest.TestCase):
|
||||
def test_foo(self):
|
||||
pass
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
print('set up module')
|
||||
unittest.addModuleCleanup(bad_cleanup1)
|
||||
unittest.addModuleCleanup(bad_cleanup2)
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
print('tear down module')
|
||||
1/0
|
||||
|
||||
Foo.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
self.addCleanup(sys.modules.pop, 'Module')
|
||||
suite = unittest.TestSuite([Foo('test_foo')])
|
||||
suite(result)
|
||||
expected_out = '\nStdout:\ntear down module\ndo cleanup2\ndo cleanup1\n'
|
||||
self.assertEqual(stdout.getvalue(), expected_out)
|
||||
self.assertEqual(len(result.errors), 2)
|
||||
description = 'tearDownModule (Module)'
|
||||
test_case, formatted_exc = result.errors[0]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||
self.assertNotIn('ValueError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn('\nStdout:\ntear down module\n', formatted_exc)
|
||||
test_case, formatted_exc = result.errors[1]
|
||||
self.assertEqual(test_case.description, description)
|
||||
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||
self.assertNotIn('TypeError', formatted_exc)
|
||||
self.assertIn(expected_out, formatted_exc)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Vendored
+865
-5
@@ -11,8 +11,41 @@ from unittest.test.support import (LoggingResult,
|
||||
ResultWithNoStartTestRunStopTestRun)
|
||||
|
||||
|
||||
class TestCleanUp(unittest.TestCase):
|
||||
def resultFactory(*_):
|
||||
return unittest.TestResult()
|
||||
|
||||
|
||||
def getRunner():
|
||||
return unittest.TextTestRunner(resultclass=resultFactory,
|
||||
stream=io.StringIO())
|
||||
|
||||
|
||||
def runTests(*cases):
|
||||
suite = unittest.TestSuite()
|
||||
for case in cases:
|
||||
tests = unittest.defaultTestLoader.loadTestsFromTestCase(case)
|
||||
suite.addTests(tests)
|
||||
|
||||
runner = getRunner()
|
||||
|
||||
# creating a nested suite exposes some potential bugs
|
||||
realSuite = unittest.TestSuite()
|
||||
realSuite.addTest(suite)
|
||||
# adding empty suites to the end exposes potential bugs
|
||||
suite.addTest(unittest.TestSuite())
|
||||
realSuite.addTest(unittest.TestSuite())
|
||||
return runner.run(realSuite)
|
||||
|
||||
|
||||
def cleanup(ordering, blowUp=False):
|
||||
if not blowUp:
|
||||
ordering.append('cleanup_good')
|
||||
else:
|
||||
ordering.append('cleanup_exc')
|
||||
raise Exception('CleanUpExc')
|
||||
|
||||
|
||||
class TestCleanUp(unittest.TestCase):
|
||||
def testCleanUp(self):
|
||||
class TestableTest(unittest.TestCase):
|
||||
def testNothing(self):
|
||||
@@ -47,10 +80,10 @@ class TestCleanUp(unittest.TestCase):
|
||||
test = TestableTest('testNothing')
|
||||
outcome = test._outcome = _Outcome()
|
||||
|
||||
exc1 = Exception('foo')
|
||||
CleanUpExc = Exception('foo')
|
||||
exc2 = Exception('bar')
|
||||
def cleanup1():
|
||||
raise exc1
|
||||
raise CleanUpExc
|
||||
|
||||
def cleanup2():
|
||||
raise exc2
|
||||
@@ -63,7 +96,7 @@ class TestCleanUp(unittest.TestCase):
|
||||
|
||||
((_, (Type1, instance1, _)),
|
||||
(_, (Type2, instance2, _))) = reversed(outcome.errors)
|
||||
self.assertEqual((Type1, instance1), (Exception, exc1))
|
||||
self.assertEqual((Type1, instance1), (Exception, CleanUpExc))
|
||||
self.assertEqual((Type2, instance2), (Exception, exc2))
|
||||
|
||||
def testCleanupInRun(self):
|
||||
@@ -135,6 +168,834 @@ class TestCleanUp(unittest.TestCase):
|
||||
self.assertEqual(ordering, ['setUp', 'test', 'tearDown', 'cleanup1', 'cleanup2'])
|
||||
|
||||
|
||||
class TestClassCleanup(unittest.TestCase):
|
||||
def test_addClassCleanUp(self):
|
||||
class TestableTest(unittest.TestCase):
|
||||
def testNothing(self):
|
||||
pass
|
||||
test = TestableTest('testNothing')
|
||||
self.assertEqual(test._class_cleanups, [])
|
||||
class_cleanups = []
|
||||
|
||||
def class_cleanup1(*args, **kwargs):
|
||||
class_cleanups.append((3, args, kwargs))
|
||||
|
||||
def class_cleanup2(*args, **kwargs):
|
||||
class_cleanups.append((4, args, kwargs))
|
||||
|
||||
TestableTest.addClassCleanup(class_cleanup1, 1, 2, 3,
|
||||
four='hello', five='goodbye')
|
||||
TestableTest.addClassCleanup(class_cleanup2)
|
||||
|
||||
self.assertEqual(test._class_cleanups,
|
||||
[(class_cleanup1, (1, 2, 3),
|
||||
dict(four='hello', five='goodbye')),
|
||||
(class_cleanup2, (), {})])
|
||||
|
||||
TestableTest.doClassCleanups()
|
||||
self.assertEqual(class_cleanups, [(4, (), {}), (3, (1, 2, 3),
|
||||
dict(four='hello', five='goodbye'))])
|
||||
|
||||
def test_run_class_cleanUp(self):
|
||||
ordering = []
|
||||
blowUp = True
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering)
|
||||
if blowUp:
|
||||
raise Exception()
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(ordering, ['setUpClass', 'cleanup_good'])
|
||||
|
||||
ordering = []
|
||||
blowUp = False
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||
|
||||
def test_run_class_cleanUp_without_tearDownClass(self):
|
||||
ordering = []
|
||||
blowUp = True
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering)
|
||||
if blowUp:
|
||||
raise Exception()
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
@property
|
||||
def tearDownClass(cls):
|
||||
raise AttributeError
|
||||
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(ordering, ['setUpClass', 'cleanup_good'])
|
||||
|
||||
ordering = []
|
||||
blowUp = False
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'test', 'cleanup_good'])
|
||||
|
||||
def test_debug_executes_classCleanUp(self):
|
||||
ordering = []
|
||||
blowUp = False
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering, blowUp=blowUp)
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
suite.debug()
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||
|
||||
ordering = []
|
||||
blowUp = True
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
with self.assertRaises(Exception) as cm:
|
||||
suite.debug()
|
||||
self.assertEqual(str(cm.exception), 'CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'test', 'tearDownClass', 'cleanup_exc'])
|
||||
|
||||
def test_debug_executes_classCleanUp_when_teardown_exception(self):
|
||||
ordering = []
|
||||
blowUp = False
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering, blowUp=blowUp)
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
raise Exception('TearDownClassExc')
|
||||
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
with self.assertRaises(Exception) as cm:
|
||||
suite.debug()
|
||||
self.assertEqual(str(cm.exception), 'TearDownClassExc')
|
||||
self.assertEqual(ordering, ['setUpClass', 'test'])
|
||||
self.assertTrue(TestableTest._class_cleanups)
|
||||
TestableTest._class_cleanups.clear()
|
||||
|
||||
ordering = []
|
||||
blowUp = True
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
with self.assertRaises(Exception) as cm:
|
||||
suite.debug()
|
||||
self.assertEqual(str(cm.exception), 'TearDownClassExc')
|
||||
self.assertEqual(ordering, ['setUpClass', 'test'])
|
||||
self.assertTrue(TestableTest._class_cleanups)
|
||||
TestableTest._class_cleanups.clear()
|
||||
|
||||
def test_doClassCleanups_with_errors_addClassCleanUp(self):
|
||||
class TestableTest(unittest.TestCase):
|
||||
def testNothing(self):
|
||||
pass
|
||||
|
||||
def cleanup1():
|
||||
raise Exception('cleanup1')
|
||||
|
||||
def cleanup2():
|
||||
raise Exception('cleanup2')
|
||||
|
||||
TestableTest.addClassCleanup(cleanup1)
|
||||
TestableTest.addClassCleanup(cleanup2)
|
||||
with self.assertRaises(Exception) as e:
|
||||
TestableTest.doClassCleanups()
|
||||
self.assertEqual(e, 'cleanup1')
|
||||
|
||||
def test_with_errors_addCleanUp(self):
|
||||
ordering = []
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering)
|
||||
def setUp(self):
|
||||
ordering.append('setUp')
|
||||
self.addCleanup(cleanup, ordering, blowUp=True)
|
||||
def testNothing(self):
|
||||
pass
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'setUp', 'cleanup_exc',
|
||||
'tearDownClass', 'cleanup_good'])
|
||||
|
||||
def test_run_with_errors_addClassCleanUp(self):
|
||||
ordering = []
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering, blowUp=True)
|
||||
def setUp(self):
|
||||
ordering.append('setUp')
|
||||
self.addCleanup(cleanup, ordering)
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'setUp', 'test', 'cleanup_good',
|
||||
'tearDownClass', 'cleanup_exc'])
|
||||
|
||||
def test_with_errors_in_addClassCleanup_and_setUps(self):
|
||||
ordering = []
|
||||
class_blow_up = False
|
||||
method_blow_up = False
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering, blowUp=True)
|
||||
if class_blow_up:
|
||||
raise Exception('ClassExc')
|
||||
def setUp(self):
|
||||
ordering.append('setUp')
|
||||
if method_blow_up:
|
||||
raise Exception('MethodExc')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'setUp', 'test',
|
||||
'tearDownClass', 'cleanup_exc'])
|
||||
|
||||
ordering = []
|
||||
class_blow_up = True
|
||||
method_blow_up = False
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: ClassExc')
|
||||
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'cleanup_exc'])
|
||||
|
||||
ordering = []
|
||||
class_blow_up = False
|
||||
method_blow_up = True
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: MethodExc')
|
||||
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'setUp', 'tearDownClass',
|
||||
'cleanup_exc'])
|
||||
|
||||
def test_with_errors_in_tearDownClass(self):
|
||||
ordering = []
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering)
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
raise Exception('TearDownExc')
|
||||
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: TearDownExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||
|
||||
|
||||
class TestModuleCleanUp(unittest.TestCase):
|
||||
def test_add_and_do_ModuleCleanup(self):
|
||||
module_cleanups = []
|
||||
|
||||
def module_cleanup1(*args, **kwargs):
|
||||
module_cleanups.append((3, args, kwargs))
|
||||
|
||||
def module_cleanup2(*args, **kwargs):
|
||||
module_cleanups.append((4, args, kwargs))
|
||||
|
||||
class Module(object):
|
||||
unittest.addModuleCleanup(module_cleanup1, 1, 2, 3,
|
||||
four='hello', five='goodbye')
|
||||
unittest.addModuleCleanup(module_cleanup2)
|
||||
|
||||
self.assertEqual(unittest.case._module_cleanups,
|
||||
[(module_cleanup1, (1, 2, 3),
|
||||
dict(four='hello', five='goodbye')),
|
||||
(module_cleanup2, (), {})])
|
||||
|
||||
unittest.case.doModuleCleanups()
|
||||
self.assertEqual(module_cleanups, [(4, (), {}), (3, (1, 2, 3),
|
||||
dict(four='hello', five='goodbye'))])
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
def test_doModuleCleanup_with_errors_in_addModuleCleanup(self):
|
||||
module_cleanups = []
|
||||
|
||||
def module_cleanup_good(*args, **kwargs):
|
||||
module_cleanups.append((3, args, kwargs))
|
||||
|
||||
def module_cleanup_bad(*args, **kwargs):
|
||||
raise Exception('CleanUpExc')
|
||||
|
||||
class Module(object):
|
||||
unittest.addModuleCleanup(module_cleanup_good, 1, 2, 3,
|
||||
four='hello', five='goodbye')
|
||||
unittest.addModuleCleanup(module_cleanup_bad)
|
||||
self.assertEqual(unittest.case._module_cleanups,
|
||||
[(module_cleanup_good, (1, 2, 3),
|
||||
dict(four='hello', five='goodbye')),
|
||||
(module_cleanup_bad, (), {})])
|
||||
with self.assertRaises(Exception) as e:
|
||||
unittest.case.doModuleCleanups()
|
||||
self.assertEqual(str(e.exception), 'CleanUpExc')
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
def test_addModuleCleanup_arg_errors(self):
|
||||
cleanups = []
|
||||
def cleanup(*args, **kwargs):
|
||||
cleanups.append((args, kwargs))
|
||||
|
||||
class Module(object):
|
||||
unittest.addModuleCleanup(cleanup, 1, 2, function='hello')
|
||||
with self.assertRaises(TypeError):
|
||||
unittest.addModuleCleanup(function=cleanup, arg='hello')
|
||||
with self.assertRaises(TypeError):
|
||||
unittest.addModuleCleanup()
|
||||
unittest.case.doModuleCleanups()
|
||||
self.assertEqual(cleanups,
|
||||
[((1, 2), {'function': 'hello'})])
|
||||
|
||||
def test_run_module_cleanUp(self):
|
||||
blowUp = True
|
||||
ordering = []
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering)
|
||||
if blowUp:
|
||||
raise Exception('setUpModule Exc')
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(ordering, ['setUpModule', 'cleanup_good'])
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: setUpModule Exc')
|
||||
|
||||
ordering = []
|
||||
blowUp = False
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(ordering,
|
||||
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||
'tearDownModule', 'cleanup_good'])
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
def test_run_multiple_module_cleanUp(self):
|
||||
blowUp = True
|
||||
blowUp2 = False
|
||||
ordering = []
|
||||
class Module1(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering)
|
||||
if blowUp:
|
||||
raise Exception()
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule')
|
||||
|
||||
class Module2(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule2')
|
||||
unittest.addModuleCleanup(cleanup, ordering)
|
||||
if blowUp2:
|
||||
raise Exception()
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule2')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
class TestableTest2(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass2')
|
||||
def testNothing(self):
|
||||
ordering.append('test2')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass2')
|
||||
|
||||
TestableTest.__module__ = 'Module1'
|
||||
sys.modules['Module1'] = Module1
|
||||
TestableTest2.__module__ = 'Module2'
|
||||
sys.modules['Module2'] = Module2
|
||||
runTests(TestableTest, TestableTest2)
|
||||
self.assertEqual(ordering, ['setUpModule', 'cleanup_good',
|
||||
'setUpModule2', 'setUpClass2', 'test2',
|
||||
'tearDownClass2', 'tearDownModule2',
|
||||
'cleanup_good'])
|
||||
ordering = []
|
||||
blowUp = False
|
||||
blowUp2 = True
|
||||
runTests(TestableTest, TestableTest2)
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||
'tearDownClass', 'tearDownModule',
|
||||
'cleanup_good', 'setUpModule2',
|
||||
'cleanup_good'])
|
||||
|
||||
ordering = []
|
||||
blowUp = False
|
||||
blowUp2 = False
|
||||
runTests(TestableTest, TestableTest2)
|
||||
self.assertEqual(ordering,
|
||||
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||
'tearDownModule', 'cleanup_good', 'setUpModule2',
|
||||
'setUpClass2', 'test2', 'tearDownClass2',
|
||||
'tearDownModule2', 'cleanup_good'])
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
def test_run_module_cleanUp_without_teardown(self):
|
||||
ordering = []
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering)
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||
'tearDownClass', 'cleanup_good'])
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
def test_run_module_cleanUp_when_teardown_exception(self):
|
||||
ordering = []
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering)
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
raise Exception('CleanUpExc')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||
'tearDownClass', 'cleanup_good'])
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
def test_debug_module_executes_cleanUp(self):
|
||||
ordering = []
|
||||
blowUp = False
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp)
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
suite.debug()
|
||||
self.assertEqual(ordering,
|
||||
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||
'tearDownModule', 'cleanup_good'])
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
ordering = []
|
||||
blowUp = True
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
with self.assertRaises(Exception) as cm:
|
||||
suite.debug()
|
||||
self.assertEqual(str(cm.exception), 'CleanUpExc')
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||
'tearDownClass', 'tearDownModule', 'cleanup_exc'])
|
||||
self.assertEqual(unittest.case._module_cleanups, [])
|
||||
|
||||
def test_debug_module_cleanUp_when_teardown_exception(self):
|
||||
ordering = []
|
||||
blowUp = False
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp)
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
raise Exception('TearDownModuleExc')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
with self.assertRaises(Exception) as cm:
|
||||
suite.debug()
|
||||
self.assertEqual(str(cm.exception), 'TearDownModuleExc')
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||
'tearDownClass'])
|
||||
self.assertTrue(unittest.case._module_cleanups)
|
||||
unittest.case._module_cleanups.clear()
|
||||
|
||||
ordering = []
|
||||
blowUp = True
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||
with self.assertRaises(Exception) as cm:
|
||||
suite.debug()
|
||||
self.assertEqual(str(cm.exception), 'TearDownModuleExc')
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||
'tearDownClass'])
|
||||
self.assertTrue(unittest.case._module_cleanups)
|
||||
unittest.case._module_cleanups.clear()
|
||||
|
||||
def test_addClassCleanup_arg_errors(self):
|
||||
cleanups = []
|
||||
def cleanup(*args, **kwargs):
|
||||
cleanups.append((args, kwargs))
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.addClassCleanup(cleanup, 1, 2, function=3, cls=4)
|
||||
with self.assertRaises(TypeError):
|
||||
cls.addClassCleanup(function=cleanup, arg='hello')
|
||||
def testNothing(self):
|
||||
pass
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
TestableTest.addClassCleanup()
|
||||
with self.assertRaises(TypeError):
|
||||
unittest.TestCase.addCleanup(cls=TestableTest(), function=cleanup)
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(cleanups,
|
||||
[((1, 2), {'function': 3, 'cls': 4})])
|
||||
|
||||
def test_addCleanup_arg_errors(self):
|
||||
cleanups = []
|
||||
def cleanup(*args, **kwargs):
|
||||
cleanups.append((args, kwargs))
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
def setUp(self2):
|
||||
self2.addCleanup(cleanup, 1, 2, function=3, self=4)
|
||||
with self.assertRaises(TypeError):
|
||||
self2.addCleanup(function=cleanup, arg='hello')
|
||||
def testNothing(self):
|
||||
pass
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
TestableTest().addCleanup()
|
||||
with self.assertRaises(TypeError):
|
||||
unittest.TestCase.addCleanup(self=TestableTest(), function=cleanup)
|
||||
runTests(TestableTest)
|
||||
self.assertEqual(cleanups,
|
||||
[((1, 2), {'function': 3, 'self': 4})])
|
||||
|
||||
def test_with_errors_in_addClassCleanup(self):
|
||||
ordering = []
|
||||
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering)
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
cls.addClassCleanup(cleanup, ordering, blowUp=True)
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||
'cleanup_exc', 'tearDownModule', 'cleanup_good'])
|
||||
|
||||
def test_with_errors_in_addCleanup(self):
|
||||
ordering = []
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering)
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
ordering.append('setUp')
|
||||
self.addCleanup(cleanup, ordering, blowUp=True)
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
def tearDown(self):
|
||||
ordering.append('tearDown')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpModule', 'setUp', 'test', 'tearDown',
|
||||
'cleanup_exc', 'tearDownModule', 'cleanup_good'])
|
||||
|
||||
def test_with_errors_in_addModuleCleanup_and_setUps(self):
|
||||
ordering = []
|
||||
module_blow_up = False
|
||||
class_blow_up = False
|
||||
method_blow_up = False
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup, ordering, blowUp=True)
|
||||
if module_blow_up:
|
||||
raise Exception('ModuleExc')
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
ordering.append('setUpClass')
|
||||
if class_blow_up:
|
||||
raise Exception('ClassExc')
|
||||
def setUp(self):
|
||||
ordering.append('setUp')
|
||||
if method_blow_up:
|
||||
raise Exception('MethodExc')
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
ordering.append('tearDownClass')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering,
|
||||
['setUpModule', 'setUpClass', 'setUp', 'test',
|
||||
'tearDownClass', 'tearDownModule',
|
||||
'cleanup_exc'])
|
||||
|
||||
ordering = []
|
||||
module_blow_up = True
|
||||
class_blow_up = False
|
||||
method_blow_up = False
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: ModuleExc')
|
||||
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering, ['setUpModule', 'cleanup_exc'])
|
||||
|
||||
ordering = []
|
||||
module_blow_up = False
|
||||
class_blow_up = True
|
||||
method_blow_up = False
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: ClassExc')
|
||||
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass',
|
||||
'tearDownModule', 'cleanup_exc'])
|
||||
|
||||
ordering = []
|
||||
module_blow_up = False
|
||||
class_blow_up = False
|
||||
method_blow_up = True
|
||||
result = runTests(TestableTest)
|
||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||
'Exception: MethodExc')
|
||||
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||
'Exception: CleanUpExc')
|
||||
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'setUp',
|
||||
'tearDownClass', 'tearDownModule',
|
||||
'cleanup_exc'])
|
||||
|
||||
def test_module_cleanUp_with_multiple_classes(self):
|
||||
ordering =[]
|
||||
def cleanup1():
|
||||
ordering.append('cleanup1')
|
||||
|
||||
def cleanup2():
|
||||
ordering.append('cleanup2')
|
||||
|
||||
def cleanup3():
|
||||
ordering.append('cleanup3')
|
||||
|
||||
class Module(object):
|
||||
@staticmethod
|
||||
def setUpModule():
|
||||
ordering.append('setUpModule')
|
||||
unittest.addModuleCleanup(cleanup1)
|
||||
@staticmethod
|
||||
def tearDownModule():
|
||||
ordering.append('tearDownModule')
|
||||
|
||||
class TestableTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
ordering.append('setUp')
|
||||
self.addCleanup(cleanup2)
|
||||
def testNothing(self):
|
||||
ordering.append('test')
|
||||
def tearDown(self):
|
||||
ordering.append('tearDown')
|
||||
|
||||
class OtherTestableTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
ordering.append('setUp2')
|
||||
self.addCleanup(cleanup3)
|
||||
def testNothing(self):
|
||||
ordering.append('test2')
|
||||
def tearDown(self):
|
||||
ordering.append('tearDown2')
|
||||
|
||||
TestableTest.__module__ = 'Module'
|
||||
OtherTestableTest.__module__ = 'Module'
|
||||
sys.modules['Module'] = Module
|
||||
runTests(TestableTest, OtherTestableTest)
|
||||
self.assertEqual(ordering,
|
||||
['setUpModule', 'setUp', 'test', 'tearDown',
|
||||
'cleanup2', 'setUp2', 'test2', 'tearDown2',
|
||||
'cleanup3', 'tearDownModule', 'cleanup1'])
|
||||
|
||||
|
||||
class Test_TextTestRunner(unittest.TestCase):
|
||||
"""Tests for TextTestRunner."""
|
||||
|
||||
@@ -276,7 +1137,6 @@ class Test_TextTestRunner(unittest.TestCase):
|
||||
expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY)
|
||||
self.assertEqual(runner._makeResult(), expectedresult)
|
||||
|
||||
|
||||
def test_warnings(self):
|
||||
"""
|
||||
Check that warnings argument of TextTestRunner correctly affects the
|
||||
|
||||
Vendored
+285
-15
@@ -7,30 +7,50 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
|
||||
def test_skipping(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def defaultTestResult(self):
|
||||
return LoggingResult(events)
|
||||
def test_skip_me(self):
|
||||
self.skipTest("skip")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_skip_me")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'stopTest'])
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
|
||||
events = []
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip',
|
||||
'stopTest', 'stopTestRun'])
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
self.assertEqual(result.testsRun, 1)
|
||||
|
||||
# Try letting setUp skip the test now.
|
||||
class Foo(unittest.TestCase):
|
||||
def defaultTestResult(self):
|
||||
return LoggingResult(events)
|
||||
def setUp(self):
|
||||
self.skipTest("testing")
|
||||
def test_nothing(self): pass
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_nothing")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'stopTest'])
|
||||
self.assertEqual(result.skipped, [(test, "testing")])
|
||||
self.assertEqual(result.testsRun, 1)
|
||||
|
||||
events = []
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip',
|
||||
'stopTest', 'stopTestRun'])
|
||||
self.assertEqual(result.skipped, [(test, "testing")])
|
||||
self.assertEqual(result.testsRun, 1)
|
||||
|
||||
def test_skipping_subtests(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def defaultTestResult(self):
|
||||
return LoggingResult(events)
|
||||
def test_skip_me(self):
|
||||
with self.subTest(a=1):
|
||||
with self.subTest(b=2):
|
||||
@@ -40,7 +60,7 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_skip_me")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'addSkip',
|
||||
'addSkip', 'stopTest'])
|
||||
self.assertEqual(len(result.skipped), 3)
|
||||
@@ -54,11 +74,22 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
self.assertIsNot(subtest, test)
|
||||
self.assertEqual(result.skipped[2], (test, "skip 3"))
|
||||
|
||||
events = []
|
||||
result = test.run()
|
||||
self.assertEqual(events,
|
||||
['startTestRun', 'startTest', 'addSkip', 'addSkip',
|
||||
'addSkip', 'stopTest', 'stopTestRun'])
|
||||
self.assertEqual([msg for subtest, msg in result.skipped],
|
||||
['skip 1', 'skip 2', 'skip 3'])
|
||||
|
||||
def test_skipping_decorators(self):
|
||||
op_table = ((unittest.skipUnless, False, True),
|
||||
(unittest.skipIf, True, False))
|
||||
for deco, do_skip, dont_skip in op_table:
|
||||
class Foo(unittest.TestCase):
|
||||
def defaultTestResult(self):
|
||||
return LoggingResult(events)
|
||||
|
||||
@deco(do_skip, "testing")
|
||||
def test_skip(self): pass
|
||||
|
||||
@@ -66,10 +97,11 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
def test_dont_skip(self): pass
|
||||
test_do_skip = Foo("test_skip")
|
||||
test_dont_skip = Foo("test_dont_skip")
|
||||
|
||||
suite = unittest.TestSuite([test_do_skip, test_dont_skip])
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
suite.run(result)
|
||||
self.assertIs(suite.run(result), result)
|
||||
self.assertEqual(len(result.skipped), 1)
|
||||
expected = ['startTest', 'addSkip', 'stopTest',
|
||||
'startTest', 'addSuccess', 'stopTest']
|
||||
@@ -78,16 +110,39 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
self.assertEqual(result.skipped, [(test_do_skip, "testing")])
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
events = []
|
||||
result = test_do_skip.run()
|
||||
self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip',
|
||||
'stopTest', 'stopTestRun'])
|
||||
self.assertEqual(result.skipped, [(test_do_skip, "testing")])
|
||||
|
||||
events = []
|
||||
result = test_dont_skip.run()
|
||||
self.assertEqual(events, ['startTestRun', 'startTest', 'addSuccess',
|
||||
'stopTest', 'stopTestRun'])
|
||||
self.assertEqual(result.skipped, [])
|
||||
|
||||
def test_skip_class(self):
|
||||
@unittest.skip("testing")
|
||||
class Foo(unittest.TestCase):
|
||||
def defaultTestResult(self):
|
||||
return LoggingResult(events)
|
||||
def test_1(self):
|
||||
record.append(1)
|
||||
events = []
|
||||
record = []
|
||||
result = unittest.TestResult()
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_1")
|
||||
suite = unittest.TestSuite([test])
|
||||
suite.run(result)
|
||||
self.assertIs(suite.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'stopTest'])
|
||||
self.assertEqual(result.skipped, [(test, "testing")])
|
||||
self.assertEqual(record, [])
|
||||
|
||||
events = []
|
||||
result = test.run()
|
||||
self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip',
|
||||
'stopTest', 'stopTestRun'])
|
||||
self.assertEqual(result.skipped, [(test, "testing")])
|
||||
self.assertEqual(record, [])
|
||||
|
||||
@@ -102,10 +157,62 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
result = unittest.TestResult()
|
||||
test = Foo("test_1")
|
||||
suite = unittest.TestSuite([test])
|
||||
suite.run(result)
|
||||
self.assertIs(suite.run(result), result)
|
||||
self.assertEqual(result.skipped, [(test, "testing")])
|
||||
self.assertEqual(record, [])
|
||||
|
||||
def test_skip_in_setup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest("skip")
|
||||
def test_skip_me(self):
|
||||
self.fail("shouldn't come here")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_skip_me")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'stopTest'])
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
|
||||
def test_skip_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def test_skip_me(self):
|
||||
pass
|
||||
def tearDown(self):
|
||||
self.skipTest("skip")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_skip_me")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'stopTest'])
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
|
||||
def test_failure_and_skip_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def test_skip_me(self):
|
||||
self.fail("fail")
|
||||
def tearDown(self):
|
||||
self.skipTest("skip")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_skip_me")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'addFailure', 'stopTest'])
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
|
||||
def test_skipping_and_fail_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def test_skip_me(self):
|
||||
self.skipTest("skip")
|
||||
def tearDown(self):
|
||||
self.fail("fail")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_skip_me")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events, ['startTest', 'addSkip', 'addFailure', 'stopTest'])
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
|
||||
def test_expected_failure(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
@@ -114,10 +221,12 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addExpectedFailure', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertEqual(result.expectedFailures[0][0], test)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
def test_expected_failure_with_wrapped_class(self):
|
||||
@@ -129,10 +238,12 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_1")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addExpectedFailure', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertEqual(result.expectedFailures[0][0], test)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
def test_expected_failure_with_wrapped_subclass(self):
|
||||
@@ -147,10 +258,12 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Bar("test_1")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addExpectedFailure', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertEqual(result.expectedFailures[0][0], test)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
def test_expected_failure_subtests(self):
|
||||
@@ -170,12 +283,52 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addSubTestSuccess',
|
||||
'addExpectedFailure', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertEqual(len(result.expectedFailures), 1)
|
||||
self.assertIs(result.expectedFailures[0][0], test)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
def test_expected_failure_and_fail_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
def test_die(self):
|
||||
self.fail("help me!")
|
||||
def tearDown(self):
|
||||
self.fail("bad tearDown")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addFailure', 'stopTest'])
|
||||
self.assertEqual(len(result.failures), 1)
|
||||
self.assertIn('AssertionError: bad tearDown', result.failures[0][1])
|
||||
self.assertFalse(result.expectedFailures)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertFalse(result.wasSuccessful())
|
||||
|
||||
def test_expected_failure_and_skip_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
def test_die(self):
|
||||
self.fail("help me!")
|
||||
def tearDown(self):
|
||||
self.skipTest("skip")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addSkip', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertFalse(result.expectedFailures)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
def test_unexpected_success(self):
|
||||
@@ -186,10 +339,11 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addUnexpectedSuccess', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertFalse(result.expectedFailures)
|
||||
self.assertEqual(result.unexpectedSuccesses, [test])
|
||||
self.assertFalse(result.wasSuccessful())
|
||||
|
||||
@@ -208,15 +362,54 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
test.run(result)
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest',
|
||||
'addSubTestSuccess', 'addSubTestSuccess',
|
||||
'addUnexpectedSuccess', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertFalse(result.expectedFailures)
|
||||
self.assertEqual(result.unexpectedSuccesses, [test])
|
||||
self.assertFalse(result.wasSuccessful())
|
||||
|
||||
def test_unexpected_success_and_fail_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
def test_die(self):
|
||||
pass
|
||||
def tearDown(self):
|
||||
self.fail("bad tearDown")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addFailure', 'stopTest'])
|
||||
self.assertEqual(len(result.failures), 1)
|
||||
self.assertIn('AssertionError: bad tearDown', result.failures[0][1])
|
||||
self.assertFalse(result.expectedFailures)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertFalse(result.wasSuccessful())
|
||||
|
||||
def test_unexpected_success_and_skip_in_cleanup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
def test_die(self):
|
||||
pass
|
||||
def tearDown(self):
|
||||
self.skipTest("skip")
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test_die")
|
||||
self.assertIs(test.run(result), result)
|
||||
self.assertEqual(events,
|
||||
['startTest', 'addSkip', 'stopTest'])
|
||||
self.assertFalse(result.failures)
|
||||
self.assertFalse(result.expectedFailures)
|
||||
self.assertFalse(result.unexpectedSuccesses)
|
||||
self.assertEqual(result.skipped, [(test, "skip")])
|
||||
self.assertTrue(result.wasSuccessful())
|
||||
|
||||
def test_skip_doesnt_run_setup(self):
|
||||
class Foo(unittest.TestCase):
|
||||
wasSetUp = False
|
||||
@@ -232,7 +425,7 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
result = unittest.TestResult()
|
||||
test = Foo("test_1")
|
||||
suite = unittest.TestSuite([test])
|
||||
suite.run(result)
|
||||
self.assertIs(suite.run(result), result)
|
||||
self.assertEqual(result.skipped, [(test, "testing")])
|
||||
self.assertFalse(Foo.wasSetUp)
|
||||
self.assertFalse(Foo.wasTornDown)
|
||||
@@ -252,9 +445,86 @@ class Test_TestSkipping(unittest.TestCase):
|
||||
result = unittest.TestResult()
|
||||
test = Foo("test_1")
|
||||
suite = unittest.TestSuite([test])
|
||||
suite.run(result)
|
||||
self.assertIs(suite.run(result), result)
|
||||
self.assertEqual(result.skipped, [(test, "testing")])
|
||||
|
||||
def test_skip_without_reason(self):
|
||||
class Foo(unittest.TestCase):
|
||||
@unittest.skip
|
||||
def test_1(self):
|
||||
pass
|
||||
|
||||
result = unittest.TestResult()
|
||||
test = Foo("test_1")
|
||||
suite = unittest.TestSuite([test])
|
||||
self.assertIs(suite.run(result), result)
|
||||
self.assertEqual(result.skipped, [(test, "")])
|
||||
|
||||
def test_debug_skipping(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
events.append("setUp")
|
||||
def tearDown(self):
|
||||
events.append("tearDown")
|
||||
def test1(self):
|
||||
self.skipTest('skipping exception')
|
||||
events.append("test1")
|
||||
@unittest.skip("skipping decorator")
|
||||
def test2(self):
|
||||
events.append("test2")
|
||||
|
||||
events = []
|
||||
test = Foo("test1")
|
||||
with self.assertRaises(unittest.SkipTest) as cm:
|
||||
test.debug()
|
||||
self.assertIn("skipping exception", str(cm.exception))
|
||||
self.assertEqual(events, ["setUp"])
|
||||
|
||||
events = []
|
||||
test = Foo("test2")
|
||||
with self.assertRaises(unittest.SkipTest) as cm:
|
||||
test.debug()
|
||||
self.assertIn("skipping decorator", str(cm.exception))
|
||||
self.assertEqual(events, [])
|
||||
|
||||
def test_debug_skipping_class(self):
|
||||
@unittest.skip("testing")
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
events.append("setUp")
|
||||
def tearDown(self):
|
||||
events.append("tearDown")
|
||||
def test(self):
|
||||
events.append("test")
|
||||
|
||||
events = []
|
||||
test = Foo("test")
|
||||
with self.assertRaises(unittest.SkipTest) as cm:
|
||||
test.debug()
|
||||
self.assertIn("testing", str(cm.exception))
|
||||
self.assertEqual(events, [])
|
||||
|
||||
def test_debug_skipping_subtests(self):
|
||||
class Foo(unittest.TestCase):
|
||||
def setUp(self):
|
||||
events.append("setUp")
|
||||
def tearDown(self):
|
||||
events.append("tearDown")
|
||||
def test(self):
|
||||
with self.subTest(a=1):
|
||||
events.append('subtest')
|
||||
self.skipTest("skip subtest")
|
||||
events.append('end subtest')
|
||||
events.append('end test')
|
||||
|
||||
events = []
|
||||
result = LoggingResult(events)
|
||||
test = Foo("test")
|
||||
with self.assertRaises(unittest.SkipTest) as cm:
|
||||
test.debug()
|
||||
self.assertIn("skip subtest", str(cm.exception))
|
||||
self.assertEqual(events, ['setUp', 'subtest'])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
import unittest
|
||||
|
||||
# import gc
|
||||
import gc
|
||||
import sys
|
||||
import weakref
|
||||
from unittest.test.support import LoggingResult, TestEquality
|
||||
|
||||
+4
-9
@@ -1,3 +1,6 @@
|
||||
target = {'foo': 'FOO'}
|
||||
|
||||
|
||||
def is_instance(obj, klass):
|
||||
"""Version of is_instance that doesn't access __class__"""
|
||||
return issubclass(type(obj), klass)
|
||||
@@ -6,16 +9,8 @@ def is_instance(obj, klass):
|
||||
class SomeClass(object):
|
||||
class_attribute = None
|
||||
|
||||
def wibble(self):
|
||||
pass
|
||||
def wibble(self): pass
|
||||
|
||||
|
||||
class X(object):
|
||||
pass
|
||||
|
||||
|
||||
def examine_warnings(func):
|
||||
def wrapper():
|
||||
with catch_warnings(record=True) as ws:
|
||||
func(ws)
|
||||
return wrapper
|
||||
+1059
File diff suppressed because it is too large.
Load diff
+2
-3
@@ -98,8 +98,7 @@ class TestCallable(unittest.TestCase):
|
||||
|
||||
def test_patch_spec_callable_class(self):
|
||||
class CallableX(X):
|
||||
def __call__(self):
|
||||
pass
|
||||
def __call__(self): pass
|
||||
|
||||
class Sub(CallableX):
|
||||
pass
|
||||
@@ -128,7 +127,7 @@ class TestCallable(unittest.TestCase):
|
||||
result.foo.assert_called_once_with(3, 2, 1)
|
||||
|
||||
|
||||
def test_create_autopsec(self):
|
||||
def test_create_autospec(self):
|
||||
mock = create_autospec(X)
|
||||
instance = mock()
|
||||
self.assertRaises(TypeError, instance)
|
||||
|
||||
+255
-74
@@ -1,21 +1,20 @@
|
||||
import inspect
|
||||
import time
|
||||
import types
|
||||
import unittest
|
||||
|
||||
from unittest.mock import (
|
||||
call, _Call, create_autospec, MagicMock,
|
||||
Mock, ANY, _CallList, patch, PropertyMock
|
||||
Mock, ANY, _CallList, patch, PropertyMock, _callable
|
||||
)
|
||||
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
|
||||
class SomeClass(object):
|
||||
def one(self, a, b):
|
||||
pass
|
||||
def two(self):
|
||||
pass
|
||||
def three(self, a=None):
|
||||
pass
|
||||
def one(self, a, b): pass
|
||||
def two(self): pass
|
||||
def three(self, a=None): pass
|
||||
|
||||
|
||||
|
||||
@@ -46,12 +45,9 @@ class AnyTest(unittest.TestCase):
|
||||
|
||||
def test_any_mock_calls_comparison_order(self):
|
||||
mock = Mock()
|
||||
d = datetime.now()
|
||||
class Foo(object):
|
||||
def __eq__(self, other):
|
||||
return False
|
||||
def __ne__(self, other):
|
||||
return True
|
||||
def __eq__(self, other): pass
|
||||
def __ne__(self, other): pass
|
||||
|
||||
for d in datetime.now(), Foo():
|
||||
mock.reset_mock()
|
||||
@@ -68,7 +64,28 @@ class AnyTest(unittest.TestCase):
|
||||
self.assertEqual(expected, mock.mock_calls)
|
||||
self.assertEqual(mock.mock_calls, expected)
|
||||
|
||||
def test_any_no_spec(self):
|
||||
# This is a regression test for bpo-37555
|
||||
class Foo:
|
||||
def __eq__(self, other): pass
|
||||
|
||||
mock = Mock()
|
||||
mock(Foo(), 1)
|
||||
mock.assert_has_calls([call(ANY, 1)])
|
||||
mock.assert_called_with(ANY, 1)
|
||||
mock.assert_any_call(ANY, 1)
|
||||
|
||||
def test_any_and_spec_set(self):
|
||||
# This is a regression test for bpo-37555
|
||||
class Foo:
|
||||
def __eq__(self, other): pass
|
||||
|
||||
mock = Mock(spec=Foo)
|
||||
|
||||
mock(Foo(), 1)
|
||||
mock.assert_has_calls([call(ANY, 1)])
|
||||
mock.assert_called_with(ANY, 1)
|
||||
mock.assert_any_call(ANY, 1)
|
||||
|
||||
class CallTest(unittest.TestCase):
|
||||
|
||||
@@ -144,6 +161,8 @@ class CallTest(unittest.TestCase):
|
||||
self.assertEqual(args, ('foo', (1, 2, 3)))
|
||||
self.assertEqual(args, ('foo', (1, 2, 3), {}))
|
||||
self.assertEqual(args, ((1, 2, 3), {}))
|
||||
self.assertEqual(args.args, (1, 2, 3))
|
||||
self.assertEqual(args.kwargs, {})
|
||||
|
||||
|
||||
def test_named_call_with_args(self):
|
||||
@@ -151,6 +170,8 @@ class CallTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(args, ('foo', (1, 2, 3)))
|
||||
self.assertEqual(args, ('foo', (1, 2, 3), {}))
|
||||
self.assertEqual(args.args, (1, 2, 3))
|
||||
self.assertEqual(args.kwargs, {})
|
||||
|
||||
self.assertNotEqual(args, ((1, 2, 3),))
|
||||
self.assertNotEqual(args, ((1, 2, 3), {}))
|
||||
@@ -163,6 +184,8 @@ class CallTest(unittest.TestCase):
|
||||
self.assertEqual(args, ('foo', dict(a=3, b=4)))
|
||||
self.assertEqual(args, ('foo', (), dict(a=3, b=4)))
|
||||
self.assertEqual(args, ((), dict(a=3, b=4)))
|
||||
self.assertEqual(args.args, ())
|
||||
self.assertEqual(args.kwargs, dict(a=3, b=4))
|
||||
|
||||
|
||||
def test_named_call_with_kwargs(self):
|
||||
@@ -170,6 +193,8 @@ class CallTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(args, ('foo', dict(a=3, b=4)))
|
||||
self.assertEqual(args, ('foo', (), dict(a=3, b=4)))
|
||||
self.assertEqual(args.args, ())
|
||||
self.assertEqual(args.kwargs, dict(a=3, b=4))
|
||||
|
||||
self.assertNotEqual(args, (dict(a=3, b=4),))
|
||||
self.assertNotEqual(args, ((), dict(a=3, b=4)))
|
||||
@@ -177,6 +202,7 @@ class CallTest(unittest.TestCase):
|
||||
|
||||
def test_call_with_args_call_empty_name(self):
|
||||
args = _Call(((1, 2, 3), {}))
|
||||
|
||||
self.assertEqual(args, call(1, 2, 3))
|
||||
self.assertEqual(call(1, 2, 3), args)
|
||||
self.assertIn(call(1, 2, 3), [args])
|
||||
@@ -269,6 +295,22 @@ class CallTest(unittest.TestCase):
|
||||
self.assertEqual(mock.mock_calls, last_call.call_list())
|
||||
|
||||
|
||||
def test_extended_not_equal(self):
|
||||
a = call(x=1).foo
|
||||
b = call(x=2).foo
|
||||
self.assertEqual(a, a)
|
||||
self.assertEqual(b, b)
|
||||
self.assertNotEqual(a, b)
|
||||
|
||||
|
||||
def test_nested_calls_not_equal(self):
|
||||
a = call(x=1).foo().bar
|
||||
b = call(x=2).foo().bar
|
||||
self.assertEqual(a, a)
|
||||
self.assertEqual(b, b)
|
||||
self.assertNotEqual(a, b)
|
||||
|
||||
|
||||
def test_call_list(self):
|
||||
mock = MagicMock()
|
||||
mock(1)
|
||||
@@ -313,6 +355,26 @@ class CallTest(unittest.TestCase):
|
||||
self.assertEqual(_Call((('bar', 'barz'),),)[0], '')
|
||||
self.assertEqual(_Call((('bar', 'barz'), {'hello': 'world'}),)[0], '')
|
||||
|
||||
def test_dunder_call(self):
|
||||
m = MagicMock()
|
||||
m().foo()['bar']()
|
||||
self.assertEqual(
|
||||
m.mock_calls,
|
||||
[call(), call().foo(), call().foo().__getitem__('bar'), call().foo().__getitem__()()]
|
||||
)
|
||||
m = MagicMock()
|
||||
m().foo()['bar'] = 1
|
||||
self.assertEqual(
|
||||
m.mock_calls,
|
||||
[call(), call().foo(), call().foo().__setitem__('bar', 1)]
|
||||
)
|
||||
m = MagicMock()
|
||||
iter(m().foo())
|
||||
self.assertEqual(
|
||||
m.mock_calls,
|
||||
[call(), call().foo(), call().foo().__iter__()]
|
||||
)
|
||||
|
||||
|
||||
class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
@@ -351,8 +413,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_create_autospec_return_value(self):
|
||||
def f():
|
||||
pass
|
||||
def f(): pass
|
||||
mock = create_autospec(f, return_value='foo')
|
||||
self.assertEqual(mock(), 'foo')
|
||||
|
||||
@@ -372,8 +433,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
def test_mocking_unbound_methods(self):
|
||||
class Foo(object):
|
||||
def foo(self, foo):
|
||||
pass
|
||||
def foo(self, foo): pass
|
||||
p = patch.object(Foo, 'foo')
|
||||
mock_foo = p.start()
|
||||
Foo().foo(1)
|
||||
@@ -381,24 +441,6 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
mock_foo.assert_called_with(1)
|
||||
|
||||
|
||||
def test_create_autospec_unbound_methods(self):
|
||||
# see mock issue 128
|
||||
# this is expected to fail until the issue is fixed
|
||||
return
|
||||
class Foo(object):
|
||||
def foo(self):
|
||||
pass
|
||||
|
||||
klass = create_autospec(Foo)
|
||||
instance = klass()
|
||||
self.assertRaises(TypeError, instance.foo, 1)
|
||||
|
||||
# Note: no type checking on the "self" parameter
|
||||
klass.foo(1)
|
||||
klass.foo.assert_called_with(1)
|
||||
self.assertRaises(TypeError, klass.foo)
|
||||
|
||||
|
||||
def test_create_autospec_keyword_arguments(self):
|
||||
class Foo(object):
|
||||
a = 3
|
||||
@@ -407,8 +449,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_create_autospec_keyword_only_arguments(self):
|
||||
def foo(a, *, b=None):
|
||||
pass
|
||||
def foo(a, *, b=None): pass
|
||||
|
||||
m = create_autospec(foo)
|
||||
m(1)
|
||||
@@ -421,8 +462,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
def test_function_as_instance_attribute(self):
|
||||
obj = SomeClass()
|
||||
def f(a):
|
||||
pass
|
||||
def f(a): pass
|
||||
obj.f = f
|
||||
|
||||
mock = create_autospec(obj)
|
||||
@@ -458,13 +498,57 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
self._check_someclass_mock(mock)
|
||||
|
||||
|
||||
def test_spec_has_descriptor_returning_function(self):
|
||||
|
||||
class CrazyDescriptor(object):
|
||||
|
||||
def __get__(self, obj, type_):
|
||||
if obj is None:
|
||||
return lambda x: None
|
||||
|
||||
class MyClass(object):
|
||||
|
||||
some_attr = CrazyDescriptor()
|
||||
|
||||
mock = create_autospec(MyClass)
|
||||
mock.some_attr(1)
|
||||
with self.assertRaises(TypeError):
|
||||
mock.some_attr()
|
||||
with self.assertRaises(TypeError):
|
||||
mock.some_attr(1, 2)
|
||||
|
||||
|
||||
def test_spec_has_function_not_in_bases(self):
|
||||
|
||||
class CrazyClass(object):
|
||||
|
||||
def __dir__(self):
|
||||
return super(CrazyClass, self).__dir__()+['crazy']
|
||||
|
||||
def __getattr__(self, item):
|
||||
if item == 'crazy':
|
||||
return lambda x: x
|
||||
raise AttributeError(item)
|
||||
|
||||
inst = CrazyClass()
|
||||
with self.assertRaises(AttributeError):
|
||||
inst.other
|
||||
self.assertEqual(inst.crazy(42), 42)
|
||||
|
||||
mock = create_autospec(inst)
|
||||
mock.crazy(42)
|
||||
with self.assertRaises(TypeError):
|
||||
mock.crazy()
|
||||
with self.assertRaises(TypeError):
|
||||
mock.crazy(1, 2)
|
||||
|
||||
|
||||
def test_builtin_functions_types(self):
|
||||
# we could replace builtin functions / methods with a function
|
||||
# with *args / **kwargs signature. Using the builtin method type
|
||||
# as a spec seems to work fairly well though.
|
||||
class BuiltinSubclass(list):
|
||||
def bar(self, arg):
|
||||
pass
|
||||
def bar(self, arg): pass
|
||||
sorted = sorted
|
||||
attr = {}
|
||||
|
||||
@@ -538,17 +622,13 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
def test_descriptors(self):
|
||||
class Foo(object):
|
||||
@classmethod
|
||||
def f(cls, a, b):
|
||||
pass
|
||||
def f(cls, a, b): pass
|
||||
@staticmethod
|
||||
def g(a, b):
|
||||
pass
|
||||
def g(a, b): pass
|
||||
|
||||
class Bar(Foo):
|
||||
pass
|
||||
class Bar(Foo): pass
|
||||
|
||||
class Baz(SomeClass, Bar):
|
||||
pass
|
||||
class Baz(SomeClass, Bar): pass
|
||||
|
||||
for spec in (Foo, Foo(), Bar, Bar(), Baz, Baz()):
|
||||
mock = create_autospec(spec)
|
||||
@@ -561,8 +641,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
def test_recursive(self):
|
||||
class A(object):
|
||||
def a(self):
|
||||
pass
|
||||
def a(self): pass
|
||||
foo = 'foo bar baz'
|
||||
bar = foo
|
||||
|
||||
@@ -584,11 +663,9 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
def test_spec_inheritance_for_classes(self):
|
||||
class Foo(object):
|
||||
def a(self, x):
|
||||
pass
|
||||
def a(self, x): pass
|
||||
class Bar(object):
|
||||
def f(self, y):
|
||||
pass
|
||||
def f(self, y): pass
|
||||
|
||||
class_mock = create_autospec(Foo)
|
||||
|
||||
@@ -668,8 +745,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_function(self):
|
||||
def f(a, b):
|
||||
pass
|
||||
def f(a, b): pass
|
||||
|
||||
mock = create_autospec(f)
|
||||
self.assertRaises(TypeError, mock)
|
||||
@@ -699,9 +775,10 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
def existing(a, b):
|
||||
return a + b
|
||||
|
||||
self.assertEqual(RaiserClass.existing(1, 2), 3)
|
||||
s = create_autospec(RaiserClass)
|
||||
self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3))
|
||||
s.existing(1, 2)
|
||||
self.assertEqual(s.existing(1, 2), s.existing.return_value)
|
||||
self.assertRaises(AttributeError, lambda: s.nonexisting)
|
||||
|
||||
# check we can fetch the raiser attribute and it has no spec
|
||||
@@ -711,8 +788,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
def test_signature_class(self):
|
||||
class Foo(object):
|
||||
def __init__(self, a, b=3):
|
||||
pass
|
||||
def __init__(self, a, b=3): pass
|
||||
|
||||
mock = create_autospec(Foo)
|
||||
|
||||
@@ -738,10 +814,8 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
def test_signature_callable(self):
|
||||
class Callable(object):
|
||||
def __init__(self, x, y):
|
||||
pass
|
||||
def __call__(self, a):
|
||||
pass
|
||||
def __init__(self, x, y): pass
|
||||
def __call__(self, a): pass
|
||||
|
||||
mock = create_autospec(Callable)
|
||||
mock(1, 2)
|
||||
@@ -797,8 +871,7 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
|
||||
def test_autospec_functions_with_self_in_odd_place(self):
|
||||
class Foo(object):
|
||||
def f(a, self):
|
||||
pass
|
||||
def f(a, self): pass
|
||||
|
||||
a = create_autospec(Foo)
|
||||
a.f(10)
|
||||
@@ -815,12 +888,9 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
self.value = value
|
||||
|
||||
def __get__(self, obj, cls=None):
|
||||
if obj is None:
|
||||
return self
|
||||
return self.value
|
||||
return self
|
||||
|
||||
def __set__(self, obj, value):
|
||||
pass
|
||||
def __set__(self, obj, value): pass
|
||||
|
||||
class MyProperty(property):
|
||||
pass
|
||||
@@ -829,12 +899,10 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
__slots__ = ['slot']
|
||||
|
||||
@property
|
||||
def prop(self):
|
||||
return 3
|
||||
def prop(self): pass
|
||||
|
||||
@MyProperty
|
||||
def subprop(self):
|
||||
return 4
|
||||
def subprop(self): pass
|
||||
|
||||
desc = Descriptor(42)
|
||||
|
||||
@@ -871,6 +939,84 @@ class SpecSignatureTest(unittest.TestCase):
|
||||
mocked.assert_called_once_with(4, 5, 6)
|
||||
|
||||
|
||||
def test_autospec_getattr_partial_function(self):
|
||||
# bpo-32153 : getattr returning partial functions without
|
||||
# __name__ should not create AttributeError in create_autospec
|
||||
class Foo:
|
||||
|
||||
def __getattr__(self, attribute):
|
||||
return partial(lambda name: name, attribute)
|
||||
|
||||
proxy = Foo()
|
||||
autospec = create_autospec(proxy)
|
||||
self.assertFalse(hasattr(autospec, '__name__'))
|
||||
|
||||
|
||||
def test_spec_inspect_signature(self):
|
||||
|
||||
def myfunc(x, y): pass
|
||||
|
||||
mock = create_autospec(myfunc)
|
||||
mock(1, 2)
|
||||
mock(x=1, y=2)
|
||||
|
||||
self.assertEqual(inspect.signature(mock), inspect.signature(myfunc))
|
||||
self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)])
|
||||
self.assertRaises(TypeError, mock, 1)
|
||||
|
||||
|
||||
def test_spec_inspect_signature_annotations(self):
|
||||
|
||||
def foo(a: int, b: int=10, *, c:int) -> int:
|
||||
return a + b + c
|
||||
|
||||
self.assertEqual(foo(1, 2 , c=3), 6)
|
||||
mock = create_autospec(foo)
|
||||
mock(1, 2, c=3)
|
||||
mock(1, c=3)
|
||||
|
||||
self.assertEqual(inspect.signature(mock), inspect.signature(foo))
|
||||
self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)])
|
||||
self.assertRaises(TypeError, mock, 1)
|
||||
self.assertRaises(TypeError, mock, 1, 2, 3, c=4)
|
||||
|
||||
|
||||
def test_spec_function_no_name(self):
|
||||
func = lambda: 'nope'
|
||||
mock = create_autospec(func)
|
||||
self.assertEqual(mock.__name__, 'funcopy')
|
||||
|
||||
|
||||
def test_spec_function_assert_has_calls(self):
|
||||
def f(a): pass
|
||||
mock = create_autospec(f)
|
||||
mock(1)
|
||||
mock.assert_has_calls([call(1)])
|
||||
with self.assertRaises(AssertionError):
|
||||
mock.assert_has_calls([call(2)])
|
||||
|
||||
|
||||
def test_spec_function_assert_any_call(self):
|
||||
def f(a): pass
|
||||
mock = create_autospec(f)
|
||||
mock(1)
|
||||
mock.assert_any_call(1)
|
||||
with self.assertRaises(AssertionError):
|
||||
mock.assert_any_call(2)
|
||||
|
||||
|
||||
def test_spec_function_reset_mock(self):
|
||||
def f(a): pass
|
||||
rv = Mock()
|
||||
mock = create_autospec(f, return_value=rv)
|
||||
mock(1)(2)
|
||||
self.assertEqual(mock.mock_calls, [call(1)])
|
||||
self.assertEqual(rv.mock_calls, [call(2)])
|
||||
mock.reset_mock()
|
||||
self.assertEqual(mock.mock_calls, [])
|
||||
self.assertEqual(rv.mock_calls, [])
|
||||
|
||||
|
||||
class TestCallList(unittest.TestCase):
|
||||
|
||||
def test_args_list_contains_call_list(self):
|
||||
@@ -942,5 +1088,40 @@ class TestCallList(unittest.TestCase):
|
||||
self.assertNotIsInstance(returned, PropertyMock)
|
||||
|
||||
|
||||
class TestCallablePredicate(unittest.TestCase):
|
||||
|
||||
def test_type(self):
|
||||
for obj in [str, bytes, int, list, tuple, SomeClass]:
|
||||
self.assertTrue(_callable(obj))
|
||||
|
||||
def test_call_magic_method(self):
|
||||
class Callable:
|
||||
def __call__(self): pass
|
||||
instance = Callable()
|
||||
self.assertTrue(_callable(instance))
|
||||
|
||||
def test_staticmethod(self):
|
||||
class WithStaticMethod:
|
||||
@staticmethod
|
||||
def staticfunc(): pass
|
||||
self.assertTrue(_callable(WithStaticMethod.staticfunc))
|
||||
|
||||
def test_non_callable_staticmethod(self):
|
||||
class BadStaticMethod:
|
||||
not_callable = staticmethod(None)
|
||||
self.assertFalse(_callable(BadStaticMethod.not_callable))
|
||||
|
||||
def test_classmethod(self):
|
||||
class WithClassMethod:
|
||||
@classmethod
|
||||
def classfunc(cls): pass
|
||||
self.assertTrue(_callable(WithClassMethod.classfunc))
|
||||
|
||||
def test_non_callable_classmethod(self):
|
||||
class BadClassMethod:
|
||||
not_callable = classmethod(None)
|
||||
self.assertFalse(_callable(BadClassMethod.not_callable))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
+48
-7
@@ -1,6 +1,8 @@
|
||||
import math
|
||||
import unittest
|
||||
import sys
|
||||
from unittest.mock import Mock, MagicMock, _magics
|
||||
import os
|
||||
from asyncio import iscoroutinefunction
|
||||
from unittest.mock import AsyncMock, Mock, MagicMock, _magics
|
||||
|
||||
|
||||
|
||||
@@ -268,6 +270,31 @@ class TestMockingMagicMethods(unittest.TestCase):
|
||||
self.assertEqual(mock == mock, True)
|
||||
self.assertEqual(mock != mock, False)
|
||||
|
||||
def test_asyncmock_defaults(self):
|
||||
mock = AsyncMock()
|
||||
self.assertEqual(int(mock), 1)
|
||||
self.assertEqual(complex(mock), 1j)
|
||||
self.assertEqual(float(mock), 1.0)
|
||||
self.assertNotIn(object(), mock)
|
||||
self.assertEqual(len(mock), 0)
|
||||
self.assertEqual(list(mock), [])
|
||||
self.assertEqual(hash(mock), object.__hash__(mock))
|
||||
self.assertEqual(str(mock), object.__str__(mock))
|
||||
self.assertTrue(bool(mock))
|
||||
self.assertEqual(round(mock), mock.__round__())
|
||||
self.assertEqual(math.trunc(mock), mock.__trunc__())
|
||||
self.assertEqual(math.floor(mock), mock.__floor__())
|
||||
self.assertEqual(math.ceil(mock), mock.__ceil__())
|
||||
self.assertTrue(iscoroutinefunction(mock.__aexit__))
|
||||
self.assertTrue(iscoroutinefunction(mock.__aenter__))
|
||||
self.assertIsInstance(mock.__aenter__, AsyncMock)
|
||||
self.assertIsInstance(mock.__aexit__, AsyncMock)
|
||||
|
||||
# in Python 3 oct and hex use __index__
|
||||
# so these tests are for __index__ in py3k
|
||||
self.assertEqual(oct(mock), '0o1')
|
||||
self.assertEqual(hex(mock), '0x1')
|
||||
# how to test __sizeof__ ?
|
||||
|
||||
def test_magicmock_defaults(self):
|
||||
mock = MagicMock()
|
||||
@@ -280,6 +307,14 @@ class TestMockingMagicMethods(unittest.TestCase):
|
||||
self.assertEqual(hash(mock), object.__hash__(mock))
|
||||
self.assertEqual(str(mock), object.__str__(mock))
|
||||
self.assertTrue(bool(mock))
|
||||
self.assertEqual(round(mock), mock.__round__())
|
||||
self.assertEqual(math.trunc(mock), mock.__trunc__())
|
||||
self.assertEqual(math.floor(mock), mock.__floor__())
|
||||
self.assertEqual(math.ceil(mock), mock.__ceil__())
|
||||
self.assertTrue(iscoroutinefunction(mock.__aexit__))
|
||||
self.assertTrue(iscoroutinefunction(mock.__aenter__))
|
||||
self.assertIsInstance(mock.__aenter__, AsyncMock)
|
||||
self.assertIsInstance(mock.__aexit__, AsyncMock)
|
||||
|
||||
# in Python 3 oct and hex use __index__
|
||||
# so these tests are for __index__ in py3k
|
||||
@@ -288,10 +323,18 @@ class TestMockingMagicMethods(unittest.TestCase):
|
||||
# how to test __sizeof__ ?
|
||||
|
||||
|
||||
def test_magic_methods_fspath(self):
|
||||
mock = MagicMock()
|
||||
expected_path = mock.__fspath__()
|
||||
mock.reset_mock()
|
||||
|
||||
self.assertEqual(os.fspath(mock), expected_path)
|
||||
mock.__fspath__.assert_called_once()
|
||||
|
||||
|
||||
def test_magic_methods_and_spec(self):
|
||||
class Iterable(object):
|
||||
def __iter__(self):
|
||||
pass
|
||||
def __iter__(self): pass
|
||||
|
||||
mock = Mock(spec=Iterable)
|
||||
self.assertRaises(AttributeError, lambda: mock.__iter__)
|
||||
@@ -315,8 +358,7 @@ class TestMockingMagicMethods(unittest.TestCase):
|
||||
|
||||
def test_magic_methods_and_spec_set(self):
|
||||
class Iterable(object):
|
||||
def __iter__(self):
|
||||
pass
|
||||
def __iter__(self): pass
|
||||
|
||||
mock = Mock(spec_set=Iterable)
|
||||
self.assertRaises(AttributeError, lambda: mock.__iter__)
|
||||
@@ -386,7 +428,6 @@ class TestMockingMagicMethods(unittest.TestCase):
|
||||
self.assertEqual(dir(mock), ['foo'])
|
||||
|
||||
|
||||
@unittest.skipIf('PyPy' in sys.version, "This fails differently on pypy")
|
||||
def test_bound_methods(self):
|
||||
m = Mock()
|
||||
|
||||
|
||||
+748
-63
File diff suppressed because it is too large.
Load diff
+214
-114
@@ -4,11 +4,13 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
|
||||
import unittest
|
||||
from unittest.test.testmock import support
|
||||
from unittest.test.testmock.support import SomeClass, is_instance
|
||||
|
||||
from test.test_importlib.util import uncache
|
||||
from unittest.mock import (
|
||||
NonCallableMock, CallableMixin, sentinel,
|
||||
MagicMock, Mock, NonCallableMagicMock, patch, _patch,
|
||||
@@ -42,23 +44,24 @@ something_else = sentinel.SomethingElse
|
||||
|
||||
|
||||
class Foo(object):
|
||||
def __init__(self, a):
|
||||
pass
|
||||
def f(self, a):
|
||||
pass
|
||||
def g(self):
|
||||
pass
|
||||
def __init__(self, a): pass
|
||||
def f(self, a): pass
|
||||
def g(self): pass
|
||||
foo = 'bar'
|
||||
|
||||
@staticmethod
|
||||
def static_method(): pass
|
||||
|
||||
@classmethod
|
||||
def class_method(cls): pass
|
||||
|
||||
class Bar(object):
|
||||
def a(self):
|
||||
pass
|
||||
def a(self): pass
|
||||
|
||||
foo_name = '%s.Foo' % __name__
|
||||
|
||||
|
||||
def function(a, b=Foo):
|
||||
pass
|
||||
def function(a, b=Foo): pass
|
||||
|
||||
|
||||
class Container(object):
|
||||
@@ -103,6 +106,10 @@ class PatchTest(unittest.TestCase):
|
||||
self.assertEqual(Something.attribute, sentinel.Original,
|
||||
"patch not restored")
|
||||
|
||||
def test_patchobject_with_string_as_target(self):
|
||||
msg = "'Something' must be the actual object to be patched, not a str"
|
||||
with self.assertRaisesRegex(TypeError, msg):
|
||||
patch.object('Something', 'do_something')
|
||||
|
||||
def test_patchobject_with_none(self):
|
||||
class Something(object):
|
||||
@@ -361,31 +368,19 @@ class PatchTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_patch_wont_create_by_default(self):
|
||||
try:
|
||||
with self.assertRaises(AttributeError):
|
||||
@patch('%s.frooble' % builtin_string, sentinel.Frooble)
|
||||
def test():
|
||||
self.assertEqual(frooble, sentinel.Frooble)
|
||||
def test(): pass
|
||||
|
||||
test()
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
self.fail('Patching non existent attributes should fail')
|
||||
|
||||
self.assertRaises(NameError, lambda: frooble)
|
||||
|
||||
|
||||
def test_patchobject_wont_create_by_default(self):
|
||||
try:
|
||||
with self.assertRaises(AttributeError):
|
||||
@patch.object(SomeClass, 'ord', sentinel.Frooble)
|
||||
def test():
|
||||
self.fail('Patching non existent attributes should fail')
|
||||
|
||||
def test(): pass
|
||||
test()
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
self.fail('Patching non existent attributes should fail')
|
||||
self.assertFalse(hasattr(SomeClass, 'ord'))
|
||||
|
||||
|
||||
@@ -475,6 +470,9 @@ class PatchTest(unittest.TestCase):
|
||||
attribute = sentinel.Original
|
||||
|
||||
class Foo(object):
|
||||
|
||||
test_class_attr = 'whatever'
|
||||
|
||||
def test_method(other_self, mock_something):
|
||||
self.assertEqual(PTModule.something, mock_something,
|
||||
"unpatched")
|
||||
@@ -626,6 +624,13 @@ class PatchTest(unittest.TestCase):
|
||||
self.assertEqual(foo.values, original)
|
||||
|
||||
|
||||
def test_patch_dict_as_context_manager(self):
|
||||
foo = {'a': 'b'}
|
||||
with patch.dict(foo, a='c') as patched:
|
||||
self.assertEqual(patched, {'a': 'c'})
|
||||
self.assertEqual(foo, {'a': 'b'})
|
||||
|
||||
|
||||
def test_name_preserved(self):
|
||||
foo = {}
|
||||
|
||||
@@ -633,8 +638,7 @@ class PatchTest(unittest.TestCase):
|
||||
@patch('%s.SomeClass' % __name__, object(), autospec=True)
|
||||
@patch.object(SomeClass, object())
|
||||
@patch.dict(foo)
|
||||
def some_name():
|
||||
pass
|
||||
def some_name(): pass
|
||||
|
||||
self.assertEqual(some_name.__name__, 'some_name')
|
||||
|
||||
@@ -645,12 +649,9 @@ class PatchTest(unittest.TestCase):
|
||||
@patch.dict(foo, {'a': 'b'})
|
||||
def test():
|
||||
raise NameError('Konrad')
|
||||
try:
|
||||
|
||||
with self.assertRaises(NameError):
|
||||
test()
|
||||
except NameError:
|
||||
pass
|
||||
else:
|
||||
self.fail('NameError not raised by test')
|
||||
|
||||
self.assertEqual(foo, {})
|
||||
|
||||
@@ -663,47 +664,21 @@ class PatchTest(unittest.TestCase):
|
||||
test()
|
||||
|
||||
|
||||
def test_patch_descriptor(self):
|
||||
# would be some effort to fix this - we could special case the
|
||||
# builtin descriptors: classmethod, property, staticmethod
|
||||
return
|
||||
class Nothing(object):
|
||||
foo = None
|
||||
def test_patch_dict_decorator_resolution(self):
|
||||
# bpo-35512: Ensure that patch with a string target resolves to
|
||||
# the new dictionary during function call
|
||||
original = support.target.copy()
|
||||
|
||||
class Something(object):
|
||||
foo = {}
|
||||
@patch.dict('unittest.test.testmock.support.target', {'bar': 'BAR'})
|
||||
def test():
|
||||
self.assertEqual(support.target, {'foo': 'BAZ', 'bar': 'BAR'})
|
||||
|
||||
@patch.object(Nothing, 'foo', 2)
|
||||
@classmethod
|
||||
def klass(cls):
|
||||
self.assertIs(cls, Something)
|
||||
|
||||
@patch.object(Nothing, 'foo', 2)
|
||||
@staticmethod
|
||||
def static(arg):
|
||||
return arg
|
||||
|
||||
@patch.dict(foo)
|
||||
@classmethod
|
||||
def klass_dict(cls):
|
||||
self.assertIs(cls, Something)
|
||||
|
||||
@patch.dict(foo)
|
||||
@staticmethod
|
||||
def static_dict(arg):
|
||||
return arg
|
||||
|
||||
# these will raise exceptions if patching descriptors is broken
|
||||
self.assertEqual(Something.static('f00'), 'f00')
|
||||
Something.klass()
|
||||
self.assertEqual(Something.static_dict('f00'), 'f00')
|
||||
Something.klass_dict()
|
||||
|
||||
something = Something()
|
||||
self.assertEqual(something.static('f00'), 'f00')
|
||||
something.klass()
|
||||
self.assertEqual(something.static_dict('f00'), 'f00')
|
||||
something.klass_dict()
|
||||
try:
|
||||
support.target = {'foo': 'BAZ'}
|
||||
test()
|
||||
self.assertEqual(support.target, {'foo': 'BAZ'})
|
||||
finally:
|
||||
support.target = original
|
||||
|
||||
|
||||
def test_patch_spec_set(self):
|
||||
@@ -754,10 +729,18 @@ class PatchTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_stop_without_start(self):
|
||||
# bpo-36366: calling stop without start will return None.
|
||||
patcher = patch(foo_name, 'bar', 3)
|
||||
self.assertIsNone(patcher.stop())
|
||||
|
||||
|
||||
def test_stop_idempotent(self):
|
||||
# bpo-36366: calling stop on an already stopped patch will return None.
|
||||
patcher = patch(foo_name, 'bar', 3)
|
||||
|
||||
# calling stop without start used to produce a very obscure error
|
||||
self.assertRaises(RuntimeError, patcher.stop)
|
||||
patcher.start()
|
||||
patcher.stop()
|
||||
self.assertIsNone(patcher.stop())
|
||||
|
||||
|
||||
def test_patchobject_start_stop(self):
|
||||
@@ -787,6 +770,14 @@ class PatchTest(unittest.TestCase):
|
||||
self.assertEqual(d, original)
|
||||
|
||||
|
||||
def test_patch_dict_stop_without_start(self):
|
||||
d = {'foo': 'bar'}
|
||||
original = d.copy()
|
||||
patcher = patch.dict(d, [('spam', 'eggs')], clear=True)
|
||||
self.assertFalse(patcher.stop())
|
||||
self.assertEqual(d, original)
|
||||
|
||||
|
||||
def test_patch_dict_class_decorator(self):
|
||||
this = self
|
||||
d = {'spam': 'eggs'}
|
||||
@@ -897,17 +888,13 @@ class PatchTest(unittest.TestCase):
|
||||
|
||||
def test_autospec(self):
|
||||
class Boo(object):
|
||||
def __init__(self, a):
|
||||
pass
|
||||
def f(self, a):
|
||||
pass
|
||||
def g(self):
|
||||
pass
|
||||
def __init__(self, a): pass
|
||||
def f(self, a): pass
|
||||
def g(self): pass
|
||||
foo = 'bar'
|
||||
|
||||
class Bar(object):
|
||||
def a(self):
|
||||
pass
|
||||
def a(self): pass
|
||||
|
||||
def _test(mock):
|
||||
mock(1)
|
||||
@@ -997,6 +984,18 @@ class PatchTest(unittest.TestCase):
|
||||
self.assertEqual(result, 3)
|
||||
|
||||
|
||||
def test_autospec_staticmethod(self):
|
||||
with patch('%s.Foo.static_method' % __name__, autospec=True) as method:
|
||||
Foo.static_method()
|
||||
method.assert_called_once_with()
|
||||
|
||||
|
||||
def test_autospec_classmethod(self):
|
||||
with patch('%s.Foo.class_method' % __name__, autospec=True) as method:
|
||||
Foo.class_method()
|
||||
method.assert_called_once_with()
|
||||
|
||||
|
||||
def test_autospec_with_new(self):
|
||||
patcher = patch('%s.function' % __name__, new=3, autospec=True)
|
||||
self.assertRaises(TypeError, patcher.start)
|
||||
@@ -1266,7 +1265,6 @@ class PatchTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_patch_multiple_create_mocks_different_order(self):
|
||||
# bug revealed by Jython!
|
||||
original_f = Foo.f
|
||||
original_g = Foo.g
|
||||
|
||||
@@ -1443,20 +1441,17 @@ class PatchTest(unittest.TestCase):
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'missing', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing1():
|
||||
pass
|
||||
def thing1(): pass
|
||||
|
||||
@patch.object(Foo, 'missing', 1)
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing2():
|
||||
pass
|
||||
def thing2(): pass
|
||||
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
@patch.object(Foo, 'missing', 1)
|
||||
def thing3():
|
||||
pass
|
||||
def thing3(): pass
|
||||
|
||||
for func in thing1, thing2, thing3:
|
||||
self.assertRaises(AttributeError, func)
|
||||
@@ -1475,20 +1470,17 @@ class PatchTest(unittest.TestCase):
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'foo', new_callable=crasher)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing1():
|
||||
pass
|
||||
def thing1(): pass
|
||||
|
||||
@patch.object(Foo, 'foo', new_callable=crasher)
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
def thing2():
|
||||
pass
|
||||
def thing2(): pass
|
||||
|
||||
@patch.object(Foo, 'g', 1)
|
||||
@patch.object(Foo, 'f', 1)
|
||||
@patch.object(Foo, 'foo', new_callable=crasher)
|
||||
def thing3():
|
||||
pass
|
||||
def thing3(): pass
|
||||
|
||||
for func in thing1, thing2, thing3:
|
||||
self.assertRaises(NameError, func)
|
||||
@@ -1514,8 +1506,7 @@ class PatchTest(unittest.TestCase):
|
||||
patcher.additional_patchers = additionals
|
||||
|
||||
@patcher
|
||||
def func():
|
||||
pass
|
||||
def func(): pass
|
||||
|
||||
self.assertRaises(AttributeError, func)
|
||||
self.assertEqual(Foo.f, original_f)
|
||||
@@ -1543,8 +1534,7 @@ class PatchTest(unittest.TestCase):
|
||||
patcher.additional_patchers = additionals
|
||||
|
||||
@patcher
|
||||
def func():
|
||||
pass
|
||||
def func(): pass
|
||||
|
||||
self.assertRaises(NameError, func)
|
||||
self.assertEqual(Foo.f, original_f)
|
||||
@@ -1660,22 +1650,21 @@ class PatchTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_patch_imports_lazily(self):
|
||||
sys.modules.pop('squizz', None)
|
||||
|
||||
p1 = patch('squizz.squozz')
|
||||
self.assertRaises(ImportError, p1.start)
|
||||
|
||||
squizz = Mock()
|
||||
squizz.squozz = 6
|
||||
sys.modules['squizz'] = squizz
|
||||
p1 = patch('squizz.squozz')
|
||||
squizz.squozz = 3
|
||||
p1.start()
|
||||
p1.stop()
|
||||
with uncache('squizz'):
|
||||
squizz = Mock()
|
||||
sys.modules['squizz'] = squizz
|
||||
|
||||
squizz.squozz = 6
|
||||
p1 = patch('squizz.squozz')
|
||||
squizz.squozz = 3
|
||||
p1.start()
|
||||
p1.stop()
|
||||
self.assertEqual(squizz.squozz, 3)
|
||||
|
||||
|
||||
def test_patch_propogrates_exc_on_exit(self):
|
||||
def test_patch_propagates_exc_on_exit(self):
|
||||
class holder:
|
||||
exc_info = None, None, None
|
||||
|
||||
@@ -1696,12 +1685,17 @@ class PatchTest(unittest.TestCase):
|
||||
def test(mock):
|
||||
raise RuntimeError
|
||||
|
||||
self.assertRaises(RuntimeError, test)
|
||||
with uncache('squizz'):
|
||||
squizz = Mock()
|
||||
sys.modules['squizz'] = squizz
|
||||
|
||||
self.assertRaises(RuntimeError, test)
|
||||
|
||||
self.assertIs(holder.exc_info[0], RuntimeError)
|
||||
self.assertIsNotNone(holder.exc_info[1],
|
||||
'exception value not propgated')
|
||||
'exception value not propagated')
|
||||
self.assertIsNotNone(holder.exc_info[2],
|
||||
'exception traceback not propgated')
|
||||
'exception traceback not propagated')
|
||||
|
||||
|
||||
def test_create_and_specs(self):
|
||||
@@ -1822,6 +1816,56 @@ class PatchTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(stopped, ["three", "two", "one"])
|
||||
|
||||
def test_patch_dict_stopall(self):
|
||||
dic1 = {}
|
||||
dic2 = {1: 'a'}
|
||||
dic3 = {1: 'A', 2: 'B'}
|
||||
origdic1 = dic1.copy()
|
||||
origdic2 = dic2.copy()
|
||||
origdic3 = dic3.copy()
|
||||
patch.dict(dic1, {1: 'I', 2: 'II'}).start()
|
||||
patch.dict(dic2, {2: 'b'}).start()
|
||||
|
||||
@patch.dict(dic3)
|
||||
def patched():
|
||||
del dic3[1]
|
||||
|
||||
patched()
|
||||
self.assertNotEqual(dic1, origdic1)
|
||||
self.assertNotEqual(dic2, origdic2)
|
||||
self.assertEqual(dic3, origdic3)
|
||||
|
||||
patch.stopall()
|
||||
|
||||
self.assertEqual(dic1, origdic1)
|
||||
self.assertEqual(dic2, origdic2)
|
||||
self.assertEqual(dic3, origdic3)
|
||||
|
||||
|
||||
def test_patch_and_patch_dict_stopall(self):
|
||||
original_unlink = os.unlink
|
||||
original_chdir = os.chdir
|
||||
dic1 = {}
|
||||
dic2 = {1: 'A', 2: 'B'}
|
||||
origdic1 = dic1.copy()
|
||||
origdic2 = dic2.copy()
|
||||
|
||||
patch('os.unlink', something).start()
|
||||
patch('os.chdir', something_else).start()
|
||||
patch.dict(dic1, {1: 'I', 2: 'II'}).start()
|
||||
patch.dict(dic2).start()
|
||||
del dic2[1]
|
||||
|
||||
self.assertIsNot(os.unlink, original_unlink)
|
||||
self.assertIsNot(os.chdir, original_chdir)
|
||||
self.assertNotEqual(dic1, origdic1)
|
||||
self.assertNotEqual(dic2, origdic2)
|
||||
patch.stopall()
|
||||
self.assertIs(os.unlink, original_unlink)
|
||||
self.assertIs(os.chdir, original_chdir)
|
||||
self.assertEqual(dic1, origdic1)
|
||||
self.assertEqual(dic2, origdic2)
|
||||
|
||||
|
||||
def test_special_attrs(self):
|
||||
def foo(x=0):
|
||||
@@ -1831,9 +1875,10 @@ class PatchTest(unittest.TestCase):
|
||||
self.assertEqual(foo(), 1)
|
||||
self.assertEqual(foo(), 0)
|
||||
|
||||
orig_doc = foo.__doc__
|
||||
with patch.object(foo, '__doc__', "FUN"):
|
||||
self.assertEqual(foo.__doc__, "FUN")
|
||||
self.assertEqual(foo.__doc__, "TEST")
|
||||
self.assertEqual(foo.__doc__, orig_doc)
|
||||
|
||||
with patch.object(foo, '__module__', "testpatch2"):
|
||||
self.assertEqual(foo.__module__, "testpatch2")
|
||||
@@ -1849,5 +1894,60 @@ class PatchTest(unittest.TestCase):
|
||||
self.assertEqual(foo(), 1)
|
||||
self.assertEqual(foo(), 0)
|
||||
|
||||
def test_patch_orderdict(self):
|
||||
foo = OrderedDict()
|
||||
foo['a'] = object()
|
||||
foo['b'] = 'python'
|
||||
|
||||
original = foo.copy()
|
||||
update_values = list(zip('cdefghijklmnopqrstuvwxyz', range(26)))
|
||||
patched_values = list(foo.items()) + update_values
|
||||
|
||||
with patch.dict(foo, OrderedDict(update_values)):
|
||||
self.assertEqual(list(foo.items()), patched_values)
|
||||
|
||||
self.assertEqual(foo, original)
|
||||
|
||||
with patch.dict(foo, update_values):
|
||||
self.assertEqual(list(foo.items()), patched_values)
|
||||
|
||||
self.assertEqual(foo, original)
|
||||
|
||||
def test_dotted_but_module_not_loaded(self):
|
||||
# This exercises the AttributeError branch of _dot_lookup.
|
||||
|
||||
# make sure it's there
|
||||
import unittest.test.testmock.support
|
||||
# now make sure it's not:
|
||||
with patch.dict('sys.modules'):
|
||||
del sys.modules['unittest.test.testmock.support']
|
||||
del sys.modules['unittest.test.testmock']
|
||||
del sys.modules['unittest.test']
|
||||
del sys.modules['unittest']
|
||||
|
||||
# now make sure we can patch based on a dotted path:
|
||||
@patch('unittest.test.testmock.support.X')
|
||||
def test(mock):
|
||||
pass
|
||||
test()
|
||||
|
||||
|
||||
def test_invalid_target(self):
|
||||
class Foo:
|
||||
pass
|
||||
|
||||
for target in ['', 12, Foo()]:
|
||||
with self.subTest(target=target):
|
||||
with self.assertRaises(TypeError):
|
||||
patch(target)
|
||||
|
||||
|
||||
def test_cant_set_kwargs_when_passing_a_mock(self):
|
||||
@patch('unittest.test.testmock.support.X', new=object(), x=1)
|
||||
def test(): pass
|
||||
with self.assertRaises(TypeError):
|
||||
test()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
+64
-8
@@ -3,15 +3,10 @@ from unittest import mock
|
||||
|
||||
|
||||
class SampleObject:
|
||||
def __init__(self):
|
||||
self.attr_sample1 = 1
|
||||
self.attr_sample2 = 1
|
||||
|
||||
def method_sample1(self):
|
||||
pass
|
||||
def method_sample1(self): pass
|
||||
|
||||
def method_sample2(self):
|
||||
pass
|
||||
def method_sample2(self): pass
|
||||
|
||||
|
||||
class TestSealable(unittest.TestCase):
|
||||
@@ -133,7 +128,7 @@ class TestSealable(unittest.TestCase):
|
||||
m.attr_sample2
|
||||
|
||||
def test_integration_with_spec_method_definition(self):
|
||||
"""You need to defin the methods, even if they are in the spec"""
|
||||
"""You need to define the methods, even if they are in the spec"""
|
||||
m = mock.Mock(SampleObject)
|
||||
|
||||
m.method_sample1.return_value = 1
|
||||
@@ -176,6 +171,67 @@ class TestSealable(unittest.TestCase):
|
||||
m.test1().test2.test3().test4()
|
||||
self.assertIn("mock.test1().test2.test3().test4", str(cm.exception))
|
||||
|
||||
def test_seal_with_autospec(self):
|
||||
# https://bugs.python.org/issue45156
|
||||
class Foo:
|
||||
foo = 0
|
||||
def bar1(self):
|
||||
return 1
|
||||
def bar2(self):
|
||||
return 2
|
||||
|
||||
class Baz:
|
||||
baz = 3
|
||||
def ban(self):
|
||||
return 4
|
||||
|
||||
for spec_set in (True, False):
|
||||
with self.subTest(spec_set=spec_set):
|
||||
foo = mock.create_autospec(Foo, spec_set=spec_set)
|
||||
foo.bar1.return_value = 'a'
|
||||
foo.Baz.ban.return_value = 'b'
|
||||
|
||||
mock.seal(foo)
|
||||
|
||||
self.assertIsInstance(foo.foo, mock.NonCallableMagicMock)
|
||||
self.assertIsInstance(foo.bar1, mock.MagicMock)
|
||||
self.assertIsInstance(foo.bar2, mock.MagicMock)
|
||||
self.assertIsInstance(foo.Baz, mock.MagicMock)
|
||||
self.assertIsInstance(foo.Baz.baz, mock.NonCallableMagicMock)
|
||||
self.assertIsInstance(foo.Baz.ban, mock.MagicMock)
|
||||
|
||||
self.assertEqual(foo.bar1(), 'a')
|
||||
foo.bar1.return_value = 'new_a'
|
||||
self.assertEqual(foo.bar1(), 'new_a')
|
||||
self.assertEqual(foo.Baz.ban(), 'b')
|
||||
foo.Baz.ban.return_value = 'new_b'
|
||||
self.assertEqual(foo.Baz.ban(), 'new_b')
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
foo.foo()
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.bar = 1
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.bar2()
|
||||
|
||||
foo.bar2.return_value = 'bar2'
|
||||
self.assertEqual(foo.bar2(), 'bar2')
|
||||
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.missing_attr
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.missing_attr = 1
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.missing_method()
|
||||
with self.assertRaises(TypeError):
|
||||
foo.Baz.baz()
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.Baz.missing_attr
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.Baz.missing_attr = 1
|
||||
with self.assertRaises(AttributeError):
|
||||
foo.Baz.missing_method()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+53
-7
@@ -10,6 +10,8 @@ something = sentinel.Something
|
||||
something_else = sentinel.SomethingElse
|
||||
|
||||
|
||||
class SampleException(Exception): pass
|
||||
|
||||
|
||||
class WithTest(unittest.TestCase):
|
||||
|
||||
@@ -20,14 +22,10 @@ class WithTest(unittest.TestCase):
|
||||
|
||||
|
||||
def test_with_statement_exception(self):
|
||||
try:
|
||||
with self.assertRaises(SampleException):
|
||||
with patch('%s.something' % __name__, sentinel.Something2):
|
||||
self.assertEqual(something, sentinel.Something2, "unpatched")
|
||||
raise Exception('pow')
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
self.fail("patch swallowed exception")
|
||||
raise SampleException()
|
||||
self.assertEqual(something, sentinel.Something)
|
||||
|
||||
|
||||
@@ -126,6 +124,19 @@ class WithTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(foo, {})
|
||||
|
||||
def test_double_patch_instance_method(self):
|
||||
class C:
|
||||
def f(self): pass
|
||||
|
||||
c = C()
|
||||
|
||||
with patch.object(c, 'f', autospec=True) as patch1:
|
||||
with patch.object(c, 'f', autospec=True) as patch2:
|
||||
c.f()
|
||||
self.assertEqual(patch2.call_count, 1)
|
||||
self.assertEqual(patch1.call_count, 0)
|
||||
c.f()
|
||||
self.assertEqual(patch1.call_count, 1)
|
||||
|
||||
|
||||
class TestMockOpen(unittest.TestCase):
|
||||
@@ -188,6 +199,7 @@ class TestMockOpen(unittest.TestCase):
|
||||
|
||||
def test_readline_data(self):
|
||||
# Check that readline will return all the lines from the fake file
|
||||
# And that once fully consumed, readline will return an empty string.
|
||||
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
||||
with patch('%s.open' % __name__, mock, create=True):
|
||||
h = open('bar')
|
||||
@@ -197,6 +209,7 @@ class TestMockOpen(unittest.TestCase):
|
||||
self.assertEqual(line1, 'foo\n')
|
||||
self.assertEqual(line2, 'bar\n')
|
||||
self.assertEqual(line3, 'baz\n')
|
||||
self.assertEqual(h.readline(), '')
|
||||
|
||||
# Check that we properly emulate a file that doesn't end in a newline
|
||||
mock = mock_open(read_data='foo')
|
||||
@@ -204,8 +217,36 @@ class TestMockOpen(unittest.TestCase):
|
||||
h = open('bar')
|
||||
result = h.readline()
|
||||
self.assertEqual(result, 'foo')
|
||||
self.assertEqual(h.readline(), '')
|
||||
|
||||
|
||||
def test_dunder_iter_data(self):
|
||||
# Check that dunder_iter will return all the lines from the fake file.
|
||||
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
||||
with patch('%s.open' % __name__, mock, create=True):
|
||||
h = open('bar')
|
||||
lines = [l for l in h]
|
||||
self.assertEqual(lines[0], 'foo\n')
|
||||
self.assertEqual(lines[1], 'bar\n')
|
||||
self.assertEqual(lines[2], 'baz\n')
|
||||
self.assertEqual(h.readline(), '')
|
||||
with self.assertRaises(StopIteration):
|
||||
next(h)
|
||||
|
||||
def test_next_data(self):
|
||||
# Check that next will correctly return the next available
|
||||
# line and plays well with the dunder_iter part.
|
||||
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
||||
with patch('%s.open' % __name__, mock, create=True):
|
||||
h = open('bar')
|
||||
line1 = next(h)
|
||||
line2 = next(h)
|
||||
lines = [l for l in h]
|
||||
self.assertEqual(line1, 'foo\n')
|
||||
self.assertEqual(line2, 'bar\n')
|
||||
self.assertEqual(lines[0], 'baz\n')
|
||||
self.assertEqual(h.readline(), '')
|
||||
|
||||
def test_readlines_data(self):
|
||||
# Test that emulating a file that ends in a newline character works
|
||||
mock = mock_open(read_data='foo\nbar\nbaz\n')
|
||||
@@ -257,7 +298,12 @@ class TestMockOpen(unittest.TestCase):
|
||||
# for mocks returned by mock_open
|
||||
some_data = 'foo\nbar\nbaz'
|
||||
mock = mock_open(read_data=some_data)
|
||||
self.assertEqual(mock().read(10), some_data)
|
||||
self.assertEqual(mock().read(10), some_data[:10])
|
||||
self.assertEqual(mock().read(10), some_data[:10])
|
||||
|
||||
f = mock()
|
||||
self.assertEqual(f.read(10), some_data[:10])
|
||||
self.assertEqual(f.read(10), some_data[10:])
|
||||
|
||||
|
||||
def test_interleaved_reads(self):
|
||||
|
||||
Reference in new issue
Block a user