Remove libraries now being pip dependency
parent
eb57a04453
commit
21e55e5e2c
|
|
@ -1,68 +0,0 @@
|
||||||
"""
|
|
||||||
unittest2
|
|
||||||
|
|
||||||
unittest2 is a backport of the new features added to the unittest testing
|
|
||||||
framework in Python 2.7. It is tested to run on Python 2.4 - 2.6.
|
|
||||||
|
|
||||||
To use unittest2 instead of unittest simply replace ``import unittest`` with
|
|
||||||
``import unittest2``.
|
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 1999-2003 Steve Purcell
|
|
||||||
Copyright (c) 2003-2010 Python Software Foundation
|
|
||||||
This module is free software, and you may redistribute it and/or modify
|
|
||||||
it under the same terms as Python itself, so long as this copyright message
|
|
||||||
and disclaimer are retained in their original form.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
|
||||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
|
|
||||||
THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
DAMAGE.
|
|
||||||
|
|
||||||
THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
|
|
||||||
AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
|
|
||||||
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__all__ = ['TestResult', 'TestCase', 'TestSuite',
|
|
||||||
'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
|
|
||||||
'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
|
|
||||||
'expectedFailure', 'TextTestResult', '__version__', 'collector']
|
|
||||||
|
|
||||||
__version__ = '0.5.1'
|
|
||||||
|
|
||||||
# Expose obsolete functions for backwards compatibility
|
|
||||||
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
|
||||||
|
|
||||||
|
|
||||||
from unittest2.collector import collector
|
|
||||||
from unittest2.result import TestResult
|
|
||||||
from unittest2.case import (
|
|
||||||
TestCase, FunctionTestCase, SkipTest, skip, skipIf,
|
|
||||||
skipUnless, expectedFailure
|
|
||||||
)
|
|
||||||
from unittest2.suite import BaseTestSuite, TestSuite
|
|
||||||
from unittest2.loader import (
|
|
||||||
TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
|
|
||||||
findTestCases
|
|
||||||
)
|
|
||||||
from unittest2.main import TestProgram, main, main_
|
|
||||||
from unittest2.runner import TextTestRunner, TextTestResult
|
|
||||||
|
|
||||||
try:
|
|
||||||
from unittest2.signals import (
|
|
||||||
installHandler, registerResult, removeResult, removeHandler
|
|
||||||
)
|
|
||||||
except ImportError:
|
|
||||||
# Compatibility with platforms that don't have the signal module
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
__all__.extend(['installHandler', 'registerResult', 'removeResult',
|
|
||||||
'removeHandler'])
|
|
||||||
|
|
||||||
# deprecated
|
|
||||||
_TextTestResult = TextTestResult
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
"""Main entry point"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
if sys.argv[0].endswith("__main__.py"):
|
|
||||||
sys.argv[0] = "unittest2"
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
from unittest2.main import main_
|
|
||||||
main_()
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,9 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from unittest2.loader import defaultTestLoader
|
|
||||||
|
|
||||||
def collector():
|
|
||||||
# import __main__ triggers code re-execution
|
|
||||||
__main__ = sys.modules['__main__']
|
|
||||||
setupDir = os.path.abspath(os.path.dirname(__main__.__file__))
|
|
||||||
return defaultTestLoader.discover(setupDir)
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
try:
|
|
||||||
from functools import wraps
|
|
||||||
except ImportError:
|
|
||||||
# only needed for Python 2.4
|
|
||||||
def wraps(_):
|
|
||||||
def _wraps(func):
|
|
||||||
return func
|
|
||||||
return _wraps
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
def _relpath_nt(path, start=os.path.curdir):
|
|
||||||
"""Return a relative version of a path"""
|
|
||||||
|
|
||||||
if not path:
|
|
||||||
raise ValueError("no path specified")
|
|
||||||
start_list = os.path.abspath(start).split(os.path.sep)
|
|
||||||
path_list = os.path.abspath(path).split(os.path.sep)
|
|
||||||
if start_list[0].lower() != path_list[0].lower():
|
|
||||||
unc_path, rest = os.path.splitunc(path)
|
|
||||||
unc_start, rest = os.path.splitunc(start)
|
|
||||||
if bool(unc_path) ^ bool(unc_start):
|
|
||||||
raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
|
|
||||||
% (path, start))
|
|
||||||
else:
|
|
||||||
raise ValueError("path is on drive %s, start on drive %s"
|
|
||||||
% (path_list[0], start_list[0]))
|
|
||||||
# Work out how much of the filepath is shared by start and path.
|
|
||||||
for i in range(min(len(start_list), len(path_list))):
|
|
||||||
if start_list[i].lower() != path_list[i].lower():
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
|
|
||||||
if not rel_list:
|
|
||||||
return os.path.curdir
|
|
||||||
return os.path.join(*rel_list)
|
|
||||||
|
|
||||||
# default to posixpath definition
|
|
||||||
def _relpath_posix(path, start=os.path.curdir):
|
|
||||||
"""Return a relative version of a path"""
|
|
||||||
|
|
||||||
if not path:
|
|
||||||
raise ValueError("no path specified")
|
|
||||||
|
|
||||||
start_list = os.path.abspath(start).split(os.path.sep)
|
|
||||||
path_list = os.path.abspath(path).split(os.path.sep)
|
|
||||||
|
|
||||||
# Work out how much of the filepath is shared by start and path.
|
|
||||||
i = len(os.path.commonprefix([start_list, path_list]))
|
|
||||||
|
|
||||||
rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
|
|
||||||
if not rel_list:
|
|
||||||
return os.path.curdir
|
|
||||||
return os.path.join(*rel_list)
|
|
||||||
|
|
||||||
if os.path is sys.modules.get('ntpath'):
|
|
||||||
relpath = _relpath_nt
|
|
||||||
else:
|
|
||||||
relpath = _relpath_posix
|
|
||||||
|
|
@ -1,322 +0,0 @@
|
||||||
"""Loading unittests."""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
import types
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from fnmatch import fnmatch
|
|
||||||
|
|
||||||
from unittest2 import case, suite
|
|
||||||
|
|
||||||
try:
|
|
||||||
from os.path import relpath
|
|
||||||
except ImportError:
|
|
||||||
from unittest2.compatibility import relpath
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
|
|
||||||
def _CmpToKey(mycmp):
|
|
||||||
'Convert a cmp= function into a key= function'
|
|
||||||
class K(object):
|
|
||||||
def __init__(self, obj):
|
|
||||||
self.obj = obj
|
|
||||||
def __lt__(self, other):
|
|
||||||
return mycmp(self.obj, other.obj) == -1
|
|
||||||
return K
|
|
||||||
|
|
||||||
|
|
||||||
# what about .pyc or .pyo (etc)
|
|
||||||
# we would need to avoid loading the same tests multiple times
|
|
||||||
# from '.py', '.pyc' *and* '.pyo'
|
|
||||||
VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE)
|
|
||||||
|
|
||||||
|
|
||||||
def _make_failed_import_test(name, suiteClass):
|
|
||||||
message = 'Failed to import test module: %s' % name
|
|
||||||
if hasattr(traceback, 'format_exc'):
|
|
||||||
# Python 2.3 compatibility
|
|
||||||
# format_exc returns two frames of discover.py as well
|
|
||||||
message += '\n%s' % traceback.format_exc()
|
|
||||||
return _make_failed_test('ModuleImportFailure', name, ImportError(message),
|
|
||||||
suiteClass)
|
|
||||||
|
|
||||||
def _make_failed_load_tests(name, exception, suiteClass):
|
|
||||||
return _make_failed_test('LoadTestsFailure', name, exception, suiteClass)
|
|
||||||
|
|
||||||
def _make_failed_test(classname, methodname, exception, suiteClass):
|
|
||||||
def testFailure(self):
|
|
||||||
raise exception
|
|
||||||
attrs = {methodname: testFailure}
|
|
||||||
TestClass = type(classname, (case.TestCase,), attrs)
|
|
||||||
return suiteClass((TestClass(methodname),))
|
|
||||||
|
|
||||||
|
|
||||||
class TestLoader(unittest.TestLoader):
|
|
||||||
"""
|
|
||||||
This class is responsible for loading tests according to various criteria
|
|
||||||
and returning them wrapped in a TestSuite
|
|
||||||
"""
|
|
||||||
testMethodPrefix = 'test'
|
|
||||||
sortTestMethodsUsing = cmp
|
|
||||||
suiteClass = suite.TestSuite
|
|
||||||
_top_level_dir = None
|
|
||||||
|
|
||||||
def loadTestsFromTestCase(self, testCaseClass):
|
|
||||||
"""Return a suite of all tests cases contained in testCaseClass"""
|
|
||||||
if issubclass(testCaseClass, suite.TestSuite):
|
|
||||||
raise TypeError("Test cases should not be derived from TestSuite."
|
|
||||||
" Maybe you meant to derive from TestCase?")
|
|
||||||
testCaseNames = self.getTestCaseNames(testCaseClass)
|
|
||||||
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
|
|
||||||
testCaseNames = ['runTest']
|
|
||||||
loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
|
|
||||||
return loaded_suite
|
|
||||||
|
|
||||||
def loadTestsFromModule(self, module, use_load_tests=True):
|
|
||||||
"""Return a suite of all tests cases contained in the given module"""
|
|
||||||
tests = []
|
|
||||||
for name in dir(module):
|
|
||||||
obj = getattr(module, name)
|
|
||||||
if isinstance(obj, type) and issubclass(obj, unittest.TestCase):
|
|
||||||
tests.append(self.loadTestsFromTestCase(obj))
|
|
||||||
|
|
||||||
load_tests = getattr(module, 'load_tests', None)
|
|
||||||
tests = self.suiteClass(tests)
|
|
||||||
if use_load_tests and load_tests is not None:
|
|
||||||
try:
|
|
||||||
return load_tests(self, tests, None)
|
|
||||||
except Exception, e:
|
|
||||||
return _make_failed_load_tests(module.__name__, e,
|
|
||||||
self.suiteClass)
|
|
||||||
return tests
|
|
||||||
|
|
||||||
def loadTestsFromName(self, name, module=None):
|
|
||||||
"""Return a suite of all tests cases given a string specifier.
|
|
||||||
|
|
||||||
The name may resolve either to a module, a test case class, a
|
|
||||||
test method within a test case class, or a callable object which
|
|
||||||
returns a TestCase or TestSuite instance.
|
|
||||||
|
|
||||||
The method optionally resolves the names relative to a given module.
|
|
||||||
"""
|
|
||||||
parts = name.split('.')
|
|
||||||
if module is None:
|
|
||||||
parts_copy = parts[:]
|
|
||||||
while parts_copy:
|
|
||||||
try:
|
|
||||||
module = __import__('.'.join(parts_copy))
|
|
||||||
break
|
|
||||||
except ImportError:
|
|
||||||
del parts_copy[-1]
|
|
||||||
if not parts_copy:
|
|
||||||
raise
|
|
||||||
parts = parts[1:]
|
|
||||||
obj = module
|
|
||||||
for part in parts:
|
|
||||||
parent, obj = obj, getattr(obj, part)
|
|
||||||
|
|
||||||
if isinstance(obj, types.ModuleType):
|
|
||||||
return self.loadTestsFromModule(obj)
|
|
||||||
elif isinstance(obj, type) and issubclass(obj, unittest.TestCase):
|
|
||||||
return self.loadTestsFromTestCase(obj)
|
|
||||||
elif (isinstance(obj, types.UnboundMethodType) and
|
|
||||||
isinstance(parent, type) and
|
|
||||||
issubclass(parent, case.TestCase)):
|
|
||||||
return self.suiteClass([parent(obj.__name__)])
|
|
||||||
elif isinstance(obj, unittest.TestSuite):
|
|
||||||
return obj
|
|
||||||
elif hasattr(obj, '__call__'):
|
|
||||||
test = obj()
|
|
||||||
if isinstance(test, unittest.TestSuite):
|
|
||||||
return test
|
|
||||||
elif isinstance(test, unittest.TestCase):
|
|
||||||
return self.suiteClass([test])
|
|
||||||
else:
|
|
||||||
raise TypeError("calling %s returned %s, not a test" %
|
|
||||||
(obj, test))
|
|
||||||
else:
|
|
||||||
raise TypeError("don't know how to make test from: %s" % obj)
|
|
||||||
|
|
||||||
def loadTestsFromNames(self, names, module=None):
|
|
||||||
"""Return a suite of all tests cases found using the given sequence
|
|
||||||
of string specifiers. See 'loadTestsFromName()'.
|
|
||||||
"""
|
|
||||||
suites = [self.loadTestsFromName(name, module) for name in names]
|
|
||||||
return self.suiteClass(suites)
|
|
||||||
|
|
||||||
def getTestCaseNames(self, testCaseClass):
|
|
||||||
"""Return a sorted sequence of method names found within testCaseClass
|
|
||||||
"""
|
|
||||||
def isTestMethod(attrname, testCaseClass=testCaseClass,
|
|
||||||
prefix=self.testMethodPrefix):
|
|
||||||
return attrname.startswith(prefix) and \
|
|
||||||
hasattr(getattr(testCaseClass, attrname), '__call__')
|
|
||||||
testFnNames = filter(isTestMethod, dir(testCaseClass))
|
|
||||||
if self.sortTestMethodsUsing:
|
|
||||||
testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing))
|
|
||||||
return testFnNames
|
|
||||||
|
|
||||||
def discover(self, start_dir, pattern='test*.py', top_level_dir=None):
|
|
||||||
"""Find and return all test modules from the specified start
|
|
||||||
directory, recursing into subdirectories to find them. Only test files
|
|
||||||
that match the pattern will be loaded. (Using shell style pattern
|
|
||||||
matching.)
|
|
||||||
|
|
||||||
All test modules must be importable from the top level of the project.
|
|
||||||
If the start directory is not the top level directory then the top
|
|
||||||
level directory must be specified separately.
|
|
||||||
|
|
||||||
If a test package name (directory with '__init__.py') matches the
|
|
||||||
pattern then the package will be checked for a 'load_tests' function. If
|
|
||||||
this exists then it will be called with loader, tests, pattern.
|
|
||||||
|
|
||||||
If load_tests exists then discovery does *not* recurse into the package,
|
|
||||||
load_tests is responsible for loading all tests in the package.
|
|
||||||
|
|
||||||
The pattern is deliberately not stored as a loader attribute so that
|
|
||||||
packages can continue discovery themselves. top_level_dir is stored so
|
|
||||||
load_tests does not need to pass this argument in to loader.discover().
|
|
||||||
"""
|
|
||||||
set_implicit_top = False
|
|
||||||
if top_level_dir is None and self._top_level_dir is not None:
|
|
||||||
# make top_level_dir optional if called from load_tests in a package
|
|
||||||
top_level_dir = self._top_level_dir
|
|
||||||
elif top_level_dir is None:
|
|
||||||
set_implicit_top = True
|
|
||||||
top_level_dir = start_dir
|
|
||||||
|
|
||||||
top_level_dir = os.path.abspath(top_level_dir)
|
|
||||||
|
|
||||||
if not top_level_dir in sys.path:
|
|
||||||
# all test modules must be importable from the top level directory
|
|
||||||
# should we *unconditionally* put the start directory in first
|
|
||||||
# in sys.path to minimise likelihood of conflicts between installed
|
|
||||||
# modules and development versions?
|
|
||||||
sys.path.insert(0, top_level_dir)
|
|
||||||
self._top_level_dir = top_level_dir
|
|
||||||
|
|
||||||
is_not_importable = False
|
|
||||||
if os.path.isdir(os.path.abspath(start_dir)):
|
|
||||||
start_dir = os.path.abspath(start_dir)
|
|
||||||
if start_dir != top_level_dir:
|
|
||||||
is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))
|
|
||||||
else:
|
|
||||||
# support for discovery from dotted module names
|
|
||||||
try:
|
|
||||||
__import__(start_dir)
|
|
||||||
except ImportError:
|
|
||||||
is_not_importable = True
|
|
||||||
else:
|
|
||||||
the_module = sys.modules[start_dir]
|
|
||||||
top_part = start_dir.split('.')[0]
|
|
||||||
start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
|
|
||||||
if set_implicit_top:
|
|
||||||
self._top_level_dir = os.path.abspath(os.path.dirname(os.path.dirname(sys.modules[top_part].__file__)))
|
|
||||||
sys.path.remove(top_level_dir)
|
|
||||||
|
|
||||||
if is_not_importable:
|
|
||||||
raise ImportError('Start directory is not importable: %r' % start_dir)
|
|
||||||
|
|
||||||
tests = list(self._find_tests(start_dir, pattern))
|
|
||||||
return self.suiteClass(tests)
|
|
||||||
|
|
||||||
def _get_name_from_path(self, path):
|
|
||||||
path = os.path.splitext(os.path.normpath(path))[0]
|
|
||||||
|
|
||||||
_relpath = relpath(path, self._top_level_dir)
|
|
||||||
assert not os.path.isabs(_relpath), "Path must be within the project"
|
|
||||||
assert not _relpath.startswith('..'), "Path must be within the project"
|
|
||||||
|
|
||||||
name = _relpath.replace(os.path.sep, '.')
|
|
||||||
return name
|
|
||||||
|
|
||||||
def _get_module_from_name(self, name):
|
|
||||||
__import__(name)
|
|
||||||
return sys.modules[name]
|
|
||||||
|
|
||||||
def _match_path(self, path, full_path, pattern):
|
|
||||||
# override this method to use alternative matching strategy
|
|
||||||
return fnmatch(path, pattern)
|
|
||||||
|
|
||||||
def _find_tests(self, start_dir, pattern):
|
|
||||||
"""Used by discovery. Yields test suites it loads."""
|
|
||||||
paths = os.listdir(start_dir)
|
|
||||||
|
|
||||||
for path in paths:
|
|
||||||
full_path = os.path.join(start_dir, path)
|
|
||||||
if os.path.isfile(full_path):
|
|
||||||
if not VALID_MODULE_NAME.match(path):
|
|
||||||
# valid Python identifiers only
|
|
||||||
continue
|
|
||||||
if not self._match_path(path, full_path, pattern):
|
|
||||||
continue
|
|
||||||
# if the test file matches, load it
|
|
||||||
name = self._get_name_from_path(full_path)
|
|
||||||
try:
|
|
||||||
module = self._get_module_from_name(name)
|
|
||||||
except:
|
|
||||||
yield _make_failed_import_test(name, self.suiteClass)
|
|
||||||
else:
|
|
||||||
mod_file = os.path.abspath(getattr(module, '__file__', full_path))
|
|
||||||
realpath = os.path.splitext(mod_file)[0]
|
|
||||||
fullpath_noext = os.path.splitext(full_path)[0]
|
|
||||||
if realpath.lower() != fullpath_noext.lower():
|
|
||||||
module_dir = os.path.dirname(realpath)
|
|
||||||
mod_name = os.path.splitext(os.path.basename(full_path))[0]
|
|
||||||
expected_dir = os.path.dirname(full_path)
|
|
||||||
msg = ("%r module incorrectly imported from %r. Expected %r. "
|
|
||||||
"Is this module globally installed?")
|
|
||||||
raise ImportError(msg % (mod_name, module_dir, expected_dir))
|
|
||||||
yield self.loadTestsFromModule(module)
|
|
||||||
elif os.path.isdir(full_path):
|
|
||||||
if not os.path.isfile(os.path.join(full_path, '__init__.py')):
|
|
||||||
continue
|
|
||||||
|
|
||||||
load_tests = None
|
|
||||||
tests = None
|
|
||||||
if fnmatch(path, pattern):
|
|
||||||
# only check load_tests if the package directory itself matches the filter
|
|
||||||
name = self._get_name_from_path(full_path)
|
|
||||||
package = self._get_module_from_name(name)
|
|
||||||
load_tests = getattr(package, 'load_tests', None)
|
|
||||||
tests = self.loadTestsFromModule(package, use_load_tests=False)
|
|
||||||
|
|
||||||
if load_tests is None:
|
|
||||||
if tests is not None:
|
|
||||||
# tests loaded from package file
|
|
||||||
yield tests
|
|
||||||
# recurse into the package
|
|
||||||
for test in self._find_tests(full_path, pattern):
|
|
||||||
yield test
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
yield load_tests(self, tests, pattern)
|
|
||||||
except Exception, e:
|
|
||||||
yield _make_failed_load_tests(package.__name__, e,
|
|
||||||
self.suiteClass)
|
|
||||||
|
|
||||||
defaultTestLoader = TestLoader()
|
|
||||||
|
|
||||||
|
|
||||||
def _makeLoader(prefix, sortUsing, suiteClass=None):
|
|
||||||
loader = TestLoader()
|
|
||||||
loader.sortTestMethodsUsing = sortUsing
|
|
||||||
loader.testMethodPrefix = prefix
|
|
||||||
if suiteClass:
|
|
||||||
loader.suiteClass = suiteClass
|
|
||||||
return loader
|
|
||||||
|
|
||||||
def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
|
|
||||||
return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
|
|
||||||
|
|
||||||
def makeSuite(testCaseClass, prefix='test', sortUsing=cmp,
|
|
||||||
suiteClass=suite.TestSuite):
|
|
||||||
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
|
|
||||||
|
|
||||||
def findTestCases(module, prefix='test', sortUsing=cmp,
|
|
||||||
suiteClass=suite.TestSuite):
|
|
||||||
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
|
|
||||||
|
|
@ -1,241 +0,0 @@
|
||||||
"""Unittest main program"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import types
|
|
||||||
|
|
||||||
from unittest2 import loader, runner
|
|
||||||
try:
|
|
||||||
from unittest2.signals import installHandler
|
|
||||||
except ImportError:
|
|
||||||
installHandler = None
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
FAILFAST = " -f, --failfast Stop on first failure\n"
|
|
||||||
CATCHBREAK = " -c, --catch Catch control-C and display results\n"
|
|
||||||
BUFFEROUTPUT = " -b, --buffer Buffer stdout and stderr during test runs\n"
|
|
||||||
|
|
||||||
USAGE_AS_MAIN = """\
|
|
||||||
Usage: %(progName)s [options] [tests]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h, --help Show this message
|
|
||||||
-v, --verbose Verbose output
|
|
||||||
-q, --quiet Minimal output
|
|
||||||
%(failfast)s%(catchbreak)s%(buffer)s
|
|
||||||
Examples:
|
|
||||||
%(progName)s test_module - run tests from test_module
|
|
||||||
%(progName)s test_module.TestClass - run tests from
|
|
||||||
test_module.TestClass
|
|
||||||
%(progName)s test_module.TestClass.test_method - run specified test method
|
|
||||||
|
|
||||||
[tests] can be a list of any number of test modules, classes and test
|
|
||||||
methods.
|
|
||||||
|
|
||||||
Alternative Usage: %(progName)s discover [options]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-v, --verbose Verbose output
|
|
||||||
%(failfast)s%(catchbreak)s%(buffer)s -s directory Directory to start discovery ('.' default)
|
|
||||||
-p pattern Pattern to match test files ('test*.py' default)
|
|
||||||
-t directory Top level directory of project (default to
|
|
||||||
start directory)
|
|
||||||
|
|
||||||
For test discovery all test modules must be importable from the top
|
|
||||||
level directory of the project.
|
|
||||||
"""
|
|
||||||
|
|
||||||
USAGE_FROM_MODULE = """\
|
|
||||||
Usage: %(progName)s [options] [test] [...]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h, --help Show this message
|
|
||||||
-v, --verbose Verbose output
|
|
||||||
-q, --quiet Minimal output
|
|
||||||
%(failfast)s%(catchbreak)s%(buffer)s
|
|
||||||
Examples:
|
|
||||||
%(progName)s - run default set of tests
|
|
||||||
%(progName)s MyTestSuite - run suite 'MyTestSuite'
|
|
||||||
%(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
|
|
||||||
%(progName)s MyTestCase - run all 'test*' test methods
|
|
||||||
in MyTestCase
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class TestProgram(object):
|
|
||||||
"""A command-line program that runs a set of tests; this is primarily
|
|
||||||
for making test modules conveniently executable.
|
|
||||||
"""
|
|
||||||
USAGE = USAGE_FROM_MODULE
|
|
||||||
|
|
||||||
# defaults for testing
|
|
||||||
failfast = catchbreak = buffer = progName = None
|
|
||||||
|
|
||||||
def __init__(self, module='__main__', defaultTest=None,
|
|
||||||
argv=None, testRunner=None,
|
|
||||||
testLoader=loader.defaultTestLoader, exit=True,
|
|
||||||
verbosity=1, failfast=None, catchbreak=None, buffer=None):
|
|
||||||
if isinstance(module, basestring):
|
|
||||||
self.module = __import__(module)
|
|
||||||
for part in module.split('.')[1:]:
|
|
||||||
self.module = getattr(self.module, part)
|
|
||||||
else:
|
|
||||||
self.module = module
|
|
||||||
if argv is None:
|
|
||||||
argv = sys.argv
|
|
||||||
|
|
||||||
self.exit = exit
|
|
||||||
self.verbosity = verbosity
|
|
||||||
self.failfast = failfast
|
|
||||||
self.catchbreak = catchbreak
|
|
||||||
self.buffer = buffer
|
|
||||||
self.defaultTest = defaultTest
|
|
||||||
self.testRunner = testRunner
|
|
||||||
self.testLoader = testLoader
|
|
||||||
self.progName = os.path.basename(argv[0])
|
|
||||||
self.parseArgs(argv)
|
|
||||||
self.runTests()
|
|
||||||
|
|
||||||
def usageExit(self, msg=None):
|
|
||||||
if msg:
|
|
||||||
print msg
|
|
||||||
usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '',
|
|
||||||
'buffer': ''}
|
|
||||||
if self.failfast != False:
|
|
||||||
usage['failfast'] = FAILFAST
|
|
||||||
if self.catchbreak != False and installHandler is not None:
|
|
||||||
usage['catchbreak'] = CATCHBREAK
|
|
||||||
if self.buffer != False:
|
|
||||||
usage['buffer'] = BUFFEROUTPUT
|
|
||||||
print self.USAGE % usage
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
def parseArgs(self, argv):
|
|
||||||
if len(argv) > 1 and argv[1].lower() == 'discover':
|
|
||||||
self._do_discovery(argv[2:])
|
|
||||||
return
|
|
||||||
|
|
||||||
import getopt
|
|
||||||
long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer']
|
|
||||||
try:
|
|
||||||
options, args = getopt.getopt(argv[1:], 'hHvqfcb', long_opts)
|
|
||||||
for opt, value in options:
|
|
||||||
if opt in ('-h','-H','--help'):
|
|
||||||
self.usageExit()
|
|
||||||
if opt in ('-q','--quiet'):
|
|
||||||
self.verbosity = 0
|
|
||||||
if opt in ('-v','--verbose'):
|
|
||||||
self.verbosity = 2
|
|
||||||
if opt in ('-f','--failfast'):
|
|
||||||
if self.failfast is None:
|
|
||||||
self.failfast = True
|
|
||||||
# Should this raise an exception if -f is not valid?
|
|
||||||
if opt in ('-c','--catch'):
|
|
||||||
if self.catchbreak is None and installHandler is not None:
|
|
||||||
self.catchbreak = True
|
|
||||||
# Should this raise an exception if -c is not valid?
|
|
||||||
if opt in ('-b','--buffer'):
|
|
||||||
if self.buffer is None:
|
|
||||||
self.buffer = True
|
|
||||||
# Should this raise an exception if -b is not valid?
|
|
||||||
if len(args) == 0 and self.defaultTest is None:
|
|
||||||
# createTests will load tests from self.module
|
|
||||||
self.testNames = None
|
|
||||||
elif len(args) > 0:
|
|
||||||
self.testNames = args
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# to support python -m unittest ...
|
|
||||||
self.module = None
|
|
||||||
else:
|
|
||||||
self.testNames = (self.defaultTest,)
|
|
||||||
self.createTests()
|
|
||||||
except getopt.error, msg:
|
|
||||||
self.usageExit(msg)
|
|
||||||
|
|
||||||
def createTests(self):
|
|
||||||
if self.testNames is None:
|
|
||||||
self.test = self.testLoader.loadTestsFromModule(self.module)
|
|
||||||
else:
|
|
||||||
self.test = self.testLoader.loadTestsFromNames(self.testNames,
|
|
||||||
self.module)
|
|
||||||
|
|
||||||
def _do_discovery(self, argv, Loader=loader.TestLoader):
|
|
||||||
# handle command line args for test discovery
|
|
||||||
self.progName = '%s discover' % self.progName
|
|
||||||
import optparse
|
|
||||||
parser = optparse.OptionParser()
|
|
||||||
parser.prog = self.progName
|
|
||||||
parser.add_option('-v', '--verbose', dest='verbose', default=False,
|
|
||||||
help='Verbose output', action='store_true')
|
|
||||||
if self.failfast != False:
|
|
||||||
parser.add_option('-f', '--failfast', dest='failfast', default=False,
|
|
||||||
help='Stop on first fail or error',
|
|
||||||
action='store_true')
|
|
||||||
if self.catchbreak != False and installHandler is not None:
|
|
||||||
parser.add_option('-c', '--catch', dest='catchbreak', default=False,
|
|
||||||
help='Catch ctrl-C and display results so far',
|
|
||||||
action='store_true')
|
|
||||||
if self.buffer != False:
|
|
||||||
parser.add_option('-b', '--buffer', dest='buffer', default=False,
|
|
||||||
help='Buffer stdout and stderr during tests',
|
|
||||||
action='store_true')
|
|
||||||
parser.add_option('-s', '--start-directory', dest='start', default='.',
|
|
||||||
help="Directory to start discovery ('.' default)")
|
|
||||||
parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
|
|
||||||
help="Pattern to match tests ('test*.py' default)")
|
|
||||||
parser.add_option('-t', '--top-level-directory', dest='top', default=None,
|
|
||||||
help='Top level directory of project (defaults to start directory)')
|
|
||||||
|
|
||||||
options, args = parser.parse_args(argv)
|
|
||||||
if len(args) > 3:
|
|
||||||
self.usageExit()
|
|
||||||
|
|
||||||
for name, value in zip(('start', 'pattern', 'top'), args):
|
|
||||||
setattr(options, name, value)
|
|
||||||
|
|
||||||
# only set options from the parsing here
|
|
||||||
# if they weren't set explicitly in the constructor
|
|
||||||
if self.failfast is None:
|
|
||||||
self.failfast = options.failfast
|
|
||||||
if self.catchbreak is None and installHandler is not None:
|
|
||||||
self.catchbreak = options.catchbreak
|
|
||||||
if self.buffer is None:
|
|
||||||
self.buffer = options.buffer
|
|
||||||
|
|
||||||
if options.verbose:
|
|
||||||
self.verbosity = 2
|
|
||||||
|
|
||||||
start_dir = options.start
|
|
||||||
pattern = options.pattern
|
|
||||||
top_level_dir = options.top
|
|
||||||
|
|
||||||
loader = Loader()
|
|
||||||
self.test = loader.discover(start_dir, pattern, top_level_dir)
|
|
||||||
|
|
||||||
def runTests(self):
|
|
||||||
if self.catchbreak:
|
|
||||||
installHandler()
|
|
||||||
if self.testRunner is None:
|
|
||||||
self.testRunner = runner.TextTestRunner
|
|
||||||
if isinstance(self.testRunner, (type, types.ClassType)):
|
|
||||||
try:
|
|
||||||
testRunner = self.testRunner(verbosity=self.verbosity,
|
|
||||||
failfast=self.failfast,
|
|
||||||
buffer=self.buffer)
|
|
||||||
except TypeError:
|
|
||||||
# didn't accept the verbosity, buffer or failfast arguments
|
|
||||||
testRunner = self.testRunner()
|
|
||||||
else:
|
|
||||||
# it is assumed to be a TestRunner instance
|
|
||||||
testRunner = self.testRunner
|
|
||||||
self.result = testRunner.run(self.test)
|
|
||||||
if self.exit:
|
|
||||||
sys.exit(not self.result.wasSuccessful())
|
|
||||||
|
|
||||||
main = TestProgram
|
|
||||||
|
|
||||||
def main_():
|
|
||||||
TestProgram.USAGE = USAGE_AS_MAIN
|
|
||||||
main(module=None)
|
|
||||||
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
"""Test result object"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from StringIO import StringIO
|
|
||||||
|
|
||||||
from unittest2 import util
|
|
||||||
from unittest2.compatibility import wraps
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
def failfast(method):
|
|
||||||
@wraps(method)
|
|
||||||
def inner(self, *args, **kw):
|
|
||||||
if getattr(self, 'failfast', False):
|
|
||||||
self.stop()
|
|
||||||
return method(self, *args, **kw)
|
|
||||||
return inner
|
|
||||||
|
|
||||||
|
|
||||||
STDOUT_LINE = '\nStdout:\n%s'
|
|
||||||
STDERR_LINE = '\nStderr:\n%s'
|
|
||||||
|
|
||||||
class TestResult(unittest.TestResult):
|
|
||||||
"""Holder for test result information.
|
|
||||||
|
|
||||||
Test results are automatically managed by the TestCase and TestSuite
|
|
||||||
classes, and do not need to be explicitly manipulated by writers of tests.
|
|
||||||
|
|
||||||
Each instance holds the total number of tests run, and collections of
|
|
||||||
failures and errors that occurred among those test runs. The collections
|
|
||||||
contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
|
|
||||||
formatted traceback of the error that occurred.
|
|
||||||
"""
|
|
||||||
_previousTestClass = None
|
|
||||||
_moduleSetUpFailed = False
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.failfast = False
|
|
||||||
self.failures = []
|
|
||||||
self.errors = []
|
|
||||||
self.testsRun = 0
|
|
||||||
self.skipped = []
|
|
||||||
self.expectedFailures = []
|
|
||||||
self.unexpectedSuccesses = []
|
|
||||||
self.shouldStop = False
|
|
||||||
self.buffer = False
|
|
||||||
self._stdout_buffer = None
|
|
||||||
self._stderr_buffer = None
|
|
||||||
self._original_stdout = sys.stdout
|
|
||||||
self._original_stderr = sys.stderr
|
|
||||||
self._mirrorOutput = False
|
|
||||||
|
|
||||||
def startTest(self, test):
|
|
||||||
"Called when the given test is about to be run"
|
|
||||||
self.testsRun += 1
|
|
||||||
self._mirrorOutput = False
|
|
||||||
if self.buffer:
|
|
||||||
if self._stderr_buffer is None:
|
|
||||||
self._stderr_buffer = StringIO()
|
|
||||||
self._stdout_buffer = StringIO()
|
|
||||||
sys.stdout = self._stdout_buffer
|
|
||||||
sys.stderr = self._stderr_buffer
|
|
||||||
|
|
||||||
def startTestRun(self):
|
|
||||||
"""Called once before any tests are executed.
|
|
||||||
|
|
||||||
See startTest for a method called before each test.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def stopTest(self, test):
|
|
||||||
"""Called when the given test has been run"""
|
|
||||||
if self.buffer:
|
|
||||||
if self._mirrorOutput:
|
|
||||||
output = sys.stdout.getvalue()
|
|
||||||
error = sys.stderr.getvalue()
|
|
||||||
if output:
|
|
||||||
if not output.endswith('\n'):
|
|
||||||
output += '\n'
|
|
||||||
self._original_stdout.write(STDOUT_LINE % output)
|
|
||||||
if error:
|
|
||||||
if not error.endswith('\n'):
|
|
||||||
error += '\n'
|
|
||||||
self._original_stderr.write(STDERR_LINE % error)
|
|
||||||
|
|
||||||
sys.stdout = self._original_stdout
|
|
||||||
sys.stderr = self._original_stderr
|
|
||||||
self._stdout_buffer.seek(0)
|
|
||||||
self._stdout_buffer.truncate()
|
|
||||||
self._stderr_buffer.seek(0)
|
|
||||||
self._stderr_buffer.truncate()
|
|
||||||
self._mirrorOutput = False
|
|
||||||
|
|
||||||
|
|
||||||
def stopTestRun(self):
|
|
||||||
"""Called once after all tests are executed.
|
|
||||||
|
|
||||||
See stopTest for a method called after each test.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@failfast
|
|
||||||
def addError(self, test, err):
|
|
||||||
"""Called when an error has occurred. 'err' is a tuple of values as
|
|
||||||
returned by sys.exc_info().
|
|
||||||
"""
|
|
||||||
self.errors.append((test, self._exc_info_to_string(err, test)))
|
|
||||||
self._mirrorOutput = True
|
|
||||||
|
|
||||||
@failfast
|
|
||||||
def addFailure(self, test, err):
|
|
||||||
"""Called when an error has occurred. 'err' is a tuple of values as
|
|
||||||
returned by sys.exc_info()."""
|
|
||||||
self.failures.append((test, self._exc_info_to_string(err, test)))
|
|
||||||
self._mirrorOutput = True
|
|
||||||
|
|
||||||
def addSuccess(self, test):
|
|
||||||
"Called when a test has completed successfully"
|
|
||||||
pass
|
|
||||||
|
|
||||||
def addSkip(self, test, reason):
|
|
||||||
"""Called when a test is skipped."""
|
|
||||||
self.skipped.append((test, reason))
|
|
||||||
|
|
||||||
def addExpectedFailure(self, test, err):
|
|
||||||
"""Called when an expected failure/error occured."""
|
|
||||||
self.expectedFailures.append(
|
|
||||||
(test, self._exc_info_to_string(err, test)))
|
|
||||||
|
|
||||||
@failfast
|
|
||||||
def addUnexpectedSuccess(self, test):
|
|
||||||
"""Called when a test was expected to fail, but succeed."""
|
|
||||||
self.unexpectedSuccesses.append(test)
|
|
||||||
|
|
||||||
def wasSuccessful(self):
|
|
||||||
"Tells whether or not this result was a success"
|
|
||||||
return (len(self.failures) + len(self.errors) == 0)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
"Indicates that the tests should be aborted"
|
|
||||||
self.shouldStop = True
|
|
||||||
|
|
||||||
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)
|
|
||||||
msgLines = traceback.format_exception(exctype, value, tb, length)
|
|
||||||
else:
|
|
||||||
msgLines = traceback.format_exception(exctype, value, tb)
|
|
||||||
|
|
||||||
if self.buffer:
|
|
||||||
output = sys.stdout.getvalue()
|
|
||||||
error = sys.stderr.getvalue()
|
|
||||||
if output:
|
|
||||||
if not output.endswith('\n'):
|
|
||||||
output += '\n'
|
|
||||||
msgLines.append(STDOUT_LINE % output)
|
|
||||||
if error:
|
|
||||||
if not error.endswith('\n'):
|
|
||||||
error += '\n'
|
|
||||||
msgLines.append(STDERR_LINE % error)
|
|
||||||
return ''.join(msgLines)
|
|
||||||
|
|
||||||
def _is_relevant_tb_level(self, tb):
|
|
||||||
return '__unittest' in tb.tb_frame.f_globals
|
|
||||||
|
|
||||||
def _count_relevant_tb_levels(self, tb):
|
|
||||||
length = 0
|
|
||||||
while tb and not self._is_relevant_tb_level(tb):
|
|
||||||
length += 1
|
|
||||||
tb = tb.tb_next
|
|
||||||
return length
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "<%s run=%i errors=%i failures=%i>" % \
|
|
||||||
(util.strclass(self.__class__), self.testsRun, len(self.errors),
|
|
||||||
len(self.failures))
|
|
||||||
|
|
@ -1,206 +0,0 @@
|
||||||
"""Running tests"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from unittest2 import result
|
|
||||||
|
|
||||||
try:
|
|
||||||
from unittest2.signals import registerResult
|
|
||||||
except ImportError:
|
|
||||||
def registerResult(_):
|
|
||||||
pass
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
|
|
||||||
class _WritelnDecorator(object):
|
|
||||||
"""Used to decorate file-like objects with a handy 'writeln' method"""
|
|
||||||
def __init__(self,stream):
|
|
||||||
self.stream = stream
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
if attr in ('stream', '__getstate__'):
|
|
||||||
raise AttributeError(attr)
|
|
||||||
return getattr(self.stream,attr)
|
|
||||||
|
|
||||||
def writeln(self, arg=None):
|
|
||||||
if arg:
|
|
||||||
self.write(arg)
|
|
||||||
self.write('\n') # text-mode streams translate to \r\n if needed
|
|
||||||
|
|
||||||
|
|
||||||
class TextTestResult(result.TestResult):
|
|
||||||
"""A test result class that can print formatted text results to a stream.
|
|
||||||
|
|
||||||
Used by TextTestRunner.
|
|
||||||
"""
|
|
||||||
separator1 = '=' * 70
|
|
||||||
separator2 = '-' * 70
|
|
||||||
|
|
||||||
def __init__(self, stream, descriptions, verbosity):
|
|
||||||
super(TextTestResult, self).__init__()
|
|
||||||
self.stream = stream
|
|
||||||
self.showAll = verbosity > 1
|
|
||||||
self.dots = verbosity == 1
|
|
||||||
self.descriptions = descriptions
|
|
||||||
|
|
||||||
def getDescription(self, test):
|
|
||||||
doc_first_line = test.shortDescription()
|
|
||||||
if self.descriptions and doc_first_line:
|
|
||||||
return '\n'.join((str(test), doc_first_line))
|
|
||||||
else:
|
|
||||||
return str(test)
|
|
||||||
|
|
||||||
def startTest(self, test):
|
|
||||||
super(TextTestResult, self).startTest(test)
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.write(self.getDescription(test))
|
|
||||||
self.stream.write(" ... ")
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
def addSuccess(self, test):
|
|
||||||
super(TextTestResult, self).addSuccess(test)
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.writeln("ok")
|
|
||||||
elif self.dots:
|
|
||||||
self.stream.write('.')
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
def addError(self, test, err):
|
|
||||||
super(TextTestResult, self).addError(test, err)
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.writeln("ERROR")
|
|
||||||
elif self.dots:
|
|
||||||
self.stream.write('E')
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
def addFailure(self, test, err):
|
|
||||||
super(TextTestResult, self).addFailure(test, err)
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.writeln("FAIL")
|
|
||||||
elif self.dots:
|
|
||||||
self.stream.write('F')
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
def addSkip(self, test, reason):
|
|
||||||
super(TextTestResult, self).addSkip(test, reason)
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.writeln("skipped %r" % (reason,))
|
|
||||||
elif self.dots:
|
|
||||||
self.stream.write("s")
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
def addExpectedFailure(self, test, err):
|
|
||||||
super(TextTestResult, self).addExpectedFailure(test, err)
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.writeln("expected failure")
|
|
||||||
elif self.dots:
|
|
||||||
self.stream.write("x")
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
def addUnexpectedSuccess(self, test):
|
|
||||||
super(TextTestResult, self).addUnexpectedSuccess(test)
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.writeln("unexpected success")
|
|
||||||
elif self.dots:
|
|
||||||
self.stream.write("u")
|
|
||||||
self.stream.flush()
|
|
||||||
|
|
||||||
def printErrors(self):
|
|
||||||
if self.dots or self.showAll:
|
|
||||||
self.stream.writeln()
|
|
||||||
self.printErrorList('ERROR', self.errors)
|
|
||||||
self.printErrorList('FAIL', self.failures)
|
|
||||||
|
|
||||||
def printErrorList(self, flavour, errors):
|
|
||||||
for test, err in errors:
|
|
||||||
self.stream.writeln(self.separator1)
|
|
||||||
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
|
|
||||||
self.stream.writeln(self.separator2)
|
|
||||||
self.stream.writeln("%s" % err)
|
|
||||||
|
|
||||||
def stopTestRun(self):
|
|
||||||
super(TextTestResult, self).stopTestRun()
|
|
||||||
self.printErrors()
|
|
||||||
|
|
||||||
|
|
||||||
class TextTestRunner(unittest.TextTestRunner):
|
|
||||||
"""A test runner class that displays results in textual form.
|
|
||||||
|
|
||||||
It prints out the names of tests as they are run, errors as they
|
|
||||||
occur, and a summary of the results at the end of the test run.
|
|
||||||
"""
|
|
||||||
resultclass = TextTestResult
|
|
||||||
|
|
||||||
def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
|
|
||||||
failfast=False, buffer=False, resultclass=None):
|
|
||||||
self.stream = _WritelnDecorator(stream)
|
|
||||||
self.descriptions = descriptions
|
|
||||||
self.verbosity = verbosity
|
|
||||||
self.failfast = failfast
|
|
||||||
self.buffer = buffer
|
|
||||||
if resultclass is not None:
|
|
||||||
self.resultclass = resultclass
|
|
||||||
|
|
||||||
def _makeResult(self):
|
|
||||||
return self.resultclass(self.stream, self.descriptions, self.verbosity)
|
|
||||||
|
|
||||||
def run(self, test):
|
|
||||||
"Run the given test case or test suite."
|
|
||||||
result = self._makeResult()
|
|
||||||
result.failfast = self.failfast
|
|
||||||
result.buffer = self.buffer
|
|
||||||
registerResult(result)
|
|
||||||
|
|
||||||
startTime = time.time()
|
|
||||||
startTestRun = getattr(result, 'startTestRun', None)
|
|
||||||
if startTestRun is not None:
|
|
||||||
startTestRun()
|
|
||||||
try:
|
|
||||||
test(result)
|
|
||||||
finally:
|
|
||||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
|
||||||
if stopTestRun is not None:
|
|
||||||
stopTestRun()
|
|
||||||
else:
|
|
||||||
result.printErrors()
|
|
||||||
stopTime = time.time()
|
|
||||||
timeTaken = stopTime - startTime
|
|
||||||
if hasattr(result, 'separator2'):
|
|
||||||
self.stream.writeln(result.separator2)
|
|
||||||
run = result.testsRun
|
|
||||||
self.stream.writeln("Ran %d test%s in %.3fs" %
|
|
||||||
(run, run != 1 and "s" or "", timeTaken))
|
|
||||||
self.stream.writeln()
|
|
||||||
|
|
||||||
expectedFails = unexpectedSuccesses = skipped = 0
|
|
||||||
try:
|
|
||||||
results = map(len, (result.expectedFailures,
|
|
||||||
result.unexpectedSuccesses,
|
|
||||||
result.skipped))
|
|
||||||
expectedFails, unexpectedSuccesses, skipped = results
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
infos = []
|
|
||||||
if not result.wasSuccessful():
|
|
||||||
self.stream.write("FAILED")
|
|
||||||
failed, errored = map(len, (result.failures, result.errors))
|
|
||||||
if failed:
|
|
||||||
infos.append("failures=%d" % failed)
|
|
||||||
if errored:
|
|
||||||
infos.append("errors=%d" % errored)
|
|
||||||
else:
|
|
||||||
self.stream.write("OK")
|
|
||||||
if skipped:
|
|
||||||
infos.append("skipped=%d" % skipped)
|
|
||||||
if expectedFails:
|
|
||||||
infos.append("expected failures=%d" % expectedFails)
|
|
||||||
if unexpectedSuccesses:
|
|
||||||
infos.append("unexpected successes=%d" % unexpectedSuccesses)
|
|
||||||
if infos:
|
|
||||||
self.stream.writeln(" (%s)" % (", ".join(infos),))
|
|
||||||
else:
|
|
||||||
self.stream.write("\n")
|
|
||||||
return result
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
import signal
|
|
||||||
import weakref
|
|
||||||
|
|
||||||
from unittest2.compatibility import wraps
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
|
|
||||||
class _InterruptHandler(object):
|
|
||||||
def __init__(self, default_handler):
|
|
||||||
self.called = False
|
|
||||||
self.default_handler = default_handler
|
|
||||||
|
|
||||||
def __call__(self, signum, frame):
|
|
||||||
installed_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
if installed_handler is not self:
|
|
||||||
# if we aren't the installed handler, then delegate immediately
|
|
||||||
# to the default handler
|
|
||||||
self.default_handler(signum, frame)
|
|
||||||
|
|
||||||
if self.called:
|
|
||||||
self.default_handler(signum, frame)
|
|
||||||
self.called = True
|
|
||||||
for result in _results.keys():
|
|
||||||
result.stop()
|
|
||||||
|
|
||||||
_results = weakref.WeakKeyDictionary()
|
|
||||||
def registerResult(result):
|
|
||||||
_results[result] = 1
|
|
||||||
|
|
||||||
def removeResult(result):
|
|
||||||
return bool(_results.pop(result, None))
|
|
||||||
|
|
||||||
_interrupt_handler = None
|
|
||||||
def installHandler():
|
|
||||||
global _interrupt_handler
|
|
||||||
if _interrupt_handler is None:
|
|
||||||
default_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
_interrupt_handler = _InterruptHandler(default_handler)
|
|
||||||
signal.signal(signal.SIGINT, _interrupt_handler)
|
|
||||||
|
|
||||||
|
|
||||||
def removeHandler(method=None):
|
|
||||||
if method is not None:
|
|
||||||
@wraps(method)
|
|
||||||
def inner(*args, **kwargs):
|
|
||||||
initial = signal.getsignal(signal.SIGINT)
|
|
||||||
removeHandler()
|
|
||||||
try:
|
|
||||||
return method(*args, **kwargs)
|
|
||||||
finally:
|
|
||||||
signal.signal(signal.SIGINT, initial)
|
|
||||||
return inner
|
|
||||||
|
|
||||||
global _interrupt_handler
|
|
||||||
if _interrupt_handler is not None:
|
|
||||||
signal.signal(signal.SIGINT, _interrupt_handler.default_handler)
|
|
||||||
|
|
@ -1,287 +0,0 @@
|
||||||
"""TestSuite"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import unittest
|
|
||||||
from unittest2 import case, util
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
|
|
||||||
class BaseTestSuite(unittest.TestSuite):
|
|
||||||
"""A simple test suite that doesn't provide class or module shared fixtures.
|
|
||||||
"""
|
|
||||||
def __init__(self, tests=()):
|
|
||||||
self._tests = []
|
|
||||||
self.addTests(tests)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if not isinstance(other, self.__class__):
|
|
||||||
return NotImplemented
|
|
||||||
return list(self) == list(other)
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return not self == other
|
|
||||||
|
|
||||||
# Can't guarantee hash invariant, so flag as unhashable
|
|
||||||
__hash__ = None
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return iter(self._tests)
|
|
||||||
|
|
||||||
def countTestCases(self):
|
|
||||||
cases = 0
|
|
||||||
for test in self:
|
|
||||||
cases += test.countTestCases()
|
|
||||||
return cases
|
|
||||||
|
|
||||||
def addTest(self, test):
|
|
||||||
# sanity checks
|
|
||||||
if not hasattr(test, '__call__'):
|
|
||||||
raise TypeError("%r is not callable" % (repr(test),))
|
|
||||||
if isinstance(test, type) and issubclass(test,
|
|
||||||
(case.TestCase, TestSuite)):
|
|
||||||
raise TypeError("TestCases and TestSuites must be instantiated "
|
|
||||||
"before passing them to addTest()")
|
|
||||||
self._tests.append(test)
|
|
||||||
|
|
||||||
def addTests(self, tests):
|
|
||||||
if isinstance(tests, basestring):
|
|
||||||
raise TypeError("tests must be an iterable of tests, not a string")
|
|
||||||
for test in tests:
|
|
||||||
self.addTest(test)
|
|
||||||
|
|
||||||
def run(self, result):
|
|
||||||
for test in self:
|
|
||||||
if result.shouldStop:
|
|
||||||
break
|
|
||||||
test(result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def __call__(self, *args, **kwds):
|
|
||||||
return self.run(*args, **kwds)
|
|
||||||
|
|
||||||
def debug(self):
|
|
||||||
"""Run the tests without collecting errors in a TestResult"""
|
|
||||||
for test in self:
|
|
||||||
test.debug()
|
|
||||||
|
|
||||||
|
|
||||||
class TestSuite(BaseTestSuite):
|
|
||||||
"""A test suite is a composite test consisting of a number of TestCases.
|
|
||||||
|
|
||||||
For use, create an instance of TestSuite, then add test case instances.
|
|
||||||
When all tests have been added, the suite can be passed to a test
|
|
||||||
runner, such as TextTestRunner. It will run the individual test cases
|
|
||||||
in the order in which they were added, aggregating the results. When
|
|
||||||
subclassing, do not forget to call the base class constructor.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def run(self, result):
|
|
||||||
self._wrapped_run(result)
|
|
||||||
self._tearDownPreviousClass(None, result)
|
|
||||||
self._handleModuleTearDown(result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def debug(self):
|
|
||||||
"""Run the tests without collecting errors in a TestResult"""
|
|
||||||
debug = _DebugResult()
|
|
||||||
self._wrapped_run(debug, True)
|
|
||||||
self._tearDownPreviousClass(None, debug)
|
|
||||||
self._handleModuleTearDown(debug)
|
|
||||||
|
|
||||||
################################
|
|
||||||
# private methods
|
|
||||||
def _wrapped_run(self, result, debug=False):
|
|
||||||
for test in self:
|
|
||||||
if result.shouldStop:
|
|
||||||
break
|
|
||||||
|
|
||||||
if _isnotsuite(test):
|
|
||||||
self._tearDownPreviousClass(test, result)
|
|
||||||
self._handleModuleFixture(test, result)
|
|
||||||
self._handleClassSetUp(test, result)
|
|
||||||
result._previousTestClass = test.__class__
|
|
||||||
|
|
||||||
if (getattr(test.__class__, '_classSetupFailed', False) or
|
|
||||||
getattr(result, '_moduleSetUpFailed', False)):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if hasattr(test, '_wrapped_run'):
|
|
||||||
test._wrapped_run(result, debug)
|
|
||||||
elif not debug:
|
|
||||||
test(result)
|
|
||||||
else:
|
|
||||||
test.debug()
|
|
||||||
|
|
||||||
def _handleClassSetUp(self, test, result):
|
|
||||||
previousClass = getattr(result, '_previousTestClass', None)
|
|
||||||
currentClass = test.__class__
|
|
||||||
if currentClass == previousClass:
|
|
||||||
return
|
|
||||||
if result._moduleSetUpFailed:
|
|
||||||
return
|
|
||||||
if getattr(currentClass, "__unittest_skip__", False):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
currentClass._classSetupFailed = False
|
|
||||||
except TypeError:
|
|
||||||
# test may actually be a function
|
|
||||||
# so its class will be a builtin-type
|
|
||||||
pass
|
|
||||||
|
|
||||||
setUpClass = getattr(currentClass, 'setUpClass', None)
|
|
||||||
if setUpClass is not None:
|
|
||||||
try:
|
|
||||||
setUpClass()
|
|
||||||
except Exception, e:
|
|
||||||
if isinstance(result, _DebugResult):
|
|
||||||
raise
|
|
||||||
currentClass._classSetupFailed = True
|
|
||||||
className = util.strclass(currentClass)
|
|
||||||
errorName = 'setUpClass (%s)' % className
|
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
|
||||||
|
|
||||||
def _get_previous_module(self, result):
|
|
||||||
previousModule = None
|
|
||||||
previousClass = getattr(result, '_previousTestClass', None)
|
|
||||||
if previousClass is not None:
|
|
||||||
previousModule = previousClass.__module__
|
|
||||||
return previousModule
|
|
||||||
|
|
||||||
|
|
||||||
def _handleModuleFixture(self, test, result):
|
|
||||||
previousModule = self._get_previous_module(result)
|
|
||||||
currentModule = test.__class__.__module__
|
|
||||||
if currentModule == previousModule:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._handleModuleTearDown(result)
|
|
||||||
|
|
||||||
|
|
||||||
result._moduleSetUpFailed = False
|
|
||||||
try:
|
|
||||||
module = sys.modules[currentModule]
|
|
||||||
except KeyError:
|
|
||||||
return
|
|
||||||
setUpModule = getattr(module, 'setUpModule', None)
|
|
||||||
if setUpModule is not None:
|
|
||||||
try:
|
|
||||||
setUpModule()
|
|
||||||
except Exception, e:
|
|
||||||
if isinstance(result, _DebugResult):
|
|
||||||
raise
|
|
||||||
result._moduleSetUpFailed = True
|
|
||||||
errorName = 'setUpModule (%s)' % currentModule
|
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
|
||||||
|
|
||||||
def _addClassOrModuleLevelException(self, result, exception, errorName):
|
|
||||||
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())
|
|
||||||
|
|
||||||
def _handleModuleTearDown(self, result):
|
|
||||||
previousModule = self._get_previous_module(result)
|
|
||||||
if previousModule is None:
|
|
||||||
return
|
|
||||||
if result._moduleSetUpFailed:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
module = sys.modules[previousModule]
|
|
||||||
except KeyError:
|
|
||||||
return
|
|
||||||
|
|
||||||
tearDownModule = getattr(module, 'tearDownModule', None)
|
|
||||||
if tearDownModule is not None:
|
|
||||||
try:
|
|
||||||
tearDownModule()
|
|
||||||
except Exception, e:
|
|
||||||
if isinstance(result, _DebugResult):
|
|
||||||
raise
|
|
||||||
errorName = 'tearDownModule (%s)' % previousModule
|
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
|
||||||
|
|
||||||
def _tearDownPreviousClass(self, test, result):
|
|
||||||
previousClass = getattr(result, '_previousTestClass', None)
|
|
||||||
currentClass = test.__class__
|
|
||||||
if currentClass == previousClass:
|
|
||||||
return
|
|
||||||
if getattr(previousClass, '_classSetupFailed', False):
|
|
||||||
return
|
|
||||||
if getattr(result, '_moduleSetUpFailed', False):
|
|
||||||
return
|
|
||||||
if getattr(previousClass, "__unittest_skip__", False):
|
|
||||||
return
|
|
||||||
|
|
||||||
tearDownClass = getattr(previousClass, 'tearDownClass', None)
|
|
||||||
if tearDownClass is not None:
|
|
||||||
try:
|
|
||||||
tearDownClass()
|
|
||||||
except Exception, e:
|
|
||||||
if isinstance(result, _DebugResult):
|
|
||||||
raise
|
|
||||||
className = util.strclass(previousClass)
|
|
||||||
errorName = 'tearDownClass (%s)' % className
|
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
|
||||||
|
|
||||||
|
|
||||||
class _ErrorHolder(object):
|
|
||||||
"""
|
|
||||||
Placeholder for a TestCase inside a result. As far as a TestResult
|
|
||||||
is concerned, this looks exactly like a unit test. Used to insert
|
|
||||||
arbitrary errors into a test suite run.
|
|
||||||
"""
|
|
||||||
# Inspired by the ErrorHolder from Twisted:
|
|
||||||
# http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py
|
|
||||||
|
|
||||||
# attribute used by TestResult._exc_info_to_string
|
|
||||||
failureException = None
|
|
||||||
|
|
||||||
def __init__(self, description):
|
|
||||||
self.description = description
|
|
||||||
|
|
||||||
def id(self):
|
|
||||||
return self.description
|
|
||||||
|
|
||||||
def shortDescription(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "<ErrorHolder description=%r>" % (self.description,)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.id()
|
|
||||||
|
|
||||||
def run(self, result):
|
|
||||||
# could call result.addError(...) - but this test-like object
|
|
||||||
# shouldn't be run anyway
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __call__(self, result):
|
|
||||||
return self.run(result)
|
|
||||||
|
|
||||||
def countTestCases(self):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def _isnotsuite(test):
|
|
||||||
"A crude way to tell apart testcases and suites with duck-typing"
|
|
||||||
try:
|
|
||||||
iter(test)
|
|
||||||
except TypeError:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class _DebugResult(object):
|
|
||||||
"Used by the TestSuite to hold previous class when running in debug."
|
|
||||||
_previousTestClass = None
|
|
||||||
_moduleSetUpFailed = False
|
|
||||||
shouldStop = False
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#
|
|
||||||
|
|
@ -1,177 +0,0 @@
|
||||||
import sys
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
|
|
||||||
def resultFactory(*_):
|
|
||||||
return unittest2.TestResult()
|
|
||||||
|
|
||||||
class OldTestResult(object):
|
|
||||||
"""An object honouring TestResult before startTestRun/stopTestRun."""
|
|
||||||
|
|
||||||
def __init__(self, *_):
|
|
||||||
self.failures = []
|
|
||||||
self.errors = []
|
|
||||||
self.testsRun = 0
|
|
||||||
self.shouldStop = False
|
|
||||||
|
|
||||||
def startTest(self, test):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def stopTest(self, test):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def addError(self, test, err):
|
|
||||||
self.errors.append((test, err))
|
|
||||||
|
|
||||||
def addFailure(self, test, err):
|
|
||||||
self.failures.append((test, err))
|
|
||||||
|
|
||||||
def addSuccess(self, test):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def wasSuccessful(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def printErrors(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class LoggingResult(unittest2.TestResult):
|
|
||||||
def __init__(self, log):
|
|
||||||
self._events = log
|
|
||||||
super(LoggingResult, self).__init__()
|
|
||||||
|
|
||||||
def startTest(self, test):
|
|
||||||
self._events.append('startTest')
|
|
||||||
super(LoggingResult, self).startTest(test)
|
|
||||||
|
|
||||||
def startTestRun(self):
|
|
||||||
self._events.append('startTestRun')
|
|
||||||
super(LoggingResult, self).startTestRun()
|
|
||||||
|
|
||||||
def stopTest(self, test):
|
|
||||||
self._events.append('stopTest')
|
|
||||||
super(LoggingResult, self).stopTest(test)
|
|
||||||
|
|
||||||
def stopTestRun(self):
|
|
||||||
self._events.append('stopTestRun')
|
|
||||||
super(LoggingResult, self).stopTestRun()
|
|
||||||
|
|
||||||
def addFailure(self, *args):
|
|
||||||
self._events.append('addFailure')
|
|
||||||
super(LoggingResult, self).addFailure(*args)
|
|
||||||
|
|
||||||
def addSuccess(self, *args):
|
|
||||||
self._events.append('addSuccess')
|
|
||||||
super(LoggingResult, self).addSuccess(*args)
|
|
||||||
|
|
||||||
def addError(self, *args):
|
|
||||||
self._events.append('addError')
|
|
||||||
super(LoggingResult, self).addError(*args)
|
|
||||||
|
|
||||||
def addSkip(self, *args):
|
|
||||||
self._events.append('addSkip')
|
|
||||||
super(LoggingResult, self).addSkip(*args)
|
|
||||||
|
|
||||||
def addExpectedFailure(self, *args):
|
|
||||||
self._events.append('addExpectedFailure')
|
|
||||||
super(LoggingResult, self).addExpectedFailure(*args)
|
|
||||||
|
|
||||||
def addUnexpectedSuccess(self, *args):
|
|
||||||
self._events.append('addUnexpectedSuccess')
|
|
||||||
super(LoggingResult, self).addUnexpectedSuccess(*args)
|
|
||||||
|
|
||||||
|
|
||||||
class EqualityMixin(object):
|
|
||||||
"""Used as a mixin for TestCase"""
|
|
||||||
|
|
||||||
# Check for a valid __eq__ implementation
|
|
||||||
def test_eq(self):
|
|
||||||
for obj_1, obj_2 in self.eq_pairs:
|
|
||||||
self.assertEqual(obj_1, obj_2)
|
|
||||||
self.assertEqual(obj_2, obj_1)
|
|
||||||
|
|
||||||
# Check for a valid __ne__ implementation
|
|
||||||
def test_ne(self):
|
|
||||||
for obj_1, obj_2 in self.ne_pairs:
|
|
||||||
self.assertNotEqual(obj_1, obj_2)
|
|
||||||
self.assertNotEqual(obj_2, obj_1)
|
|
||||||
|
|
||||||
class HashingMixin(object):
|
|
||||||
"""Used as a mixin for TestCase"""
|
|
||||||
|
|
||||||
# Check for a valid __hash__ implementation
|
|
||||||
def test_hash(self):
|
|
||||||
for obj_1, obj_2 in self.eq_pairs:
|
|
||||||
try:
|
|
||||||
if not hash(obj_1) == hash(obj_2):
|
|
||||||
self.fail("%r and %r do not hash equal" % (obj_1, obj_2))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except Exception, e:
|
|
||||||
self.fail("Problem hashing %r and %r: %s" % (obj_1, obj_2, e))
|
|
||||||
|
|
||||||
for obj_1, obj_2 in self.ne_pairs:
|
|
||||||
try:
|
|
||||||
if hash(obj_1) == hash(obj_2):
|
|
||||||
self.fail("%s and %s hash equal, but shouldn't" %
|
|
||||||
(obj_1, obj_2))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except Exception, e:
|
|
||||||
self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# copied from Python 2.6
|
|
||||||
try:
|
|
||||||
from warnings import catch_warnings
|
|
||||||
except ImportError:
|
|
||||||
class catch_warnings(object):
|
|
||||||
def __init__(self, record=False, module=None):
|
|
||||||
self._record = record
|
|
||||||
self._module = sys.modules['warnings']
|
|
||||||
self._entered = False
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
args = []
|
|
||||||
if self._record:
|
|
||||||
args.append("record=True")
|
|
||||||
name = type(self).__name__
|
|
||||||
return "%s(%s)" % (name, ", ".join(args))
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
if self._entered:
|
|
||||||
raise RuntimeError("Cannot enter %r twice" % self)
|
|
||||||
self._entered = True
|
|
||||||
self._filters = self._module.filters
|
|
||||||
self._module.filters = self._filters[:]
|
|
||||||
self._showwarning = self._module.showwarning
|
|
||||||
if self._record:
|
|
||||||
log = []
|
|
||||||
def showwarning(*args, **kwargs):
|
|
||||||
log.append(WarningMessage(*args, **kwargs))
|
|
||||||
self._module.showwarning = showwarning
|
|
||||||
return log
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __exit__(self, *exc_info):
|
|
||||||
if not self._entered:
|
|
||||||
raise RuntimeError("Cannot exit %r without entering first" % self)
|
|
||||||
self._module.filters = self._filters
|
|
||||||
self._module.showwarning = self._showwarning
|
|
||||||
|
|
||||||
class WarningMessage(object):
|
|
||||||
_WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
|
|
||||||
"line")
|
|
||||||
def __init__(self, message, category, filename, lineno, file=None,
|
|
||||||
line=None):
|
|
||||||
local_values = locals()
|
|
||||||
for attr in self._WARNING_DETAILS:
|
|
||||||
setattr(self, attr, local_values[attr])
|
|
||||||
self._category_name = None
|
|
||||||
if category.__name__:
|
|
||||||
self._category_name = category.__name__
|
|
||||||
|
|
||||||
|
|
@ -1,254 +0,0 @@
|
||||||
import datetime
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
|
|
||||||
class Test_Assertions(unittest2.TestCase):
|
|
||||||
def test_AlmostEqual(self):
|
|
||||||
self.assertAlmostEqual(1.00000001, 1.0)
|
|
||||||
self.assertNotAlmostEqual(1.0000001, 1.0)
|
|
||||||
self.assertRaises(self.failureException,
|
|
||||||
self.assertAlmostEqual, 1.0000001, 1.0)
|
|
||||||
self.assertRaises(self.failureException,
|
|
||||||
self.assertNotAlmostEqual, 1.00000001, 1.0)
|
|
||||||
|
|
||||||
self.assertAlmostEqual(1.1, 1.0, places=0)
|
|
||||||
self.assertRaises(self.failureException,
|
|
||||||
self.assertAlmostEqual, 1.1, 1.0, places=1)
|
|
||||||
|
|
||||||
self.assertAlmostEqual(0, .1+.1j, places=0)
|
|
||||||
self.assertNotAlmostEqual(0, .1+.1j, places=1)
|
|
||||||
self.assertRaises(self.failureException,
|
|
||||||
self.assertAlmostEqual, 0, .1+.1j, places=1)
|
|
||||||
self.assertRaises(self.failureException,
|
|
||||||
self.assertNotAlmostEqual, 0, .1+.1j, places=0)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.assertAlmostEqual(float('inf'), float('inf'))
|
|
||||||
self.assertRaises(self.failureException, self.assertNotAlmostEqual,
|
|
||||||
float('inf'), float('inf'))
|
|
||||||
except ValueError:
|
|
||||||
# float('inf') is invalid on Windows in Python 2.4 / 2.5
|
|
||||||
x = object()
|
|
||||||
self.assertAlmostEqual(x, x)
|
|
||||||
self.assertRaises(self.failureException, self.assertNotAlmostEqual,
|
|
||||||
x, x)
|
|
||||||
|
|
||||||
|
|
||||||
def test_AmostEqualWithDelta(self):
|
|
||||||
self.assertAlmostEqual(1.1, 1.0, delta=0.5)
|
|
||||||
self.assertAlmostEqual(1.0, 1.1, delta=0.5)
|
|
||||||
self.assertNotAlmostEqual(1.1, 1.0, delta=0.05)
|
|
||||||
self.assertNotAlmostEqual(1.0, 1.1, delta=0.05)
|
|
||||||
|
|
||||||
self.assertRaises(self.failureException, self.assertAlmostEqual,
|
|
||||||
1.1, 1.0, delta=0.05)
|
|
||||||
self.assertRaises(self.failureException, self.assertNotAlmostEqual,
|
|
||||||
1.1, 1.0, delta=0.5)
|
|
||||||
|
|
||||||
self.assertRaises(TypeError, self.assertAlmostEqual,
|
|
||||||
1.1, 1.0, places=2, delta=2)
|
|
||||||
self.assertRaises(TypeError, self.assertNotAlmostEqual,
|
|
||||||
1.1, 1.0, places=2, delta=2)
|
|
||||||
|
|
||||||
first = datetime.datetime.now()
|
|
||||||
second = first + datetime.timedelta(seconds=10)
|
|
||||||
self.assertAlmostEqual(first, second,
|
|
||||||
delta=datetime.timedelta(seconds=20))
|
|
||||||
self.assertNotAlmostEqual(first, second,
|
|
||||||
delta=datetime.timedelta(seconds=5))
|
|
||||||
|
|
||||||
def testAssertNotRegexpMatches(self):
|
|
||||||
self.assertNotRegexpMatches('Ala ma kota', r'r+')
|
|
||||||
try:
|
|
||||||
self.assertNotRegexpMatches('Ala ma kota', r'k.t', 'Message')
|
|
||||||
except self.failureException, e:
|
|
||||||
self.assertIn("'kot'", e.args[0])
|
|
||||||
self.assertIn('Message', e.args[0])
|
|
||||||
else:
|
|
||||||
self.fail('assertNotRegexpMatches should have failed.')
|
|
||||||
|
|
||||||
|
|
||||||
class TestLongMessage(unittest2.TestCase):
|
|
||||||
"""Test that the individual asserts honour longMessage.
|
|
||||||
This actually tests all the message behaviour for
|
|
||||||
asserts that use longMessage."""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
class TestableTestFalse(unittest2.TestCase):
|
|
||||||
longMessage = False
|
|
||||||
failureException = self.failureException
|
|
||||||
|
|
||||||
def testTest(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class TestableTestTrue(unittest2.TestCase):
|
|
||||||
longMessage = True
|
|
||||||
failureException = self.failureException
|
|
||||||
|
|
||||||
def testTest(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.testableTrue = TestableTestTrue('testTest')
|
|
||||||
self.testableFalse = TestableTestFalse('testTest')
|
|
||||||
|
|
||||||
def testDefault(self):
|
|
||||||
self.assertTrue(unittest2.TestCase.longMessage)
|
|
||||||
|
|
||||||
def test_formatMsg(self):
|
|
||||||
self.assertEquals(self.testableFalse._formatMessage(None, "foo"), "foo")
|
|
||||||
self.assertEquals(self.testableFalse._formatMessage("foo", "bar"), "foo")
|
|
||||||
|
|
||||||
self.assertEquals(self.testableTrue._formatMessage(None, "foo"), "foo")
|
|
||||||
self.assertEquals(self.testableTrue._formatMessage("foo", "bar"), "bar : foo")
|
|
||||||
|
|
||||||
# This blows up if _formatMessage uses string concatenation
|
|
||||||
self.testableTrue._formatMessage(object(), 'foo')
|
|
||||||
|
|
||||||
def assertMessages(self, methodName, args, errors):
|
|
||||||
def getMethod(i):
|
|
||||||
useTestableFalse = i < 2
|
|
||||||
if useTestableFalse:
|
|
||||||
test = self.testableFalse
|
|
||||||
else:
|
|
||||||
test = self.testableTrue
|
|
||||||
return getattr(test, methodName)
|
|
||||||
|
|
||||||
for i, expected_regexp in enumerate(errors):
|
|
||||||
testMethod = getMethod(i)
|
|
||||||
kwargs = {}
|
|
||||||
withMsg = i % 2
|
|
||||||
if withMsg:
|
|
||||||
kwargs = {"msg": "oops"}
|
|
||||||
|
|
||||||
self.assertRaisesRegexp(self.failureException,
|
|
||||||
expected_regexp,
|
|
||||||
lambda: testMethod(*args, **kwargs))
|
|
||||||
|
|
||||||
def testAssertTrue(self):
|
|
||||||
self.assertMessages('assertTrue', (False,),
|
|
||||||
["^False is not True$", "^oops$", "^False is not True$",
|
|
||||||
"^False is not True : oops$"])
|
|
||||||
|
|
||||||
def testAssertFalse(self):
|
|
||||||
self.assertMessages('assertFalse', (True,),
|
|
||||||
["^True is not False$", "^oops$", "^True is not False$",
|
|
||||||
"^True is not False : oops$"])
|
|
||||||
|
|
||||||
def testNotEqual(self):
|
|
||||||
self.assertMessages('assertNotEqual', (1, 1),
|
|
||||||
["^1 == 1$", "^oops$", "^1 == 1$",
|
|
||||||
"^1 == 1 : oops$"])
|
|
||||||
|
|
||||||
def testAlmostEqual(self):
|
|
||||||
self.assertMessages('assertAlmostEqual', (1, 2),
|
|
||||||
["^1 != 2 within 7 places$", "^oops$",
|
|
||||||
"^1 != 2 within 7 places$", "^1 != 2 within 7 places : oops$"])
|
|
||||||
|
|
||||||
def testNotAlmostEqual(self):
|
|
||||||
self.assertMessages('assertNotAlmostEqual', (1, 1),
|
|
||||||
["^1 == 1 within 7 places$", "^oops$",
|
|
||||||
"^1 == 1 within 7 places$", "^1 == 1 within 7 places : oops$"])
|
|
||||||
|
|
||||||
def test_baseAssertEqual(self):
|
|
||||||
self.assertMessages('_baseAssertEqual', (1, 2),
|
|
||||||
["^1 != 2$", "^oops$", "^1 != 2$", "^1 != 2 : oops$"])
|
|
||||||
|
|
||||||
def testAssertSequenceEqual(self):
|
|
||||||
# Error messages are multiline so not testing on full message
|
|
||||||
# assertTupleEqual and assertListEqual delegate to this method
|
|
||||||
self.assertMessages('assertSequenceEqual', ([], [None]),
|
|
||||||
["\+ \[None\]$", "^oops$", r"\+ \[None\]$",
|
|
||||||
r"\+ \[None\] : oops$"])
|
|
||||||
|
|
||||||
def testAssertSetEqual(self):
|
|
||||||
self.assertMessages('assertSetEqual', (set(), set([None])),
|
|
||||||
["None$", "^oops$", "None$",
|
|
||||||
"None : oops$"])
|
|
||||||
|
|
||||||
def testAssertIn(self):
|
|
||||||
self.assertMessages('assertIn', (None, []),
|
|
||||||
['^None not found in \[\]$', "^oops$",
|
|
||||||
'^None not found in \[\]$',
|
|
||||||
'^None not found in \[\] : oops$'])
|
|
||||||
|
|
||||||
def testAssertNotIn(self):
|
|
||||||
self.assertMessages('assertNotIn', (None, [None]),
|
|
||||||
['^None unexpectedly found in \[None\]$', "^oops$",
|
|
||||||
'^None unexpectedly found in \[None\]$',
|
|
||||||
'^None unexpectedly found in \[None\] : oops$'])
|
|
||||||
|
|
||||||
def testAssertDictEqual(self):
|
|
||||||
self.assertMessages('assertDictEqual', ({}, {'key': 'value'}),
|
|
||||||
[r"\+ \{'key': 'value'\}$", "^oops$",
|
|
||||||
"\+ \{'key': 'value'\}$",
|
|
||||||
"\+ \{'key': 'value'\} : oops$"])
|
|
||||||
|
|
||||||
def testAssertDictContainsSubset(self):
|
|
||||||
self.assertMessages('assertDictContainsSubset', ({'key': 'value'}, {}),
|
|
||||||
["^Missing: 'key'$", "^oops$",
|
|
||||||
"^Missing: 'key'$",
|
|
||||||
"^Missing: 'key' : oops$"])
|
|
||||||
|
|
||||||
def testAssertItemsEqual(self):
|
|
||||||
self.assertMessages('assertItemsEqual', ([], [None]),
|
|
||||||
[r"\[None\]$", "^oops$",
|
|
||||||
r"\[None\]$",
|
|
||||||
r"\[None\] : oops$"])
|
|
||||||
|
|
||||||
def testAssertMultiLineEqual(self):
|
|
||||||
self.assertMessages('assertMultiLineEqual', ("", "foo"),
|
|
||||||
[r"\+ foo$", "^oops$",
|
|
||||||
r"\+ foo$",
|
|
||||||
r"\+ foo : oops$"])
|
|
||||||
|
|
||||||
def testAssertLess(self):
|
|
||||||
self.assertMessages('assertLess', (2, 1),
|
|
||||||
["^2 not less than 1$", "^oops$",
|
|
||||||
"^2 not less than 1$", "^2 not less than 1 : oops$"])
|
|
||||||
|
|
||||||
def testAssertLessEqual(self):
|
|
||||||
self.assertMessages('assertLessEqual', (2, 1),
|
|
||||||
["^2 not less than or equal to 1$", "^oops$",
|
|
||||||
"^2 not less than or equal to 1$",
|
|
||||||
"^2 not less than or equal to 1 : oops$"])
|
|
||||||
|
|
||||||
def testAssertGreater(self):
|
|
||||||
self.assertMessages('assertGreater', (1, 2),
|
|
||||||
["^1 not greater than 2$", "^oops$",
|
|
||||||
"^1 not greater than 2$",
|
|
||||||
"^1 not greater than 2 : oops$"])
|
|
||||||
|
|
||||||
def testAssertGreaterEqual(self):
|
|
||||||
self.assertMessages('assertGreaterEqual', (1, 2),
|
|
||||||
["^1 not greater than or equal to 2$", "^oops$",
|
|
||||||
"^1 not greater than or equal to 2$",
|
|
||||||
"^1 not greater than or equal to 2 : oops$"])
|
|
||||||
|
|
||||||
def testAssertIsNone(self):
|
|
||||||
self.assertMessages('assertIsNone', ('not None',),
|
|
||||||
["^'not None' is not None$", "^oops$",
|
|
||||||
"^'not None' is not None$",
|
|
||||||
"^'not None' is not None : oops$"])
|
|
||||||
|
|
||||||
def testAssertIsNotNone(self):
|
|
||||||
self.assertMessages('assertIsNotNone', (None,),
|
|
||||||
["^unexpectedly None$", "^oops$",
|
|
||||||
"^unexpectedly None$",
|
|
||||||
"^unexpectedly None : oops$"])
|
|
||||||
|
|
||||||
def testAssertIs(self):
|
|
||||||
self.assertMessages('assertIs', (None, 'foo'),
|
|
||||||
["^None is not 'foo'$", "^oops$",
|
|
||||||
"^None is not 'foo'$",
|
|
||||||
"^None is not 'foo' : oops$"])
|
|
||||||
|
|
||||||
def testAssertIsNot(self):
|
|
||||||
self.assertMessages('assertIsNot', (None, None),
|
|
||||||
["^unexpectedly identical: None$", "^oops$",
|
|
||||||
"^unexpectedly identical: None$",
|
|
||||||
"^unexpectedly identical: None : oops$"])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,260 +0,0 @@
|
||||||
import gc
|
|
||||||
import os
|
|
||||||
import weakref
|
|
||||||
|
|
||||||
from cStringIO import StringIO
|
|
||||||
|
|
||||||
try:
|
|
||||||
import signal
|
|
||||||
except ImportError:
|
|
||||||
signal = None
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
|
|
||||||
class TestBreak(unittest2.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._default_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
signal.signal(signal.SIGINT, self._default_handler)
|
|
||||||
unittest2.signals._results = weakref.WeakKeyDictionary()
|
|
||||||
unittest2.signals._interrupt_handler = None
|
|
||||||
|
|
||||||
|
|
||||||
def testInstallHandler(self):
|
|
||||||
default_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
unittest2.installHandler()
|
|
||||||
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
try:
|
|
||||||
pid = os.getpid()
|
|
||||||
os.kill(pid, signal.SIGINT)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.fail("KeyboardInterrupt not handled")
|
|
||||||
|
|
||||||
self.assertTrue(unittest2.signals._interrupt_handler.called)
|
|
||||||
|
|
||||||
def testRegisterResult(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
unittest2.registerResult(result)
|
|
||||||
|
|
||||||
for ref in unittest2.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")
|
|
||||||
|
|
||||||
|
|
||||||
def testInterruptCaught(self):
|
|
||||||
default_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
unittest2.installHandler()
|
|
||||||
unittest2.registerResult(result)
|
|
||||||
|
|
||||||
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
def test(result):
|
|
||||||
pid = os.getpid()
|
|
||||||
os.kill(pid, signal.SIGINT)
|
|
||||||
result.breakCaught = True
|
|
||||||
self.assertTrue(result.shouldStop)
|
|
||||||
|
|
||||||
try:
|
|
||||||
test(result)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.fail("KeyboardInterrupt not handled")
|
|
||||||
self.assertTrue(result.breakCaught)
|
|
||||||
|
|
||||||
|
|
||||||
def testSecondInterrupt(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
unittest2.installHandler()
|
|
||||||
unittest2.registerResult(result)
|
|
||||||
|
|
||||||
def test(result):
|
|
||||||
pid = os.getpid()
|
|
||||||
os.kill(pid, signal.SIGINT)
|
|
||||||
result.breakCaught = True
|
|
||||||
self.assertTrue(result.shouldStop)
|
|
||||||
os.kill(pid, signal.SIGINT)
|
|
||||||
self.fail("Second KeyboardInterrupt not raised")
|
|
||||||
|
|
||||||
try:
|
|
||||||
test(result)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("Second KeyboardInterrupt not raised")
|
|
||||||
self.assertTrue(result.breakCaught)
|
|
||||||
|
|
||||||
|
|
||||||
def testTwoResults(self):
|
|
||||||
unittest2.installHandler()
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
unittest2.registerResult(result)
|
|
||||||
new_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
|
|
||||||
result2 = unittest2.TestResult()
|
|
||||||
unittest2.registerResult(result2)
|
|
||||||
self.assertEqual(signal.getsignal(signal.SIGINT), new_handler)
|
|
||||||
|
|
||||||
result3 = unittest2.TestResult()
|
|
||||||
|
|
||||||
def test(result):
|
|
||||||
pid = os.getpid()
|
|
||||||
os.kill(pid, signal.SIGINT)
|
|
||||||
|
|
||||||
try:
|
|
||||||
test(result)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.fail("KeyboardInterrupt not handled")
|
|
||||||
|
|
||||||
self.assertTrue(result.shouldStop)
|
|
||||||
self.assertTrue(result2.shouldStop)
|
|
||||||
self.assertFalse(result3.shouldStop)
|
|
||||||
|
|
||||||
|
|
||||||
def testHandlerReplacedButCalled(self):
|
|
||||||
# If our handler has been replaced (is no longer installed) but is
|
|
||||||
# called by the *new* handler, then it isn't safe to delay the
|
|
||||||
# SIGINT and we should immediately delegate to the default handler
|
|
||||||
unittest2.installHandler()
|
|
||||||
|
|
||||||
handler = signal.getsignal(signal.SIGINT)
|
|
||||||
def new_handler(frame, signum):
|
|
||||||
handler(frame, signum)
|
|
||||||
signal.signal(signal.SIGINT, new_handler)
|
|
||||||
|
|
||||||
try:
|
|
||||||
pid = os.getpid()
|
|
||||||
os.kill(pid, signal.SIGINT)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("replaced but delegated handler doesn't raise interrupt")
|
|
||||||
|
|
||||||
def testRunner(self):
|
|
||||||
# Creating a TextTestRunner with the appropriate argument should
|
|
||||||
# register the TextTestResult it creates
|
|
||||||
runner = unittest2.TextTestRunner(stream=StringIO())
|
|
||||||
|
|
||||||
result = runner.run(unittest2.TestSuite())
|
|
||||||
self.assertIn(result, unittest2.signals._results)
|
|
||||||
|
|
||||||
def testWeakReferences(self):
|
|
||||||
# Calling registerResult on a result should not keep it alive
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
unittest2.registerResult(result)
|
|
||||||
|
|
||||||
ref = weakref.ref(result)
|
|
||||||
del result
|
|
||||||
|
|
||||||
# For non-reference counting implementations
|
|
||||||
gc.collect();gc.collect()
|
|
||||||
self.assertIsNone(ref())
|
|
||||||
|
|
||||||
|
|
||||||
def testRemoveResult(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
unittest2.registerResult(result)
|
|
||||||
|
|
||||||
unittest2.installHandler()
|
|
||||||
self.assertTrue(unittest2.removeResult(result))
|
|
||||||
|
|
||||||
# Should this raise an error instead?
|
|
||||||
self.assertFalse(unittest2.removeResult(unittest2.TestResult()))
|
|
||||||
|
|
||||||
try:
|
|
||||||
pid = os.getpid()
|
|
||||||
os.kill(pid, signal.SIGINT)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.assertFalse(result.shouldStop)
|
|
||||||
|
|
||||||
def testMainInstallsHandler(self):
|
|
||||||
failfast = object()
|
|
||||||
test = object()
|
|
||||||
verbosity = object()
|
|
||||||
result = object()
|
|
||||||
default_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
|
|
||||||
class FakeRunner(object):
|
|
||||||
initArgs = []
|
|
||||||
runArgs = []
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.initArgs.append((args, kwargs))
|
|
||||||
def run(self, test):
|
|
||||||
self.runArgs.append(test)
|
|
||||||
return result
|
|
||||||
|
|
||||||
class Program(unittest2.TestProgram):
|
|
||||||
def __init__(self, catchbreak):
|
|
||||||
self.exit = False
|
|
||||||
self.verbosity = verbosity
|
|
||||||
self.failfast = failfast
|
|
||||||
self.catchbreak = catchbreak
|
|
||||||
self.testRunner = FakeRunner
|
|
||||||
self.test = test
|
|
||||||
self.result = None
|
|
||||||
|
|
||||||
p = Program(False)
|
|
||||||
p.runTests()
|
|
||||||
|
|
||||||
self.assertEqual(FakeRunner.initArgs, [((), {'verbosity': verbosity,
|
|
||||||
'failfast': failfast,
|
|
||||||
'buffer': None})])
|
|
||||||
self.assertEqual(FakeRunner.runArgs, [test])
|
|
||||||
self.assertEqual(p.result, result)
|
|
||||||
|
|
||||||
self.assertEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
FakeRunner.initArgs = []
|
|
||||||
FakeRunner.runArgs = []
|
|
||||||
p = Program(True)
|
|
||||||
p.runTests()
|
|
||||||
|
|
||||||
self.assertEqual(FakeRunner.initArgs, [((), {'verbosity': verbosity,
|
|
||||||
'failfast': failfast,
|
|
||||||
'buffer': None})])
|
|
||||||
self.assertEqual(FakeRunner.runArgs, [test])
|
|
||||||
self.assertEqual(p.result, result)
|
|
||||||
|
|
||||||
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
|
|
||||||
def testRemoveHandler(self):
|
|
||||||
default_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
unittest2.installHandler()
|
|
||||||
unittest2.removeHandler()
|
|
||||||
self.assertEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
# check that calling removeHandler multiple times has no ill-effect
|
|
||||||
unittest2.removeHandler()
|
|
||||||
self.assertEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
def testRemoveHandlerAsDecorator(self):
|
|
||||||
default_handler = signal.getsignal(signal.SIGINT)
|
|
||||||
unittest2.installHandler()
|
|
||||||
|
|
||||||
@unittest2.removeHandler
|
|
||||||
def test():
|
|
||||||
self.assertEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
test()
|
|
||||||
self.assertNotEqual(signal.getsignal(signal.SIGINT), default_handler)
|
|
||||||
|
|
||||||
|
|
||||||
# Should also skip some tests on Jython
|
|
||||||
skipper = unittest2.skipUnless(hasattr(os, 'kill') and signal is not None,
|
|
||||||
"test uses os.kill(...) and the signal module")
|
|
||||||
TestBreak = skipper(TestBreak)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,371 +0,0 @@
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
|
|
||||||
class TestDiscovery(unittest2.TestCase):
|
|
||||||
|
|
||||||
# Heavily mocked tests so I can avoid hitting the filesystem
|
|
||||||
def test_get_name_from_path(self):
|
|
||||||
loader = unittest2.TestLoader()
|
|
||||||
|
|
||||||
loader._top_level_dir = '/foo'
|
|
||||||
name = loader._get_name_from_path('/foo/bar/baz.py')
|
|
||||||
self.assertEqual(name, 'bar.baz')
|
|
||||||
|
|
||||||
if not __debug__:
|
|
||||||
# asserts are off
|
|
||||||
return
|
|
||||||
|
|
||||||
self.assertRaises(AssertionError,
|
|
||||||
loader._get_name_from_path,
|
|
||||||
'/bar/baz.py')
|
|
||||||
|
|
||||||
def test_find_tests(self):
|
|
||||||
loader = unittest2.TestLoader()
|
|
||||||
|
|
||||||
original_listdir = os.listdir
|
|
||||||
def restore_listdir():
|
|
||||||
os.listdir = original_listdir
|
|
||||||
original_isfile = os.path.isfile
|
|
||||||
def restore_isfile():
|
|
||||||
os.path.isfile = original_isfile
|
|
||||||
original_isdir = os.path.isdir
|
|
||||||
def restore_isdir():
|
|
||||||
os.path.isdir = original_isdir
|
|
||||||
|
|
||||||
path_lists = [['test1.py', 'test2.py', 'not_a_test.py', 'test_dir',
|
|
||||||
'test.foo', 'test-not-a-module.py', 'another_dir'],
|
|
||||||
['test3.py', 'test4.py', ]]
|
|
||||||
os.listdir = lambda path: path_lists.pop(0)
|
|
||||||
self.addCleanup(restore_listdir)
|
|
||||||
|
|
||||||
def isdir(path):
|
|
||||||
return path.endswith('dir')
|
|
||||||
os.path.isdir = isdir
|
|
||||||
self.addCleanup(restore_isdir)
|
|
||||||
|
|
||||||
def isfile(path):
|
|
||||||
# another_dir is not a package and so shouldn't be recursed into
|
|
||||||
return not path.endswith('dir') and not 'another_dir' in path
|
|
||||||
os.path.isfile = isfile
|
|
||||||
self.addCleanup(restore_isfile)
|
|
||||||
|
|
||||||
loader._get_module_from_name = lambda path: path + ' module'
|
|
||||||
loader.loadTestsFromModule = lambda module: module + ' tests'
|
|
||||||
|
|
||||||
top_level = os.path.abspath('/foo')
|
|
||||||
loader._top_level_dir = top_level
|
|
||||||
suite = list(loader._find_tests(top_level, 'test*.py'))
|
|
||||||
|
|
||||||
expected = [name + ' module tests' for name in
|
|
||||||
('test1', 'test2')]
|
|
||||||
expected.extend([('test_dir.%s' % name) + ' module tests' for name in
|
|
||||||
('test3', 'test4')])
|
|
||||||
self.assertEqual(suite, expected)
|
|
||||||
|
|
||||||
def test_find_tests_with_package(self):
|
|
||||||
loader = unittest2.TestLoader()
|
|
||||||
|
|
||||||
original_listdir = os.listdir
|
|
||||||
def restore_listdir():
|
|
||||||
os.listdir = original_listdir
|
|
||||||
original_isfile = os.path.isfile
|
|
||||||
def restore_isfile():
|
|
||||||
os.path.isfile = original_isfile
|
|
||||||
original_isdir = os.path.isdir
|
|
||||||
def restore_isdir():
|
|
||||||
os.path.isdir = original_isdir
|
|
||||||
|
|
||||||
directories = ['a_directory', 'test_directory', 'test_directory2']
|
|
||||||
path_lists = [directories, [], [], []]
|
|
||||||
os.listdir = lambda path: path_lists.pop(0)
|
|
||||||
self.addCleanup(restore_listdir)
|
|
||||||
|
|
||||||
os.path.isdir = lambda path: True
|
|
||||||
self.addCleanup(restore_isdir)
|
|
||||||
|
|
||||||
os.path.isfile = lambda path: os.path.basename(path) not in directories
|
|
||||||
self.addCleanup(restore_isfile)
|
|
||||||
|
|
||||||
class Module(object):
|
|
||||||
paths = []
|
|
||||||
load_tests_args = []
|
|
||||||
|
|
||||||
def __init__(self, path):
|
|
||||||
self.path = path
|
|
||||||
self.paths.append(path)
|
|
||||||
if os.path.basename(path) == 'test_directory':
|
|
||||||
def load_tests(loader, tests, pattern):
|
|
||||||
self.load_tests_args.append((loader, tests, pattern))
|
|
||||||
return 'load_tests'
|
|
||||||
self.load_tests = load_tests
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self.path == other.path
|
|
||||||
|
|
||||||
# Silence py3k warning
|
|
||||||
__hash__ = None
|
|
||||||
|
|
||||||
loader._get_module_from_name = lambda name: Module(name)
|
|
||||||
def loadTestsFromModule(module, use_load_tests):
|
|
||||||
if use_load_tests:
|
|
||||||
raise self.failureException('use_load_tests should be False for packages')
|
|
||||||
return module.path + ' module tests'
|
|
||||||
loader.loadTestsFromModule = loadTestsFromModule
|
|
||||||
|
|
||||||
loader._top_level_dir = '/foo'
|
|
||||||
# this time no '.py' on the pattern so that it can match
|
|
||||||
# a test package
|
|
||||||
suite = list(loader._find_tests('/foo', 'test*'))
|
|
||||||
|
|
||||||
# We should have loaded tests from the test_directory package by calling load_tests
|
|
||||||
# and directly from the test_directory2 package
|
|
||||||
self.assertEqual(suite,
|
|
||||||
['load_tests', 'test_directory2' + ' module tests'])
|
|
||||||
self.assertEqual(Module.paths, ['test_directory', 'test_directory2'])
|
|
||||||
|
|
||||||
# load_tests should have been called once with loader, tests and pattern
|
|
||||||
self.assertEqual(Module.load_tests_args,
|
|
||||||
[(loader, 'test_directory' + ' module tests', 'test*')])
|
|
||||||
|
|
||||||
def test_discover(self):
|
|
||||||
loader = unittest2.TestLoader()
|
|
||||||
|
|
||||||
original_isfile = os.path.isfile
|
|
||||||
original_isdir = os.path.isdir
|
|
||||||
def restore_isfile():
|
|
||||||
os.path.isfile = original_isfile
|
|
||||||
|
|
||||||
os.path.isfile = lambda path: False
|
|
||||||
self.addCleanup(restore_isfile)
|
|
||||||
|
|
||||||
orig_sys_path = sys.path[:]
|
|
||||||
def restore_path():
|
|
||||||
sys.path[:] = orig_sys_path
|
|
||||||
self.addCleanup(restore_path)
|
|
||||||
|
|
||||||
full_path = os.path.abspath(os.path.normpath('/foo'))
|
|
||||||
self.assertRaises(ImportError,
|
|
||||||
loader.discover,
|
|
||||||
'/foo/bar', top_level_dir='/foo')
|
|
||||||
|
|
||||||
self.assertEqual(loader._top_level_dir, full_path)
|
|
||||||
self.assertIn(full_path, sys.path)
|
|
||||||
|
|
||||||
os.path.isfile = lambda path: True
|
|
||||||
os.path.isdir = lambda path: True
|
|
||||||
|
|
||||||
def restore_isdir():
|
|
||||||
os.path.isdir = original_isdir
|
|
||||||
self.addCleanup(restore_isdir)
|
|
||||||
|
|
||||||
_find_tests_args = []
|
|
||||||
def _find_tests(start_dir, pattern):
|
|
||||||
_find_tests_args.append((start_dir, pattern))
|
|
||||||
return ['tests']
|
|
||||||
loader._find_tests = _find_tests
|
|
||||||
loader.suiteClass = str
|
|
||||||
|
|
||||||
suite = loader.discover('/foo/bar/baz', 'pattern', '/foo/bar')
|
|
||||||
|
|
||||||
top_level_dir = os.path.abspath(os.path.normpath('/foo/bar'))
|
|
||||||
start_dir = os.path.abspath(os.path.normpath('/foo/bar/baz'))
|
|
||||||
self.assertEqual(suite, "['tests']")
|
|
||||||
self.assertEqual(loader._top_level_dir, top_level_dir)
|
|
||||||
self.assertEqual(_find_tests_args, [(start_dir, 'pattern')])
|
|
||||||
self.assertIn(top_level_dir, sys.path)
|
|
||||||
|
|
||||||
def test_discover_with_modules_that_fail_to_import(self):
|
|
||||||
loader = unittest2.TestLoader()
|
|
||||||
|
|
||||||
listdir = os.listdir
|
|
||||||
os.listdir = lambda _: ['test_this_does_not_exist.py']
|
|
||||||
isfile = os.path.isfile
|
|
||||||
os.path.isfile = lambda _: True
|
|
||||||
orig_sys_path = sys.path[:]
|
|
||||||
def restore():
|
|
||||||
os.path.isfile = isfile
|
|
||||||
os.listdir = listdir
|
|
||||||
sys.path[:] = orig_sys_path
|
|
||||||
self.addCleanup(restore)
|
|
||||||
|
|
||||||
suite = loader.discover('.')
|
|
||||||
self.assertIn(os.getcwd(), sys.path)
|
|
||||||
self.assertEqual(suite.countTestCases(), 1)
|
|
||||||
test = list(list(suite)[0])[0] # extract test from suite
|
|
||||||
|
|
||||||
self.assertRaises(ImportError,
|
|
||||||
lambda: test.test_this_does_not_exist())
|
|
||||||
|
|
||||||
def test_command_line_handling_parseArgs(self):
|
|
||||||
# Haha - take that uninstantiable class
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
|
|
||||||
args = []
|
|
||||||
def do_discovery(argv):
|
|
||||||
args.extend(argv)
|
|
||||||
program._do_discovery = do_discovery
|
|
||||||
program.parseArgs(['something', 'discover'])
|
|
||||||
self.assertEqual(args, [])
|
|
||||||
|
|
||||||
program.parseArgs(['something', 'discover', 'foo', 'bar'])
|
|
||||||
self.assertEqual(args, ['foo', 'bar'])
|
|
||||||
|
|
||||||
def test_command_line_handling_do_discovery_too_many_arguments(self):
|
|
||||||
class Stop(Exception):
|
|
||||||
pass
|
|
||||||
def usageExit():
|
|
||||||
raise Stop
|
|
||||||
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program.usageExit = usageExit
|
|
||||||
|
|
||||||
self.assertRaises(Stop,
|
|
||||||
# too many args
|
|
||||||
lambda: program._do_discovery(['one', 'two', 'three', 'four']))
|
|
||||||
|
|
||||||
|
|
||||||
def test_command_line_handling_do_discovery_calls_loader(self):
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
|
|
||||||
class Loader(object):
|
|
||||||
args = []
|
|
||||||
def discover(self, start_dir, pattern, top_level_dir):
|
|
||||||
self.args.append((start_dir, pattern, top_level_dir))
|
|
||||||
return 'tests'
|
|
||||||
|
|
||||||
program._do_discovery(['-v'], Loader=Loader)
|
|
||||||
self.assertEqual(program.verbosity, 2)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('.', 'test*.py', None)])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(['--verbose'], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('.', 'test*.py', None)])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery([], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('.', 'test*.py', None)])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(['fish'], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('fish', 'test*.py', None)])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(['fish', 'eggs'], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('fish', 'eggs', None)])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(['fish', 'eggs', 'ham'], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('fish', 'eggs', 'ham')])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(['-s', 'fish'], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('fish', 'test*.py', None)])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(['-t', 'fish'], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('.', 'test*.py', 'fish')])
|
|
||||||
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(['-p', 'fish'], Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('.', 'fish', None)])
|
|
||||||
self.assertFalse(program.failfast)
|
|
||||||
self.assertFalse(program.catchbreak)
|
|
||||||
|
|
||||||
args = ['-p', 'eggs', '-s', 'fish', '-v', '-f']
|
|
||||||
try:
|
|
||||||
import signal
|
|
||||||
except ImportError:
|
|
||||||
signal = None
|
|
||||||
else:
|
|
||||||
args.append('-c')
|
|
||||||
Loader.args = []
|
|
||||||
program = object.__new__(unittest2.TestProgram)
|
|
||||||
program._do_discovery(args, Loader=Loader)
|
|
||||||
self.assertEqual(program.test, 'tests')
|
|
||||||
self.assertEqual(Loader.args, [('fish', 'eggs', None)])
|
|
||||||
self.assertEqual(program.verbosity, 2)
|
|
||||||
self.assertTrue(program.failfast)
|
|
||||||
if signal is not None:
|
|
||||||
self.assertTrue(program.catchbreak)
|
|
||||||
|
|
||||||
def test_detect_module_clash(self):
|
|
||||||
class Module(object):
|
|
||||||
__file__ = 'bar/foo.py'
|
|
||||||
sys.modules['foo'] = Module
|
|
||||||
full_path = os.path.abspath('foo')
|
|
||||||
original_listdir = os.listdir
|
|
||||||
original_isfile = os.path.isfile
|
|
||||||
original_isdir = os.path.isdir
|
|
||||||
|
|
||||||
def cleanup():
|
|
||||||
os.listdir = original_listdir
|
|
||||||
os.path.isfile = original_isfile
|
|
||||||
os.path.isdir = original_isdir
|
|
||||||
del sys.modules['foo']
|
|
||||||
if full_path in sys.path:
|
|
||||||
sys.path.remove(full_path)
|
|
||||||
self.addCleanup(cleanup)
|
|
||||||
|
|
||||||
def listdir(_):
|
|
||||||
return ['foo.py']
|
|
||||||
def isfile(_):
|
|
||||||
return True
|
|
||||||
def isdir(_):
|
|
||||||
return True
|
|
||||||
os.listdir = listdir
|
|
||||||
os.path.isfile = isfile
|
|
||||||
os.path.isdir = isdir
|
|
||||||
|
|
||||||
loader = unittest2.TestLoader()
|
|
||||||
|
|
||||||
mod_dir = os.path.abspath('bar')
|
|
||||||
expected_dir = os.path.abspath('foo')
|
|
||||||
msg = re.escape(r"'foo' module incorrectly imported from %r. Expected %r. "
|
|
||||||
"Is this module globally installed?" % (mod_dir, expected_dir))
|
|
||||||
self.assertRaisesRegexp(
|
|
||||||
ImportError, '^%s$' % msg, loader.discover,
|
|
||||||
start_dir='foo', pattern='foo.py'
|
|
||||||
)
|
|
||||||
self.assertEqual(sys.path[0], full_path)
|
|
||||||
|
|
||||||
|
|
||||||
def test_discovery_from_dotted_path(self):
|
|
||||||
loader = unittest2.TestLoader()
|
|
||||||
|
|
||||||
tests = [self]
|
|
||||||
expectedPath = os.path.abspath(os.path.dirname(unittest2.test.__file__))
|
|
||||||
|
|
||||||
self.wasRun = False
|
|
||||||
def _find_tests(start_dir, pattern):
|
|
||||||
self.wasRun = True
|
|
||||||
self.assertEqual(start_dir, expectedPath)
|
|
||||||
return tests
|
|
||||||
loader._find_tests = _find_tests
|
|
||||||
suite = loader.discover('unittest2.test')
|
|
||||||
self.assertTrue(self.wasRun)
|
|
||||||
self.assertEqual(suite._tests, tests)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
import unittest2
|
|
||||||
|
|
||||||
from unittest2.test.support import LoggingResult
|
|
||||||
|
|
||||||
|
|
||||||
class Test_FunctionTestCase(unittest2.TestCase):
|
|
||||||
|
|
||||||
# "Return the number of tests represented by the this test object. For
|
|
||||||
# unittest2.TestCase instances, this will always be 1"
|
|
||||||
def test_countTestCases(self):
|
|
||||||
test = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
|
|
||||||
self.assertEqual(test.countTestCases(), 1)
|
|
||||||
|
|
||||||
# "When a setUp() method is defined, the test runner will run that method
|
|
||||||
# prior to each test. Likewise, if a tearDown() method is defined, the
|
|
||||||
# test runner will invoke that method after each test. In the example,
|
|
||||||
# setUp() was used to create a fresh sequence for each test."
|
|
||||||
#
|
|
||||||
# Make sure the proper call order is maintained, even if setUp() raises
|
|
||||||
# an exception.
|
|
||||||
def test_run_call_order__error_in_setUp(self):
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
|
|
||||||
def setUp():
|
|
||||||
events.append('setUp')
|
|
||||||
raise RuntimeError('raised by setUp')
|
|
||||||
|
|
||||||
def test():
|
|
||||||
events.append('test')
|
|
||||||
|
|
||||||
def tearDown():
|
|
||||||
events.append('tearDown')
|
|
||||||
|
|
||||||
expected = ['startTest', 'setUp', 'addError', 'stopTest']
|
|
||||||
unittest2.FunctionTestCase(test, setUp, tearDown).run(result)
|
|
||||||
self.assertEqual(events, expected)
|
|
||||||
|
|
||||||
# "When a setUp() method is defined, the test runner will run that method
|
|
||||||
# prior to each test. Likewise, if a tearDown() method is defined, the
|
|
||||||
# test runner will invoke that method after each test. In the example,
|
|
||||||
# setUp() was used to create a fresh sequence for each test."
|
|
||||||
#
|
|
||||||
# Make sure the proper call order is maintained, even if the test raises
|
|
||||||
# an error (as opposed to a failure).
|
|
||||||
def test_run_call_order__error_in_test(self):
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
|
|
||||||
def setUp():
|
|
||||||
events.append('setUp')
|
|
||||||
|
|
||||||
def test():
|
|
||||||
events.append('test')
|
|
||||||
raise RuntimeError('raised by test')
|
|
||||||
|
|
||||||
def tearDown():
|
|
||||||
events.append('tearDown')
|
|
||||||
|
|
||||||
expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown',
|
|
||||||
'stopTest']
|
|
||||||
unittest2.FunctionTestCase(test, setUp, tearDown).run(result)
|
|
||||||
self.assertEqual(events, expected)
|
|
||||||
|
|
||||||
# "When a setUp() method is defined, the test runner will run that method
|
|
||||||
# prior to each test. Likewise, if a tearDown() method is defined, the
|
|
||||||
# test runner will invoke that method after each test. In the example,
|
|
||||||
# setUp() was used to create a fresh sequence for each test."
|
|
||||||
#
|
|
||||||
# Make sure the proper call order is maintained, even if the test signals
|
|
||||||
# a failure (as opposed to an error).
|
|
||||||
def test_run_call_order__failure_in_test(self):
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
|
|
||||||
def setUp():
|
|
||||||
events.append('setUp')
|
|
||||||
|
|
||||||
def test():
|
|
||||||
events.append('test')
|
|
||||||
self.fail('raised by test')
|
|
||||||
|
|
||||||
def tearDown():
|
|
||||||
events.append('tearDown')
|
|
||||||
|
|
||||||
expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown',
|
|
||||||
'stopTest']
|
|
||||||
unittest2.FunctionTestCase(test, setUp, tearDown).run(result)
|
|
||||||
self.assertEqual(events, expected)
|
|
||||||
|
|
||||||
# "When a setUp() method is defined, the test runner will run that method
|
|
||||||
# prior to each test. Likewise, if a tearDown() method is defined, the
|
|
||||||
# test runner will invoke that method after each test. In the example,
|
|
||||||
# setUp() was used to create a fresh sequence for each test."
|
|
||||||
#
|
|
||||||
# Make sure the proper call order is maintained, even if tearDown() raises
|
|
||||||
# an exception.
|
|
||||||
def test_run_call_order__error_in_tearDown(self):
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
|
|
||||||
def setUp():
|
|
||||||
events.append('setUp')
|
|
||||||
|
|
||||||
def test():
|
|
||||||
events.append('test')
|
|
||||||
|
|
||||||
def tearDown():
|
|
||||||
events.append('tearDown')
|
|
||||||
raise RuntimeError('raised by tearDown')
|
|
||||||
|
|
||||||
expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError',
|
|
||||||
'stopTest']
|
|
||||||
unittest2.FunctionTestCase(test, setUp, tearDown).run(result)
|
|
||||||
self.assertEqual(events, expected)
|
|
||||||
|
|
||||||
# "Return a string identifying the specific test case."
|
|
||||||
#
|
|
||||||
# Because of the vague nature of the docs, I'm not going to lock this
|
|
||||||
# test down too much. Really all that can be asserted is that the id()
|
|
||||||
# will be a string (either 8-byte or unicode -- again, because the docs
|
|
||||||
# just say "string")
|
|
||||||
def test_id(self):
|
|
||||||
test = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
|
|
||||||
self.assertIsInstance(test.id(), basestring)
|
|
||||||
|
|
||||||
# "Returns a one-line description of the test, or None if no description
|
|
||||||
# has been provided. The default implementation of this method returns
|
|
||||||
# the first line of the test method's docstring, if available, or None."
|
|
||||||
def test_shortDescription__no_docstring(self):
|
|
||||||
test = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
|
|
||||||
self.assertEqual(test.shortDescription(), None)
|
|
||||||
|
|
||||||
# "Returns a one-line description of the test, or None if no description
|
|
||||||
# has been provided. The default implementation of this method returns
|
|
||||||
# the first line of the test method's docstring, if available, or None."
|
|
||||||
def test_shortDescription__singleline_docstring(self):
|
|
||||||
desc = "this tests foo"
|
|
||||||
test = unittest2.FunctionTestCase(lambda: None, description=desc)
|
|
||||||
|
|
||||||
self.assertEqual(test.shortDescription(), "this tests foo")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,46 +0,0 @@
|
||||||
from cStringIO import StringIO
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
from unittest2.test.support import resultFactory
|
|
||||||
|
|
||||||
|
|
||||||
class TestUnittest(unittest2.TestCase):
|
|
||||||
|
|
||||||
def assertIsSubclass(self, actual, klass):
|
|
||||||
self.assertTrue(issubclass(actual, klass), "Not a subclass.")
|
|
||||||
|
|
||||||
def testInheritance(self):
|
|
||||||
self.assertIsSubclass(unittest2.TestCase, unittest.TestCase)
|
|
||||||
self.assertIsSubclass(unittest2.TestResult, unittest.TestResult)
|
|
||||||
self.assertIsSubclass(unittest2.TestSuite, unittest.TestSuite)
|
|
||||||
self.assertIsSubclass(unittest2.TextTestRunner, unittest.TextTestRunner)
|
|
||||||
self.assertIsSubclass(unittest2.TestLoader, unittest.TestLoader)
|
|
||||||
self.assertIsSubclass(unittest2.TextTestResult, unittest.TestResult)
|
|
||||||
|
|
||||||
def test_new_runner_old_case(self):
|
|
||||||
runner = unittest2.TextTestRunner(resultclass=resultFactory,
|
|
||||||
stream=StringIO())
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
def testOne(self):
|
|
||||||
pass
|
|
||||||
suite = unittest2.TestSuite((Test('testOne'),))
|
|
||||||
result = runner.run(suite)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
def test_old_runner_new_case(self):
|
|
||||||
runner = unittest.TextTestRunner(stream=StringIO())
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def testOne(self):
|
|
||||||
self.assertDictEqual({}, {})
|
|
||||||
|
|
||||||
suite = unittest.TestSuite((Test('testOne'),))
|
|
||||||
result = runner.run(suite)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,239 +0,0 @@
|
||||||
from cStringIO import StringIO
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
hasInstallHandler = hasattr(unittest2, 'installHandler')
|
|
||||||
|
|
||||||
class Test_TestProgram(unittest2.TestCase):
|
|
||||||
|
|
||||||
# Horrible white box test
|
|
||||||
def testNoExit(self):
|
|
||||||
result = object()
|
|
||||||
test = object()
|
|
||||||
|
|
||||||
class FakeRunner(object):
|
|
||||||
def run(self, test):
|
|
||||||
self.test = test
|
|
||||||
return result
|
|
||||||
|
|
||||||
runner = FakeRunner()
|
|
||||||
|
|
||||||
oldParseArgs = unittest2.TestProgram.parseArgs
|
|
||||||
def restoreParseArgs():
|
|
||||||
unittest2.TestProgram.parseArgs = oldParseArgs
|
|
||||||
unittest2.TestProgram.parseArgs = lambda *args: None
|
|
||||||
self.addCleanup(restoreParseArgs)
|
|
||||||
|
|
||||||
def removeTest():
|
|
||||||
del unittest2.TestProgram.test
|
|
||||||
unittest2.TestProgram.test = test
|
|
||||||
self.addCleanup(removeTest)
|
|
||||||
|
|
||||||
program = unittest2.TestProgram(testRunner=runner, exit=False, verbosity=2)
|
|
||||||
|
|
||||||
self.assertEqual(program.result, result)
|
|
||||||
self.assertEqual(runner.test, test)
|
|
||||||
self.assertEqual(program.verbosity, 2)
|
|
||||||
|
|
||||||
class FooBar(unittest2.TestCase):
|
|
||||||
def testPass(self):
|
|
||||||
assert True
|
|
||||||
def testFail(self):
|
|
||||||
assert False
|
|
||||||
|
|
||||||
class FooBarLoader(unittest2.TestLoader):
|
|
||||||
"""Test loader that returns a suite containing FooBar."""
|
|
||||||
def loadTestsFromModule(self, module):
|
|
||||||
return self.suiteClass(
|
|
||||||
[self.loadTestsFromTestCase(Test_TestProgram.FooBar)])
|
|
||||||
|
|
||||||
|
|
||||||
def test_NonExit(self):
|
|
||||||
program = unittest2.main(exit=False,
|
|
||||||
argv=["foobar"],
|
|
||||||
testRunner=unittest2.TextTestRunner(stream=StringIO()),
|
|
||||||
testLoader=self.FooBarLoader())
|
|
||||||
self.assertTrue(hasattr(program, 'result'))
|
|
||||||
|
|
||||||
|
|
||||||
def test_Exit(self):
|
|
||||||
self.assertRaises(
|
|
||||||
SystemExit,
|
|
||||||
unittest2.main,
|
|
||||||
argv=["foobar"],
|
|
||||||
testRunner=unittest2.TextTestRunner(stream=StringIO()),
|
|
||||||
exit=True,
|
|
||||||
testLoader=self.FooBarLoader())
|
|
||||||
|
|
||||||
|
|
||||||
def test_ExitAsDefault(self):
|
|
||||||
self.assertRaises(
|
|
||||||
SystemExit,
|
|
||||||
unittest2.main,
|
|
||||||
argv=["foobar"],
|
|
||||||
testRunner=unittest2.TextTestRunner(stream=StringIO()),
|
|
||||||
testLoader=self.FooBarLoader())
|
|
||||||
|
|
||||||
|
|
||||||
class InitialisableProgram(unittest2.TestProgram):
|
|
||||||
exit = False
|
|
||||||
result = None
|
|
||||||
verbosity = 1
|
|
||||||
defaultTest = None
|
|
||||||
testRunner = None
|
|
||||||
testLoader = unittest2.defaultTestLoader
|
|
||||||
progName = 'test'
|
|
||||||
test = 'test'
|
|
||||||
def __init__(self, *args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
RESULT = object()
|
|
||||||
|
|
||||||
class FakeRunner(object):
|
|
||||||
initArgs = None
|
|
||||||
test = None
|
|
||||||
raiseError = False
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
FakeRunner.initArgs = kwargs
|
|
||||||
if FakeRunner.raiseError:
|
|
||||||
FakeRunner.raiseError = False
|
|
||||||
raise TypeError
|
|
||||||
|
|
||||||
def run(self, test):
|
|
||||||
FakeRunner.test = test
|
|
||||||
return RESULT
|
|
||||||
|
|
||||||
class TestCommandLineArgs(unittest2.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.program = InitialisableProgram()
|
|
||||||
self.program.createTests = lambda: None
|
|
||||||
FakeRunner.initArgs = None
|
|
||||||
FakeRunner.test = None
|
|
||||||
FakeRunner.raiseError = False
|
|
||||||
|
|
||||||
def testHelpAndUnknown(self):
|
|
||||||
program = self.program
|
|
||||||
def usageExit(msg=None):
|
|
||||||
program.msg = msg
|
|
||||||
program.exit = True
|
|
||||||
program.usageExit = usageExit
|
|
||||||
|
|
||||||
for opt in '-h', '-H', '--help':
|
|
||||||
program.exit = False
|
|
||||||
program.parseArgs([None, opt])
|
|
||||||
self.assertTrue(program.exit)
|
|
||||||
self.assertIsNone(program.msg)
|
|
||||||
|
|
||||||
program.parseArgs([None, '-$'])
|
|
||||||
self.assertTrue(program.exit)
|
|
||||||
self.assertIsNotNone(program.msg)
|
|
||||||
|
|
||||||
def testVerbosity(self):
|
|
||||||
program = self.program
|
|
||||||
|
|
||||||
for opt in '-q', '--quiet':
|
|
||||||
program.verbosity = 1
|
|
||||||
program.parseArgs([None, opt])
|
|
||||||
self.assertEqual(program.verbosity, 0)
|
|
||||||
|
|
||||||
for opt in '-v', '--verbose':
|
|
||||||
program.verbosity = 1
|
|
||||||
program.parseArgs([None, opt])
|
|
||||||
self.assertEqual(program.verbosity, 2)
|
|
||||||
|
|
||||||
def testBufferCatchFailfast(self):
|
|
||||||
program = self.program
|
|
||||||
for arg, attr in (('buffer', 'buffer'), ('failfast', 'failfast'),
|
|
||||||
('catch', 'catchbreak')):
|
|
||||||
if attr == 'catch' and not hasInstallHandler:
|
|
||||||
continue
|
|
||||||
|
|
||||||
short_opt = '-%s' % arg[0]
|
|
||||||
long_opt = '--%s' % arg
|
|
||||||
for opt in short_opt, long_opt:
|
|
||||||
setattr(program, attr, None)
|
|
||||||
|
|
||||||
program.parseArgs([None, opt])
|
|
||||||
self.assertTrue(getattr(program, attr))
|
|
||||||
|
|
||||||
for opt in short_opt, long_opt:
|
|
||||||
not_none = object()
|
|
||||||
setattr(program, attr, not_none)
|
|
||||||
|
|
||||||
program.parseArgs([None, opt])
|
|
||||||
self.assertEqual(getattr(program, attr), not_none)
|
|
||||||
|
|
||||||
def testRunTestsRunnerClass(self):
|
|
||||||
program = self.program
|
|
||||||
|
|
||||||
program.testRunner = FakeRunner
|
|
||||||
program.verbosity = 'verbosity'
|
|
||||||
program.failfast = 'failfast'
|
|
||||||
program.buffer = 'buffer'
|
|
||||||
|
|
||||||
program.runTests()
|
|
||||||
|
|
||||||
self.assertEqual(FakeRunner.initArgs, {'verbosity': 'verbosity',
|
|
||||||
'failfast': 'failfast',
|
|
||||||
'buffer': 'buffer'})
|
|
||||||
self.assertEqual(FakeRunner.test, 'test')
|
|
||||||
self.assertIs(program.result, RESULT)
|
|
||||||
|
|
||||||
def testRunTestsRunnerInstance(self):
|
|
||||||
program = self.program
|
|
||||||
|
|
||||||
program.testRunner = FakeRunner()
|
|
||||||
FakeRunner.initArgs = None
|
|
||||||
|
|
||||||
program.runTests()
|
|
||||||
|
|
||||||
# A new FakeRunner should not have been instantiated
|
|
||||||
self.assertIsNone(FakeRunner.initArgs)
|
|
||||||
|
|
||||||
self.assertEqual(FakeRunner.test, 'test')
|
|
||||||
self.assertIs(program.result, RESULT)
|
|
||||||
|
|
||||||
def testRunTestsOldRunnerClass(self):
|
|
||||||
program = self.program
|
|
||||||
|
|
||||||
FakeRunner.raiseError = True
|
|
||||||
program.testRunner = FakeRunner
|
|
||||||
program.verbosity = 'verbosity'
|
|
||||||
program.failfast = 'failfast'
|
|
||||||
program.buffer = 'buffer'
|
|
||||||
program.test = 'test'
|
|
||||||
|
|
||||||
program.runTests()
|
|
||||||
|
|
||||||
# If initialising raises a type error it should be retried
|
|
||||||
# without the new keyword arguments
|
|
||||||
self.assertEqual(FakeRunner.initArgs, {})
|
|
||||||
self.assertEqual(FakeRunner.test, 'test')
|
|
||||||
self.assertIs(program.result, RESULT)
|
|
||||||
|
|
||||||
def testCatchBreakInstallsHandler(self):
|
|
||||||
module = sys.modules['unittest2.main']
|
|
||||||
original = module.installHandler
|
|
||||||
def restore():
|
|
||||||
module.installHandler = original
|
|
||||||
self.addCleanup(restore)
|
|
||||||
|
|
||||||
self.installed = False
|
|
||||||
def fakeInstallHandler():
|
|
||||||
self.installed = True
|
|
||||||
module.installHandler = fakeInstallHandler
|
|
||||||
|
|
||||||
program = self.program
|
|
||||||
program.catchbreak = True
|
|
||||||
|
|
||||||
program.testRunner = FakeRunner
|
|
||||||
|
|
||||||
program.runTests()
|
|
||||||
self.assertTrue(self.installed)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,416 +0,0 @@
|
||||||
import sys
|
|
||||||
import textwrap
|
|
||||||
from StringIO import StringIO
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
|
|
||||||
class Test_TestResult(unittest2.TestCase):
|
|
||||||
# Note: there are not separate tests for TestResult.wasSuccessful(),
|
|
||||||
# TestResult.errors, TestResult.failures, TestResult.testsRun or
|
|
||||||
# TestResult.shouldStop because these only have meaning in terms of
|
|
||||||
# other TestResult methods.
|
|
||||||
#
|
|
||||||
# Accordingly, tests for the aforenamed attributes are incorporated
|
|
||||||
# in with the tests for the defining methods.
|
|
||||||
################################################################
|
|
||||||
|
|
||||||
def test_init(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.failures), 0)
|
|
||||||
self.assertEqual(result.testsRun, 0)
|
|
||||||
self.assertEqual(result.shouldStop, False)
|
|
||||||
self.assertIsNone(result._stdout_buffer)
|
|
||||||
self.assertIsNone(result._stderr_buffer)
|
|
||||||
|
|
||||||
# "This method can be called to signal that the set of tests being
|
|
||||||
# run should be aborted by setting the TestResult's shouldStop
|
|
||||||
# attribute to True."
|
|
||||||
def test_stop(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
|
|
||||||
result.stop()
|
|
||||||
|
|
||||||
self.assertEqual(result.shouldStop, True)
|
|
||||||
|
|
||||||
# "Called when the test case test is about to be run. The default
|
|
||||||
# implementation simply increments the instance's testsRun counter."
|
|
||||||
def test_startTest(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
test = Foo('test_1')
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
|
|
||||||
result.startTest(test)
|
|
||||||
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.failures), 0)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(result.shouldStop, False)
|
|
||||||
|
|
||||||
result.stopTest(test)
|
|
||||||
|
|
||||||
# "Called after the test case test has been executed, regardless of
|
|
||||||
# the outcome. The default implementation does nothing."
|
|
||||||
def test_stopTest(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
test = Foo('test_1')
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
|
|
||||||
result.startTest(test)
|
|
||||||
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.failures), 0)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(result.shouldStop, False)
|
|
||||||
|
|
||||||
result.stopTest(test)
|
|
||||||
|
|
||||||
# Same tests as above; make sure nothing has changed
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.failures), 0)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(result.shouldStop, False)
|
|
||||||
|
|
||||||
# "Called before and after tests are run. The default implementation does nothing."
|
|
||||||
def test_startTestRun_stopTestRun(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
result.startTestRun()
|
|
||||||
result.stopTestRun()
|
|
||||||
|
|
||||||
# "addSuccess(test)"
|
|
||||||
# ...
|
|
||||||
# "Called when the test case test succeeds"
|
|
||||||
# ...
|
|
||||||
# "wasSuccessful() - Returns True if all tests run so far have passed,
|
|
||||||
# otherwise returns False"
|
|
||||||
# ...
|
|
||||||
# "testsRun - The total number of tests run so far."
|
|
||||||
# ...
|
|
||||||
# "errors - A list containing 2-tuples of TestCase instances and
|
|
||||||
# formatted tracebacks. Each tuple represents a test which raised an
|
|
||||||
# unexpected exception. Contains formatted
|
|
||||||
# tracebacks instead of sys.exc_info() results."
|
|
||||||
# ...
|
|
||||||
# "failures - A list containing 2-tuples of TestCase instances and
|
|
||||||
# formatted tracebacks. Each tuple represents a test where a failure was
|
|
||||||
# explicitly signalled using the TestCase.fail*() or TestCase.assert*()
|
|
||||||
# methods. Contains formatted tracebacks instead
|
|
||||||
# of sys.exc_info() results."
|
|
||||||
def test_addSuccess(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
test = Foo('test_1')
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
|
|
||||||
result.startTest(test)
|
|
||||||
result.addSuccess(test)
|
|
||||||
result.stopTest(test)
|
|
||||||
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.failures), 0)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(result.shouldStop, False)
|
|
||||||
|
|
||||||
# "addFailure(test, err)"
|
|
||||||
# ...
|
|
||||||
# "Called when the test case test signals a failure. err is a tuple of
|
|
||||||
# the form returned by sys.exc_info(): (type, value, traceback)"
|
|
||||||
# ...
|
|
||||||
# "wasSuccessful() - Returns True if all tests run so far have passed,
|
|
||||||
# otherwise returns False"
|
|
||||||
# ...
|
|
||||||
# "testsRun - The total number of tests run so far."
|
|
||||||
# ...
|
|
||||||
# "errors - A list containing 2-tuples of TestCase instances and
|
|
||||||
# formatted tracebacks. Each tuple represents a test which raised an
|
|
||||||
# unexpected exception. Contains formatted
|
|
||||||
# tracebacks instead of sys.exc_info() results."
|
|
||||||
# ...
|
|
||||||
# "failures - A list containing 2-tuples of TestCase instances and
|
|
||||||
# formatted tracebacks. Each tuple represents a test where a failure was
|
|
||||||
# explicitly signalled using the TestCase.fail*() or TestCase.assert*()
|
|
||||||
# methods. Contains formatted tracebacks instead
|
|
||||||
# of sys.exc_info() results."
|
|
||||||
def test_addFailure(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
test = Foo('test_1')
|
|
||||||
try:
|
|
||||||
test.fail("foo")
|
|
||||||
except:
|
|
||||||
exc_info_tuple = sys.exc_info()
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
|
|
||||||
result.startTest(test)
|
|
||||||
result.addFailure(test, exc_info_tuple)
|
|
||||||
result.stopTest(test)
|
|
||||||
|
|
||||||
self.assertFalse(result.wasSuccessful())
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.failures), 1)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(result.shouldStop, False)
|
|
||||||
|
|
||||||
test_case, formatted_exc = result.failures[0]
|
|
||||||
self.assertTrue(test_case is test)
|
|
||||||
self.assertIsInstance(formatted_exc, str)
|
|
||||||
|
|
||||||
# "addError(test, err)"
|
|
||||||
# ...
|
|
||||||
# "Called when the test case test raises an unexpected exception err
|
|
||||||
# is a tuple of the form returned by sys.exc_info():
|
|
||||||
# (type, value, traceback)"
|
|
||||||
# ...
|
|
||||||
# "wasSuccessful() - Returns True if all tests run so far have passed,
|
|
||||||
# otherwise returns False"
|
|
||||||
# ...
|
|
||||||
# "testsRun - The total number of tests run so far."
|
|
||||||
# ...
|
|
||||||
# "errors - A list containing 2-tuples of TestCase instances and
|
|
||||||
# formatted tracebacks. Each tuple represents a test which raised an
|
|
||||||
# unexpected exception. Contains formatted
|
|
||||||
# tracebacks instead of sys.exc_info() results."
|
|
||||||
# ...
|
|
||||||
# "failures - A list containing 2-tuples of TestCase instances and
|
|
||||||
# formatted tracebacks. Each tuple represents a test where a failure was
|
|
||||||
# explicitly signalled using the TestCase.fail*() or TestCase.assert*()
|
|
||||||
# methods. Contains formatted tracebacks instead
|
|
||||||
# of sys.exc_info() results."
|
|
||||||
def test_addError(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
test = Foo('test_1')
|
|
||||||
try:
|
|
||||||
raise TypeError()
|
|
||||||
except:
|
|
||||||
exc_info_tuple = sys.exc_info()
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
|
|
||||||
result.startTest(test)
|
|
||||||
result.addError(test, exc_info_tuple)
|
|
||||||
result.stopTest(test)
|
|
||||||
|
|
||||||
self.assertFalse(result.wasSuccessful())
|
|
||||||
self.assertEqual(len(result.errors), 1)
|
|
||||||
self.assertEqual(len(result.failures), 0)
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
self.assertEqual(result.shouldStop, False)
|
|
||||||
|
|
||||||
test_case, formatted_exc = result.errors[0]
|
|
||||||
self.assertTrue(test_case is test)
|
|
||||||
self.assertIsInstance(formatted_exc, str)
|
|
||||||
|
|
||||||
def testGetDescriptionWithoutDocstring(self):
|
|
||||||
result = unittest2.TextTestResult(None, True, 1)
|
|
||||||
self.assertEqual(
|
|
||||||
result.getDescription(self),
|
|
||||||
'testGetDescriptionWithoutDocstring (' + __name__ +
|
|
||||||
'.Test_TestResult)')
|
|
||||||
|
|
||||||
def testGetDescriptionWithOneLineDocstring(self):
|
|
||||||
"""Tests getDescription() for a method with a docstring."""
|
|
||||||
result = unittest2.TextTestResult(None, True, 1)
|
|
||||||
self.assertEqual(
|
|
||||||
result.getDescription(self),
|
|
||||||
('testGetDescriptionWithOneLineDocstring '
|
|
||||||
'(' + __name__ + '.Test_TestResult)\n'
|
|
||||||
'Tests getDescription() for a method with a docstring.'))
|
|
||||||
|
|
||||||
def testGetDescriptionWithMultiLineDocstring(self):
|
|
||||||
"""Tests getDescription() for a method with a longer docstring.
|
|
||||||
The second line of the docstring.
|
|
||||||
"""
|
|
||||||
result = unittest2.TextTestResult(None, True, 1)
|
|
||||||
self.assertEqual(
|
|
||||||
result.getDescription(self),
|
|
||||||
('testGetDescriptionWithMultiLineDocstring '
|
|
||||||
'(' + __name__ + '.Test_TestResult)\n'
|
|
||||||
'Tests getDescription() for a method with a longer '
|
|
||||||
'docstring.'))
|
|
||||||
|
|
||||||
def testStackFrameTrimming(self):
|
|
||||||
class Frame(object):
|
|
||||||
class tb_frame(object):
|
|
||||||
f_globals = {}
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
self.assertFalse(result._is_relevant_tb_level(Frame))
|
|
||||||
|
|
||||||
Frame.tb_frame.f_globals['__unittest'] = True
|
|
||||||
self.assertTrue(result._is_relevant_tb_level(Frame))
|
|
||||||
|
|
||||||
def testFailFast(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
result._exc_info_to_string = lambda *_: ''
|
|
||||||
result.failfast = True
|
|
||||||
result.addError(None, None)
|
|
||||||
self.assertTrue(result.shouldStop)
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
result._exc_info_to_string = lambda *_: ''
|
|
||||||
result.failfast = True
|
|
||||||
result.addFailure(None, None)
|
|
||||||
self.assertTrue(result.shouldStop)
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
result._exc_info_to_string = lambda *_: ''
|
|
||||||
result.failfast = True
|
|
||||||
result.addUnexpectedSuccess(None)
|
|
||||||
self.assertTrue(result.shouldStop)
|
|
||||||
|
|
||||||
def testFailFastSetByRunner(self):
|
|
||||||
runner = unittest2.TextTestRunner(stream=StringIO(), failfast=True)
|
|
||||||
self.testRan = False
|
|
||||||
def test(result):
|
|
||||||
self.testRan = True
|
|
||||||
self.assertTrue(result.failfast)
|
|
||||||
runner.run(test)
|
|
||||||
self.assertTrue(self.testRan)
|
|
||||||
|
|
||||||
|
|
||||||
class TestOutputBuffering(unittest2.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._real_out = sys.stdout
|
|
||||||
self._real_err = sys.stderr
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
sys.stdout = self._real_out
|
|
||||||
sys.stderr = self._real_err
|
|
||||||
|
|
||||||
def testBufferOutputOff(self):
|
|
||||||
real_out = self._real_out
|
|
||||||
real_err = self._real_err
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
self.assertFalse(result.buffer)
|
|
||||||
|
|
||||||
self.assertIs(real_out, sys.stdout)
|
|
||||||
self.assertIs(real_err, sys.stderr)
|
|
||||||
|
|
||||||
result.startTest(self)
|
|
||||||
|
|
||||||
self.assertIs(real_out, sys.stdout)
|
|
||||||
self.assertIs(real_err, sys.stderr)
|
|
||||||
|
|
||||||
def testBufferOutputStartTestAddSuccess(self):
|
|
||||||
real_out = self._real_out
|
|
||||||
real_err = self._real_err
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
self.assertFalse(result.buffer)
|
|
||||||
|
|
||||||
result.buffer = True
|
|
||||||
|
|
||||||
self.assertIs(real_out, sys.stdout)
|
|
||||||
self.assertIs(real_err, sys.stderr)
|
|
||||||
|
|
||||||
result.startTest(self)
|
|
||||||
|
|
||||||
self.assertIsNot(real_out, sys.stdout)
|
|
||||||
self.assertIsNot(real_err, sys.stderr)
|
|
||||||
self.assertIsInstance(sys.stdout, StringIO)
|
|
||||||
self.assertIsInstance(sys.stderr, StringIO)
|
|
||||||
self.assertIsNot(sys.stdout, sys.stderr)
|
|
||||||
|
|
||||||
out_stream = sys.stdout
|
|
||||||
err_stream = sys.stderr
|
|
||||||
|
|
||||||
result._original_stdout = StringIO()
|
|
||||||
result._original_stderr = StringIO()
|
|
||||||
|
|
||||||
print 'foo'
|
|
||||||
print >> sys.stderr, 'bar'
|
|
||||||
|
|
||||||
self.assertEqual(out_stream.getvalue(), 'foo\n')
|
|
||||||
self.assertEqual(err_stream.getvalue(), 'bar\n')
|
|
||||||
|
|
||||||
self.assertEqual(result._original_stdout.getvalue(), '')
|
|
||||||
self.assertEqual(result._original_stderr.getvalue(), '')
|
|
||||||
|
|
||||||
result.addSuccess(self)
|
|
||||||
result.stopTest(self)
|
|
||||||
|
|
||||||
self.assertIs(sys.stdout, result._original_stdout)
|
|
||||||
self.assertIs(sys.stderr, result._original_stderr)
|
|
||||||
|
|
||||||
self.assertEqual(result._original_stdout.getvalue(), '')
|
|
||||||
self.assertEqual(result._original_stderr.getvalue(), '')
|
|
||||||
|
|
||||||
self.assertEqual(out_stream.getvalue(), '')
|
|
||||||
self.assertEqual(err_stream.getvalue(), '')
|
|
||||||
|
|
||||||
|
|
||||||
def getStartedResult(self):
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
result.buffer = True
|
|
||||||
result.startTest(self)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def testBufferOutputAddErrorOrFailure(self):
|
|
||||||
for message_attr, add_attr, include_error in [
|
|
||||||
('errors', 'addError', True),
|
|
||||||
('failures', 'addFailure', False),
|
|
||||||
('errors', 'addError', True),
|
|
||||||
('failures', 'addFailure', False)
|
|
||||||
]:
|
|
||||||
result = self.getStartedResult()
|
|
||||||
result._original_stderr = StringIO()
|
|
||||||
result._original_stdout = StringIO()
|
|
||||||
|
|
||||||
print >> sys.stdout, 'foo'
|
|
||||||
if include_error:
|
|
||||||
print >> sys.stderr, 'bar'
|
|
||||||
|
|
||||||
addFunction = getattr(result, add_attr)
|
|
||||||
addFunction(self, (None, None, None))
|
|
||||||
result.stopTest(self)
|
|
||||||
|
|
||||||
result_list = getattr(result, message_attr)
|
|
||||||
self.assertEqual(len(result_list), 1)
|
|
||||||
|
|
||||||
test, message = result_list[0]
|
|
||||||
expectedOutMessage = textwrap.dedent("""
|
|
||||||
Stdout:
|
|
||||||
foo
|
|
||||||
""")
|
|
||||||
expectedErrMessage = ''
|
|
||||||
if include_error:
|
|
||||||
expectedErrMessage = textwrap.dedent("""
|
|
||||||
Stderr:
|
|
||||||
bar
|
|
||||||
""")
|
|
||||||
expectedFullMessage = 'None\n%s%s' % (expectedOutMessage, expectedErrMessage)
|
|
||||||
|
|
||||||
self.assertIs(test, self)
|
|
||||||
self.assertEqual(result._original_stdout.getvalue(), expectedOutMessage)
|
|
||||||
self.assertEqual(result._original_stderr.getvalue(), expectedErrMessage)
|
|
||||||
self.assertMultiLineEqual(message, expectedFullMessage)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
import pickle
|
|
||||||
|
|
||||||
from cStringIO import StringIO
|
|
||||||
from unittest2.test.support import LoggingResult, OldTestResult
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
|
|
||||||
class Test_TextTestRunner(unittest2.TestCase):
|
|
||||||
"""Tests for TextTestRunner."""
|
|
||||||
|
|
||||||
def test_init(self):
|
|
||||||
runner = unittest2.TextTestRunner()
|
|
||||||
self.assertFalse(runner.failfast)
|
|
||||||
self.assertFalse(runner.buffer)
|
|
||||||
self.assertEqual(runner.verbosity, 1)
|
|
||||||
self.assertTrue(runner.descriptions)
|
|
||||||
self.assertEqual(runner.resultclass, unittest2.TextTestResult)
|
|
||||||
|
|
||||||
|
|
||||||
def testBufferAndFailfast(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def testFoo(self):
|
|
||||||
pass
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
runner = unittest2.TextTestRunner(stream=StringIO(), failfast=True,
|
|
||||||
buffer=True)
|
|
||||||
# Use our result object
|
|
||||||
runner._makeResult = lambda: result
|
|
||||||
runner.run(Test('testFoo'))
|
|
||||||
|
|
||||||
self.assertTrue(result.failfast)
|
|
||||||
self.assertTrue(result.buffer)
|
|
||||||
|
|
||||||
def testRunnerRegistersResult(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def testFoo(self):
|
|
||||||
pass
|
|
||||||
originalRegisterResult = unittest2.runner.registerResult
|
|
||||||
def cleanup():
|
|
||||||
unittest2.runner.registerResult = originalRegisterResult
|
|
||||||
self.addCleanup(cleanup)
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
runner = unittest2.TextTestRunner(stream=StringIO())
|
|
||||||
# Use our result object
|
|
||||||
runner._makeResult = lambda: result
|
|
||||||
|
|
||||||
self.wasRegistered = 0
|
|
||||||
def fakeRegisterResult(thisResult):
|
|
||||||
self.wasRegistered += 1
|
|
||||||
self.assertEqual(thisResult, result)
|
|
||||||
unittest2.runner.registerResult = fakeRegisterResult
|
|
||||||
|
|
||||||
runner.run(unittest2.TestSuite())
|
|
||||||
self.assertEqual(self.wasRegistered, 1)
|
|
||||||
|
|
||||||
def test_works_with_result_without_startTestRun_stopTestRun(self):
|
|
||||||
class OldTextResult(OldTestResult):
|
|
||||||
def __init__(self, *_):
|
|
||||||
super(OldTextResult, self).__init__()
|
|
||||||
separator2 = ''
|
|
||||||
def printErrors(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
runner = unittest2.TextTestRunner(stream=StringIO(),
|
|
||||||
resultclass=OldTextResult)
|
|
||||||
runner.run(unittest2.TestSuite())
|
|
||||||
|
|
||||||
def test_startTestRun_stopTestRun_called(self):
|
|
||||||
class LoggingTextResult(LoggingResult):
|
|
||||||
separator2 = ''
|
|
||||||
def printErrors(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class LoggingRunner(unittest2.TextTestRunner):
|
|
||||||
def __init__(self, events):
|
|
||||||
super(LoggingRunner, self).__init__(StringIO())
|
|
||||||
self._events = events
|
|
||||||
|
|
||||||
def _makeResult(self):
|
|
||||||
return LoggingTextResult(self._events)
|
|
||||||
|
|
||||||
events = []
|
|
||||||
runner = LoggingRunner(events)
|
|
||||||
runner.run(unittest2.TestSuite())
|
|
||||||
expected = ['startTestRun', 'stopTestRun']
|
|
||||||
self.assertEqual(events, expected)
|
|
||||||
|
|
||||||
def test_pickle_unpickle(self):
|
|
||||||
# Issue #7197: a TextTestRunner should be (un)pickleable. This is
|
|
||||||
# required by test_multiprocessing under Windows (in verbose mode).
|
|
||||||
import StringIO
|
|
||||||
# cStringIO objects are not pickleable, but StringIO objects are.
|
|
||||||
stream = StringIO.StringIO("foo")
|
|
||||||
runner = unittest2.TextTestRunner(stream)
|
|
||||||
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
|
|
||||||
s = pickle.dumps(runner, protocol=protocol)
|
|
||||||
obj = pickle.loads(s)
|
|
||||||
# StringIO objects never compare equal, a cheap test instead.
|
|
||||||
self.assertEqual(obj.stream.getvalue(), stream.getvalue())
|
|
||||||
|
|
||||||
def test_resultclass(self):
|
|
||||||
def MockResultClass(*args):
|
|
||||||
return args
|
|
||||||
STREAM = object()
|
|
||||||
DESCRIPTIONS = object()
|
|
||||||
VERBOSITY = object()
|
|
||||||
runner = unittest2.TextTestRunner(STREAM, DESCRIPTIONS, VERBOSITY,
|
|
||||||
resultclass=MockResultClass)
|
|
||||||
self.assertEqual(runner.resultclass, MockResultClass)
|
|
||||||
|
|
||||||
expectedresult = (runner.stream, DESCRIPTIONS, VERBOSITY)
|
|
||||||
self.assertEqual(runner._makeResult(), expectedresult)
|
|
||||||
|
|
||||||
|
|
||||||
def test_oldresult(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def testFoo(self):
|
|
||||||
pass
|
|
||||||
runner = unittest2.TextTestRunner(resultclass=OldTestResult,
|
|
||||||
stream=StringIO())
|
|
||||||
# This will raise an exception if TextTestRunner can't handle old
|
|
||||||
# test result objects
|
|
||||||
runner.run(Test('testFoo'))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,502 +0,0 @@
|
||||||
import sys
|
|
||||||
|
|
||||||
from cStringIO import StringIO
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
from unittest2.test.support import resultFactory
|
|
||||||
|
|
||||||
|
|
||||||
class TestSetups(unittest2.TestCase):
|
|
||||||
|
|
||||||
def getRunner(self):
|
|
||||||
return unittest2.TextTestRunner(resultclass=resultFactory,
|
|
||||||
stream=StringIO())
|
|
||||||
def runTests(self, *cases):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
for case in cases:
|
|
||||||
tests = unittest2.defaultTestLoader.loadTestsFromTestCase(case)
|
|
||||||
suite.addTests(tests)
|
|
||||||
|
|
||||||
runner = self.getRunner()
|
|
||||||
|
|
||||||
# creating a nested suite exposes some potential bugs
|
|
||||||
realSuite = unittest2.TestSuite()
|
|
||||||
realSuite.addTest(suite)
|
|
||||||
# adding empty suites to the end exposes potential bugs
|
|
||||||
suite.addTest(unittest2.TestSuite())
|
|
||||||
realSuite.addTest(unittest2.TestSuite())
|
|
||||||
return runner.run(realSuite)
|
|
||||||
|
|
||||||
def test_setup_class(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
setUpCalled = 0
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
Test.setUpCalled += 1
|
|
||||||
unittest2.TestCase.setUpClass()
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = self.runTests(Test)
|
|
||||||
|
|
||||||
self.assertEqual(Test.setUpCalled, 1)
|
|
||||||
self.assertEqual(result.testsRun, 2)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
def test_teardown_class(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
tearDownCalled = 0
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test.tearDownCalled += 1
|
|
||||||
unittest2.TestCase.tearDownClass()
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = self.runTests(Test)
|
|
||||||
|
|
||||||
self.assertEqual(Test.tearDownCalled, 1)
|
|
||||||
self.assertEqual(result.testsRun, 2)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
def test_teardown_class_two_classes(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
tearDownCalled = 0
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test.tearDownCalled += 1
|
|
||||||
unittest2.TestCase.tearDownClass()
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Test2(unittest2.TestCase):
|
|
||||||
tearDownCalled = 0
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test2.tearDownCalled += 1
|
|
||||||
unittest2.TestCase.tearDownClass()
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = self.runTests(Test, Test2)
|
|
||||||
|
|
||||||
self.assertEqual(Test.tearDownCalled, 1)
|
|
||||||
self.assertEqual(Test2.tearDownCalled, 1)
|
|
||||||
self.assertEqual(result.testsRun, 4)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
def test_error_in_setupclass(self):
|
|
||||||
class BrokenTest(unittest2.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
raise TypeError('foo')
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = self.runTests(BrokenTest)
|
|
||||||
|
|
||||||
self.assertEqual(result.testsRun, 0)
|
|
||||||
self.assertEqual(len(result.errors), 1)
|
|
||||||
error, _ = result.errors[0]
|
|
||||||
self.assertEqual(str(error),
|
|
||||||
'setUpClass (%s.BrokenTest)' % __name__)
|
|
||||||
|
|
||||||
def test_error_in_teardown_class(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
tornDown = 0
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test.tornDown += 1
|
|
||||||
raise TypeError('foo')
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Test2(unittest2.TestCase):
|
|
||||||
tornDown = 0
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test2.tornDown += 1
|
|
||||||
raise TypeError('foo')
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = self.runTests(Test, Test2)
|
|
||||||
self.assertEqual(result.testsRun, 4)
|
|
||||||
self.assertEqual(len(result.errors), 2)
|
|
||||||
self.assertEqual(Test.tornDown, 1)
|
|
||||||
self.assertEqual(Test2.tornDown, 1)
|
|
||||||
|
|
||||||
error, _ = result.errors[0]
|
|
||||||
self.assertEqual(str(error),
|
|
||||||
'tearDownClass (%s.Test)' % __name__)
|
|
||||||
|
|
||||||
def test_class_not_torndown_when_setup_fails(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
tornDown = False
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
raise TypeError
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test.tornDown = True
|
|
||||||
raise TypeError('foo')
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.runTests(Test)
|
|
||||||
self.assertFalse(Test.tornDown)
|
|
||||||
|
|
||||||
def test_class_not_setup_or_torndown_when_skipped(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
classSetUp = False
|
|
||||||
tornDown = False
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
Test.classSetUp = True
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test.tornDown = True
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
Test = unittest2.skip("hop")(Test)
|
|
||||||
self.runTests(Test)
|
|
||||||
self.assertFalse(Test.classSetUp)
|
|
||||||
self.assertFalse(Test.tornDown)
|
|
||||||
|
|
||||||
def test_setup_teardown_order_with_pathological_suite(self):
|
|
||||||
results = []
|
|
||||||
|
|
||||||
class Module1(object):
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
results.append('Module1.setUpModule')
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
results.append('Module1.tearDownModule')
|
|
||||||
|
|
||||||
class Module2(object):
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
results.append('Module2.setUpModule')
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
results.append('Module2.tearDownModule')
|
|
||||||
|
|
||||||
class Test1(unittest2.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
results.append('setup 1')
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
results.append('teardown 1')
|
|
||||||
def testOne(self):
|
|
||||||
results.append('Test1.testOne')
|
|
||||||
def testTwo(self):
|
|
||||||
results.append('Test1.testTwo')
|
|
||||||
|
|
||||||
class Test2(unittest2.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
results.append('setup 2')
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
results.append('teardown 2')
|
|
||||||
def testOne(self):
|
|
||||||
results.append('Test2.testOne')
|
|
||||||
def testTwo(self):
|
|
||||||
results.append('Test2.testTwo')
|
|
||||||
|
|
||||||
class Test3(unittest2.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
results.append('setup 3')
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
results.append('teardown 3')
|
|
||||||
def testOne(self):
|
|
||||||
results.append('Test3.testOne')
|
|
||||||
def testTwo(self):
|
|
||||||
results.append('Test3.testTwo')
|
|
||||||
|
|
||||||
Test1.__module__ = Test2.__module__ = 'Module'
|
|
||||||
Test3.__module__ = 'Module2'
|
|
||||||
sys.modules['Module'] = Module1
|
|
||||||
sys.modules['Module2'] = Module2
|
|
||||||
|
|
||||||
first = unittest2.TestSuite((Test1('testOne'),))
|
|
||||||
second = unittest2.TestSuite((Test1('testTwo'),))
|
|
||||||
third = unittest2.TestSuite((Test2('testOne'),))
|
|
||||||
fourth = unittest2.TestSuite((Test2('testTwo'),))
|
|
||||||
fifth = unittest2.TestSuite((Test3('testOne'),))
|
|
||||||
sixth = unittest2.TestSuite((Test3('testTwo'),))
|
|
||||||
suite = unittest2.TestSuite((first, second, third, fourth, fifth, sixth))
|
|
||||||
|
|
||||||
runner = self.getRunner()
|
|
||||||
result = runner.run(suite)
|
|
||||||
self.assertEqual(result.testsRun, 6)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
self.assertEqual(results,
|
|
||||||
['Module1.setUpModule', 'setup 1',
|
|
||||||
'Test1.testOne', 'Test1.testTwo', 'teardown 1',
|
|
||||||
'setup 2', 'Test2.testOne', 'Test2.testTwo',
|
|
||||||
'teardown 2', 'Module1.tearDownModule',
|
|
||||||
'Module2.setUpModule', 'setup 3',
|
|
||||||
'Test3.testOne', 'Test3.testTwo',
|
|
||||||
'teardown 3', 'Module2.tearDownModule'])
|
|
||||||
|
|
||||||
def test_setup_module(self):
|
|
||||||
class Module(object):
|
|
||||||
moduleSetup = 0
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
Module.moduleSetup += 1
|
|
||||||
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
|
|
||||||
result = self.runTests(Test)
|
|
||||||
self.assertEqual(Module.moduleSetup, 1)
|
|
||||||
self.assertEqual(result.testsRun, 2)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
def test_error_in_setup_module(self):
|
|
||||||
class Module(object):
|
|
||||||
moduleSetup = 0
|
|
||||||
moduleTornDown = 0
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
Module.moduleSetup += 1
|
|
||||||
raise TypeError('foo')
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
Module.moduleTornDown += 1
|
|
||||||
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
classSetUp = False
|
|
||||||
classTornDown = False
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
Test.classSetUp = True
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test.classTornDown = True
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Test2(unittest2.TestCase):
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
Test2.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
|
|
||||||
result = self.runTests(Test, Test2)
|
|
||||||
self.assertEqual(Module.moduleSetup, 1)
|
|
||||||
self.assertEqual(Module.moduleTornDown, 0)
|
|
||||||
self.assertEqual(result.testsRun, 0)
|
|
||||||
self.assertFalse(Test.classSetUp)
|
|
||||||
self.assertFalse(Test.classTornDown)
|
|
||||||
self.assertEqual(len(result.errors), 1)
|
|
||||||
error, _ = result.errors[0]
|
|
||||||
self.assertEqual(str(error), 'setUpModule (Module)')
|
|
||||||
|
|
||||||
def test_testcase_with_missing_module(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
sys.modules.pop('Module', None)
|
|
||||||
|
|
||||||
result = self.runTests(Test)
|
|
||||||
self.assertEqual(result.testsRun, 2)
|
|
||||||
|
|
||||||
def test_teardown_module(self):
|
|
||||||
class Module(object):
|
|
||||||
moduleTornDown = 0
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
Module.moduleTornDown += 1
|
|
||||||
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
|
|
||||||
result = self.runTests(Test)
|
|
||||||
self.assertEqual(Module.moduleTornDown, 1)
|
|
||||||
self.assertEqual(result.testsRun, 2)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
|
|
||||||
def test_error_in_teardown_module(self):
|
|
||||||
class Module(object):
|
|
||||||
moduleTornDown = 0
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
Module.moduleTornDown += 1
|
|
||||||
raise TypeError('foo')
|
|
||||||
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
classSetUp = False
|
|
||||||
classTornDown = False
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
Test.classSetUp = True
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
Test.classTornDown = True
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Test2(unittest2.TestCase):
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
Test2.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
|
|
||||||
result = self.runTests(Test, Test2)
|
|
||||||
self.assertEqual(Module.moduleTornDown, 1)
|
|
||||||
self.assertEqual(result.testsRun, 4)
|
|
||||||
self.assertTrue(Test.classSetUp)
|
|
||||||
self.assertTrue(Test.classTornDown)
|
|
||||||
self.assertEqual(len(result.errors), 1)
|
|
||||||
error, _ = result.errors[0]
|
|
||||||
self.assertEqual(str(error), 'tearDownModule (Module)')
|
|
||||||
|
|
||||||
def test_skiptest_in_setupclass(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
raise unittest2.SkipTest('foo')
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = self.runTests(Test)
|
|
||||||
self.assertEqual(result.testsRun, 0)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.skipped), 1)
|
|
||||||
skipped = result.skipped[0][0]
|
|
||||||
self.assertEqual(str(skipped), 'setUpClass (%s.Test)' % __name__)
|
|
||||||
|
|
||||||
def test_skiptest_in_setupmodule(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def test_one(self):
|
|
||||||
pass
|
|
||||||
def test_two(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Module(object):
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
raise unittest2.SkipTest('foo')
|
|
||||||
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
|
|
||||||
result = self.runTests(Test)
|
|
||||||
self.assertEqual(result.testsRun, 0)
|
|
||||||
self.assertEqual(len(result.errors), 0)
|
|
||||||
self.assertEqual(len(result.skipped), 1)
|
|
||||||
skipped = result.skipped[0][0]
|
|
||||||
self.assertEqual(str(skipped), 'setUpModule (Module)')
|
|
||||||
|
|
||||||
def test_suite_debug_executes_setups_and_teardowns(self):
|
|
||||||
ordering = []
|
|
||||||
|
|
||||||
class Module(object):
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
ordering.append('setUpModule')
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
ordering.append('tearDownModule')
|
|
||||||
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
ordering.append('setUpClass')
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
ordering.append('tearDownClass')
|
|
||||||
def test_something(self):
|
|
||||||
ordering.append('test_something')
|
|
||||||
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
|
|
||||||
suite = unittest2.defaultTestLoader.loadTestsFromTestCase(Test)
|
|
||||||
suite.debug()
|
|
||||||
expectedOrder = ['setUpModule', 'setUpClass', 'test_something', 'tearDownClass', 'tearDownModule']
|
|
||||||
self.assertEqual(ordering, expectedOrder)
|
|
||||||
|
|
||||||
def test_suite_debug_propagates_exceptions(self):
|
|
||||||
class Module(object):
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
if phase == 0:
|
|
||||||
raise Exception('setUpModule')
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
if phase == 1:
|
|
||||||
raise Exception('tearDownModule')
|
|
||||||
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
if phase == 2:
|
|
||||||
raise Exception('setUpClass')
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
if phase == 3:
|
|
||||||
raise Exception('tearDownClass')
|
|
||||||
def test_something(self):
|
|
||||||
if phase == 4:
|
|
||||||
raise Exception('test_something')
|
|
||||||
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
|
|
||||||
_suite = unittest2.defaultTestLoader.loadTestsFromTestCase(Test)
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
|
|
||||||
# nesting a suite again exposes a bug in the initial implementation
|
|
||||||
suite.addTest(_suite)
|
|
||||||
messages = ('setUpModule', 'tearDownModule', 'setUpClass', 'tearDownClass', 'test_something')
|
|
||||||
for phase, msg in enumerate(messages):
|
|
||||||
self.assertRaisesRegexp(Exception, msg, suite.debug)
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
from unittest2.test.support import LoggingResult
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
|
|
||||||
class Test_TestSkipping(unittest2.TestCase):
|
|
||||||
|
|
||||||
def test_skipping(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_skip_me(self):
|
|
||||||
self.skipTest("skip")
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
test = Foo("test_skip_me")
|
|
||||||
test.run(result)
|
|
||||||
self.assertEqual(events, ['startTest', 'addSkip', 'stopTest'])
|
|
||||||
self.assertEqual(result.skipped, [(test, "skip")])
|
|
||||||
|
|
||||||
# Try letting setUp skip the test now.
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.skipTest("testing")
|
|
||||||
def test_nothing(self): pass
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
test = Foo("test_nothing")
|
|
||||||
test.run(result)
|
|
||||||
self.assertEqual(events, ['startTest', 'addSkip', 'stopTest'])
|
|
||||||
self.assertEqual(result.skipped, [(test, "testing")])
|
|
||||||
self.assertEqual(result.testsRun, 1)
|
|
||||||
|
|
||||||
def test_skipping_decorators(self):
|
|
||||||
op_table = ((unittest2.skipUnless, False, True),
|
|
||||||
(unittest2.skipIf, True, False))
|
|
||||||
for deco, do_skip, dont_skip in op_table:
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
@deco(do_skip, "testing")
|
|
||||||
def test_skip(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@deco(dont_skip, "testing")
|
|
||||||
def test_dont_skip(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
test_do_skip = Foo("test_skip")
|
|
||||||
test_dont_skip = Foo("test_dont_skip")
|
|
||||||
suite = unittest2.TestSuite([test_do_skip, test_dont_skip])
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
suite.run(result)
|
|
||||||
self.assertEqual(len(result.skipped), 1)
|
|
||||||
expected = ['startTest', 'addSkip', 'stopTest',
|
|
||||||
'startTest', 'addSuccess', 'stopTest']
|
|
||||||
self.assertEqual(events, expected)
|
|
||||||
self.assertEqual(result.testsRun, 2)
|
|
||||||
self.assertEqual(result.skipped, [(test_do_skip, "testing")])
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
|
|
||||||
def test_skip_class(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self):
|
|
||||||
record.append(1)
|
|
||||||
|
|
||||||
# was originally a class decorator...
|
|
||||||
Foo = unittest2.skip("testing")(Foo)
|
|
||||||
record = []
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
test = Foo("test_1")
|
|
||||||
suite = unittest2.TestSuite([test])
|
|
||||||
suite.run(result)
|
|
||||||
self.assertEqual(result.skipped, [(test, "testing")])
|
|
||||||
self.assertEqual(record, [])
|
|
||||||
|
|
||||||
def test_expected_failure(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
@unittest2.expectedFailure
|
|
||||||
def test_die(self):
|
|
||||||
self.fail("help me!")
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
test = Foo("test_die")
|
|
||||||
test.run(result)
|
|
||||||
self.assertEqual(events,
|
|
||||||
['startTest', 'addExpectedFailure', 'stopTest'])
|
|
||||||
self.assertEqual(result.expectedFailures[0][0], test)
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
|
|
||||||
def test_unexpected_success(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
@unittest2.expectedFailure
|
|
||||||
def test_die(self):
|
|
||||||
pass
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
test = Foo("test_die")
|
|
||||||
test.run(result)
|
|
||||||
self.assertEqual(events,
|
|
||||||
['startTest', 'addUnexpectedSuccess', 'stopTest'])
|
|
||||||
self.assertFalse(result.failures)
|
|
||||||
self.assertEqual(result.unexpectedSuccesses, [test])
|
|
||||||
self.assertTrue(result.wasSuccessful())
|
|
||||||
|
|
||||||
def test_skip_doesnt_run_setup(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
wasSetUp = False
|
|
||||||
wasTornDown = False
|
|
||||||
def setUp(self):
|
|
||||||
Foo.wasSetUp = True
|
|
||||||
def tornDown(self):
|
|
||||||
Foo.wasTornDown = True
|
|
||||||
@unittest2.skip('testing')
|
|
||||||
def test_1(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
test = Foo("test_1")
|
|
||||||
suite = unittest2.TestSuite([test])
|
|
||||||
suite.run(result)
|
|
||||||
self.assertEqual(result.skipped, [(test, "testing")])
|
|
||||||
self.assertFalse(Foo.wasSetUp)
|
|
||||||
self.assertFalse(Foo.wasTornDown)
|
|
||||||
|
|
||||||
def test_decorated_skip(self):
|
|
||||||
def decorator(func):
|
|
||||||
def inner(*a):
|
|
||||||
return func(*a)
|
|
||||||
return inner
|
|
||||||
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
@decorator
|
|
||||||
@unittest2.skip('testing')
|
|
||||||
def test_1(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
test = Foo("test_1")
|
|
||||||
suite = unittest2.TestSuite([test])
|
|
||||||
suite.run(result)
|
|
||||||
self.assertEqual(result.skipped, [(test, "testing")])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,341 +0,0 @@
|
||||||
from unittest2.test.support import EqualityMixin, LoggingResult
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import unittest2
|
|
||||||
|
|
||||||
class Test(object):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self): pass
|
|
||||||
def test_2(self): pass
|
|
||||||
def test_3(self): pass
|
|
||||||
def runTest(self): pass
|
|
||||||
|
|
||||||
def _mk_TestSuite(*names):
|
|
||||||
return unittest2.TestSuite(Test.Foo(n) for n in names)
|
|
||||||
|
|
||||||
|
|
||||||
class Test_TestSuite(unittest2.TestCase, EqualityMixin):
|
|
||||||
|
|
||||||
### Set up attributes needed by inherited tests
|
|
||||||
################################################################
|
|
||||||
|
|
||||||
# Used by EqualityMixin.test_eq
|
|
||||||
eq_pairs = [(unittest2.TestSuite(), unittest2.TestSuite()),
|
|
||||||
(unittest2.TestSuite(), unittest2.TestSuite([])),
|
|
||||||
(_mk_TestSuite('test_1'), _mk_TestSuite('test_1'))]
|
|
||||||
|
|
||||||
# Used by EqualityMixin.test_ne
|
|
||||||
ne_pairs = [(unittest2.TestSuite(), _mk_TestSuite('test_1')),
|
|
||||||
(unittest2.TestSuite([]), _mk_TestSuite('test_1')),
|
|
||||||
(_mk_TestSuite('test_1', 'test_2'), _mk_TestSuite('test_1', 'test_3')),
|
|
||||||
(_mk_TestSuite('test_1'), _mk_TestSuite('test_2'))]
|
|
||||||
|
|
||||||
################################################################
|
|
||||||
### /Set up attributes needed by inherited tests
|
|
||||||
|
|
||||||
### Tests for TestSuite.__init__
|
|
||||||
################################################################
|
|
||||||
|
|
||||||
# "class TestSuite([tests])"
|
|
||||||
#
|
|
||||||
# The tests iterable should be optional
|
|
||||||
def test_init__tests_optional(self):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
|
|
||||||
self.assertEqual(suite.countTestCases(), 0)
|
|
||||||
|
|
||||||
# "class TestSuite([tests])"
|
|
||||||
# ...
|
|
||||||
# "If tests is given, it must be an iterable of individual test cases
|
|
||||||
# or other test suites that will be used to build the suite initially"
|
|
||||||
#
|
|
||||||
# TestSuite should deal with empty tests iterables by allowing the
|
|
||||||
# creation of an empty suite
|
|
||||||
def test_init__empty_tests(self):
|
|
||||||
suite = unittest2.TestSuite([])
|
|
||||||
|
|
||||||
self.assertEqual(suite.countTestCases(), 0)
|
|
||||||
|
|
||||||
# "class TestSuite([tests])"
|
|
||||||
# ...
|
|
||||||
# "If tests is given, it must be an iterable of individual test cases
|
|
||||||
# or other test suites that will be used to build the suite initially"
|
|
||||||
#
|
|
||||||
# TestSuite should allow any iterable to provide tests
|
|
||||||
def test_init__tests_from_any_iterable(self):
|
|
||||||
def tests():
|
|
||||||
yield unittest2.FunctionTestCase(lambda: None)
|
|
||||||
yield unittest2.FunctionTestCase(lambda: None)
|
|
||||||
|
|
||||||
suite_1 = unittest2.TestSuite(tests())
|
|
||||||
self.assertEqual(suite_1.countTestCases(), 2)
|
|
||||||
|
|
||||||
suite_2 = unittest2.TestSuite(suite_1)
|
|
||||||
self.assertEqual(suite_2.countTestCases(), 2)
|
|
||||||
|
|
||||||
suite_3 = unittest2.TestSuite(set(suite_1))
|
|
||||||
self.assertEqual(suite_3.countTestCases(), 2)
|
|
||||||
|
|
||||||
# "class TestSuite([tests])"
|
|
||||||
# ...
|
|
||||||
# "If tests is given, it must be an iterable of individual test cases
|
|
||||||
# or other test suites that will be used to build the suite initially"
|
|
||||||
#
|
|
||||||
# Does TestSuite() also allow other TestSuite() instances to be present
|
|
||||||
# in the tests iterable?
|
|
||||||
def test_init__TestSuite_instances_in_tests(self):
|
|
||||||
def tests():
|
|
||||||
ftc = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
yield unittest2.TestSuite([ftc])
|
|
||||||
yield unittest2.FunctionTestCase(lambda: None)
|
|
||||||
|
|
||||||
suite = unittest2.TestSuite(tests())
|
|
||||||
self.assertEqual(suite.countTestCases(), 2)
|
|
||||||
|
|
||||||
################################################################
|
|
||||||
### /Tests for TestSuite.__init__
|
|
||||||
|
|
||||||
# Container types should support the iter protocol
|
|
||||||
def test_iter(self):
|
|
||||||
test1 = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
test2 = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
suite = unittest2.TestSuite((test1, test2))
|
|
||||||
|
|
||||||
self.assertEqual(list(suite), [test1, test2])
|
|
||||||
|
|
||||||
# "Return the number of tests represented by the this test object.
|
|
||||||
# ...this method is also implemented by the TestSuite class, which can
|
|
||||||
# return larger [greater than 1] values"
|
|
||||||
#
|
|
||||||
# Presumably an empty TestSuite returns 0?
|
|
||||||
def test_countTestCases_zero_simple(self):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
|
|
||||||
self.assertEqual(suite.countTestCases(), 0)
|
|
||||||
|
|
||||||
# "Return the number of tests represented by the this test object.
|
|
||||||
# ...this method is also implemented by the TestSuite class, which can
|
|
||||||
# return larger [greater than 1] values"
|
|
||||||
#
|
|
||||||
# Presumably an empty TestSuite (even if it contains other empty
|
|
||||||
# TestSuite instances) returns 0?
|
|
||||||
def test_countTestCases_zero_nested(self):
|
|
||||||
class Test1(unittest2.TestCase):
|
|
||||||
def test(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
suite = unittest2.TestSuite([unittest2.TestSuite()])
|
|
||||||
|
|
||||||
self.assertEqual(suite.countTestCases(), 0)
|
|
||||||
|
|
||||||
# "Return the number of tests represented by the this test object.
|
|
||||||
# ...this method is also implemented by the TestSuite class, which can
|
|
||||||
# return larger [greater than 1] values"
|
|
||||||
def test_countTestCases_simple(self):
|
|
||||||
test1 = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
test2 = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
suite = unittest2.TestSuite((test1, test2))
|
|
||||||
|
|
||||||
self.assertEqual(suite.countTestCases(), 2)
|
|
||||||
|
|
||||||
# "Return the number of tests represented by the this test object.
|
|
||||||
# ...this method is also implemented by the TestSuite class, which can
|
|
||||||
# return larger [greater than 1] values"
|
|
||||||
#
|
|
||||||
# Make sure this holds for nested TestSuite instances, too
|
|
||||||
def test_countTestCases_nested(self):
|
|
||||||
class Test1(unittest2.TestCase):
|
|
||||||
def test1(self): pass
|
|
||||||
def test2(self): pass
|
|
||||||
|
|
||||||
test2 = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
test3 = unittest2.FunctionTestCase(lambda: None)
|
|
||||||
child = unittest2.TestSuite((Test1('test2'), test2))
|
|
||||||
parent = unittest2.TestSuite((test3, child, Test1('test1')))
|
|
||||||
|
|
||||||
self.assertEqual(parent.countTestCases(), 4)
|
|
||||||
|
|
||||||
# "Run the tests associated with this suite, collecting the result into
|
|
||||||
# the test result object passed as result."
|
|
||||||
#
|
|
||||||
# And if there are no tests? What then?
|
|
||||||
def test_run__empty_suite(self):
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
|
|
||||||
suite.run(result)
|
|
||||||
|
|
||||||
self.assertEqual(events, [])
|
|
||||||
|
|
||||||
# "Note that unlike TestCase.run(), TestSuite.run() requires the
|
|
||||||
# "result object to be passed in."
|
|
||||||
def test_run__requires_result(self):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
|
|
||||||
try:
|
|
||||||
suite.run()
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("Failed to raise TypeError")
|
|
||||||
|
|
||||||
# "Run the tests associated with this suite, collecting the result into
|
|
||||||
# the test result object passed as result."
|
|
||||||
def test_run(self):
|
|
||||||
events = []
|
|
||||||
result = LoggingResult(events)
|
|
||||||
|
|
||||||
class LoggingCase(unittest2.TestCase):
|
|
||||||
def run(self, result):
|
|
||||||
events.append('run %s' % self._testMethodName)
|
|
||||||
|
|
||||||
def test1(self): pass
|
|
||||||
def test2(self): pass
|
|
||||||
|
|
||||||
tests = [LoggingCase('test1'), LoggingCase('test2')]
|
|
||||||
|
|
||||||
unittest2.TestSuite(tests).run(result)
|
|
||||||
|
|
||||||
self.assertEqual(events, ['run test1', 'run test2'])
|
|
||||||
|
|
||||||
# "Add a TestCase ... to the suite"
|
|
||||||
def test_addTest__TestCase(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test(self): pass
|
|
||||||
|
|
||||||
test = Foo('test')
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
|
|
||||||
suite.addTest(test)
|
|
||||||
|
|
||||||
self.assertEqual(suite.countTestCases(), 1)
|
|
||||||
self.assertEqual(list(suite), [test])
|
|
||||||
|
|
||||||
# "Add a ... TestSuite to the suite"
|
|
||||||
def test_addTest__TestSuite(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test(self): pass
|
|
||||||
|
|
||||||
suite_2 = unittest2.TestSuite([Foo('test')])
|
|
||||||
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
suite.addTest(suite_2)
|
|
||||||
|
|
||||||
self.assertEqual(suite.countTestCases(), 1)
|
|
||||||
self.assertEqual(list(suite), [suite_2])
|
|
||||||
|
|
||||||
# "Add all the tests from an iterable of TestCase and TestSuite
|
|
||||||
# instances to this test suite."
|
|
||||||
#
|
|
||||||
# "This is equivalent to iterating over tests, calling addTest() for
|
|
||||||
# each element"
|
|
||||||
def test_addTests(self):
|
|
||||||
class Foo(unittest2.TestCase):
|
|
||||||
def test_1(self): pass
|
|
||||||
def test_2(self): pass
|
|
||||||
|
|
||||||
test_1 = Foo('test_1')
|
|
||||||
test_2 = Foo('test_2')
|
|
||||||
inner_suite = unittest2.TestSuite([test_2])
|
|
||||||
|
|
||||||
def gen():
|
|
||||||
yield test_1
|
|
||||||
yield test_2
|
|
||||||
yield inner_suite
|
|
||||||
|
|
||||||
suite_1 = unittest2.TestSuite()
|
|
||||||
suite_1.addTests(gen())
|
|
||||||
|
|
||||||
self.assertEqual(list(suite_1), list(gen()))
|
|
||||||
|
|
||||||
# "This is equivalent to iterating over tests, calling addTest() for
|
|
||||||
# each element"
|
|
||||||
suite_2 = unittest2.TestSuite()
|
|
||||||
for t in gen():
|
|
||||||
suite_2.addTest(t)
|
|
||||||
|
|
||||||
self.assertEqual(suite_1, suite_2)
|
|
||||||
|
|
||||||
# "Add all the tests from an iterable of TestCase and TestSuite
|
|
||||||
# instances to this test suite."
|
|
||||||
#
|
|
||||||
# What happens if it doesn't get an iterable?
|
|
||||||
def test_addTest__noniterable(self):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
|
|
||||||
try:
|
|
||||||
suite.addTests(5)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("Failed to raise TypeError")
|
|
||||||
|
|
||||||
def test_addTest__noncallable(self):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
self.assertRaises(TypeError, suite.addTest, 5)
|
|
||||||
|
|
||||||
def test_addTest__casesuiteclass(self):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
self.assertRaises(TypeError, suite.addTest, Test_TestSuite)
|
|
||||||
self.assertRaises(TypeError, suite.addTest, unittest2.TestSuite)
|
|
||||||
|
|
||||||
def test_addTests__string(self):
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
self.assertRaises(TypeError, suite.addTests, "foo")
|
|
||||||
|
|
||||||
def test_function_in_suite(self):
|
|
||||||
def f(_):
|
|
||||||
pass
|
|
||||||
suite = unittest2.TestSuite()
|
|
||||||
suite.addTest(f)
|
|
||||||
|
|
||||||
# when the bug is fixed this line will not crash
|
|
||||||
suite.run(unittest2.TestResult())
|
|
||||||
|
|
||||||
|
|
||||||
def test_basetestsuite(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
wasSetUp = False
|
|
||||||
wasTornDown = False
|
|
||||||
@classmethod
|
|
||||||
def setUpClass(cls):
|
|
||||||
cls.wasSetUp = True
|
|
||||||
@classmethod
|
|
||||||
def tearDownClass(cls):
|
|
||||||
cls.wasTornDown = True
|
|
||||||
def testPass(self):
|
|
||||||
pass
|
|
||||||
def testFail(self):
|
|
||||||
fail
|
|
||||||
class Module(object):
|
|
||||||
wasSetUp = False
|
|
||||||
wasTornDown = False
|
|
||||||
@staticmethod
|
|
||||||
def setUpModule():
|
|
||||||
Module.wasSetUp = True
|
|
||||||
@staticmethod
|
|
||||||
def tearDownModule():
|
|
||||||
Module.wasTornDown = True
|
|
||||||
|
|
||||||
Test.__module__ = 'Module'
|
|
||||||
sys.modules['Module'] = Module
|
|
||||||
self.addCleanup(sys.modules.pop, 'Module')
|
|
||||||
|
|
||||||
suite = unittest2.BaseTestSuite()
|
|
||||||
suite.addTests([Test('testPass'), Test('testFail')])
|
|
||||||
self.assertEqual(suite.countTestCases(), 2)
|
|
||||||
|
|
||||||
result = unittest2.TestResult()
|
|
||||||
suite.run(result)
|
|
||||||
self.assertFalse(Module.wasSetUp)
|
|
||||||
self.assertFalse(Module.wasTornDown)
|
|
||||||
self.assertFalse(Test.wasSetUp)
|
|
||||||
self.assertFalse(Test.wasTornDown)
|
|
||||||
self.assertEqual(len(result.errors), 1)
|
|
||||||
self.assertEqual(len(result.failures), 0)
|
|
||||||
self.assertEqual(result.testsRun, 2)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
from __future__ import with_statement
|
|
||||||
|
|
||||||
import unittest2
|
|
||||||
from unittest2.test.support import OldTestResult, catch_warnings
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
# needed to enable the deprecation warnings
|
|
||||||
warnings.simplefilter('default')
|
|
||||||
|
|
||||||
class TestWith(unittest2.TestCase):
|
|
||||||
"""Tests that use the with statement live in this
|
|
||||||
module so that all other tests can be run with Python 2.4.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def testAssertRaisesExcValue(self):
|
|
||||||
class ExceptionMock(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Stub(foo):
|
|
||||||
raise ExceptionMock(foo)
|
|
||||||
v = "particular value"
|
|
||||||
|
|
||||||
ctx = self.assertRaises(ExceptionMock)
|
|
||||||
with ctx:
|
|
||||||
Stub(v)
|
|
||||||
e = ctx.exception
|
|
||||||
self.assertIsInstance(e, ExceptionMock)
|
|
||||||
self.assertEqual(e.args[0], v)
|
|
||||||
|
|
||||||
|
|
||||||
def test_assertRaises(self):
|
|
||||||
def _raise(e):
|
|
||||||
raise e
|
|
||||||
self.assertRaises(KeyError, _raise, KeyError)
|
|
||||||
self.assertRaises(KeyError, _raise, KeyError("key"))
|
|
||||||
try:
|
|
||||||
self.assertRaises(KeyError, lambda: None)
|
|
||||||
except self.failureException, e:
|
|
||||||
self.assertIn("KeyError not raised", e.args)
|
|
||||||
else:
|
|
||||||
self.fail("assertRaises() didn't fail")
|
|
||||||
try:
|
|
||||||
self.assertRaises(KeyError, _raise, ValueError)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("assertRaises() didn't let exception pass through")
|
|
||||||
with self.assertRaises(KeyError) as cm:
|
|
||||||
try:
|
|
||||||
raise KeyError
|
|
||||||
except Exception, e:
|
|
||||||
raise
|
|
||||||
self.assertIs(cm.exception, e)
|
|
||||||
|
|
||||||
with self.assertRaises(KeyError):
|
|
||||||
raise KeyError("key")
|
|
||||||
try:
|
|
||||||
with self.assertRaises(KeyError):
|
|
||||||
pass
|
|
||||||
except self.failureException, e:
|
|
||||||
self.assertIn("KeyError not raised", e.args)
|
|
||||||
else:
|
|
||||||
self.fail("assertRaises() didn't fail")
|
|
||||||
try:
|
|
||||||
with self.assertRaises(KeyError):
|
|
||||||
raise ValueError
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("assertRaises() didn't let exception pass through")
|
|
||||||
|
|
||||||
def test_assert_dict_unicode_error(self):
|
|
||||||
with catch_warnings(record=True):
|
|
||||||
# This causes a UnicodeWarning due to its craziness
|
|
||||||
one = ''.join(chr(i) for i in range(255))
|
|
||||||
# this used to cause a UnicodeDecodeError constructing the failure msg
|
|
||||||
with self.assertRaises(self.failureException):
|
|
||||||
self.assertDictContainsSubset({'foo': one}, {'foo': u'\uFFFD'})
|
|
||||||
|
|
||||||
def test_formatMessage_unicode_error(self):
|
|
||||||
with catch_warnings(record=True):
|
|
||||||
# This causes a UnicodeWarning due to its craziness
|
|
||||||
one = ''.join(chr(i) for i in range(255))
|
|
||||||
# this used to cause a UnicodeDecodeError constructing msg
|
|
||||||
self._formatMessage(one, u'\uFFFD')
|
|
||||||
|
|
||||||
def assertOldResultWarning(self, test, failures):
|
|
||||||
with catch_warnings(record=True) as log:
|
|
||||||
result = OldTestResult()
|
|
||||||
test.run(result)
|
|
||||||
self.assertEqual(len(result.failures), failures)
|
|
||||||
warning, = log
|
|
||||||
self.assertIs(warning.category, DeprecationWarning)
|
|
||||||
|
|
||||||
def test_old_testresult(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def testSkip(self):
|
|
||||||
self.skipTest('foobar')
|
|
||||||
@unittest2.expectedFailure
|
|
||||||
def testExpectedFail(self):
|
|
||||||
raise TypeError
|
|
||||||
@unittest2.expectedFailure
|
|
||||||
def testUnexpectedSuccess(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
for test_name, should_pass in (('testSkip', True),
|
|
||||||
('testExpectedFail', True),
|
|
||||||
('testUnexpectedSuccess', False)):
|
|
||||||
test = Test(test_name)
|
|
||||||
self.assertOldResultWarning(test, int(not should_pass))
|
|
||||||
|
|
||||||
def test_old_testresult_setup(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.skipTest('no reason')
|
|
||||||
def testFoo(self):
|
|
||||||
pass
|
|
||||||
self.assertOldResultWarning(Test('testFoo'), 0)
|
|
||||||
|
|
||||||
def test_old_testresult_class(self):
|
|
||||||
class Test(unittest2.TestCase):
|
|
||||||
def testFoo(self):
|
|
||||||
pass
|
|
||||||
Test = unittest2.skip('no reason')(Test)
|
|
||||||
self.assertOldResultWarning(Test('testFoo'), 0)
|
|
||||||
|
|
||||||
def testPendingDeprecationMethodNames(self):
|
|
||||||
"""Test fail* methods pending deprecation, they will warn in 3.2.
|
|
||||||
|
|
||||||
Do not use these methods. They will go away in 3.3.
|
|
||||||
"""
|
|
||||||
with catch_warnings(record=True):
|
|
||||||
self.failIfEqual(3, 5)
|
|
||||||
self.failUnlessEqual(3, 3)
|
|
||||||
self.failUnlessAlmostEqual(2.0, 2.0)
|
|
||||||
self.failIfAlmostEqual(3.0, 5.0)
|
|
||||||
self.failUnless(True)
|
|
||||||
self.failUnlessRaises(TypeError, lambda _: 3.14 + u'spam')
|
|
||||||
self.failIf(False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest2.main()
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
"""Various utility functions."""
|
|
||||||
|
|
||||||
__unittest = True
|
|
||||||
|
|
||||||
|
|
||||||
_MAX_LENGTH = 80
|
|
||||||
def safe_repr(obj, short=False):
|
|
||||||
try:
|
|
||||||
result = repr(obj)
|
|
||||||
except Exception:
|
|
||||||
result = object.__repr__(obj)
|
|
||||||
if not short or len(result) < _MAX_LENGTH:
|
|
||||||
return result
|
|
||||||
return result[:_MAX_LENGTH] + ' [truncated]...'
|
|
||||||
|
|
||||||
def safe_str(obj):
|
|
||||||
try:
|
|
||||||
return str(obj)
|
|
||||||
except Exception:
|
|
||||||
return object.__str__(obj)
|
|
||||||
|
|
||||||
def strclass(cls):
|
|
||||||
return "%s.%s" % (cls.__module__, cls.__name__)
|
|
||||||
|
|
||||||
def sorted_list_difference(expected, actual):
|
|
||||||
"""Finds elements in only one or the other of two, sorted input lists.
|
|
||||||
|
|
||||||
Returns a two-element tuple of lists. The first list contains those
|
|
||||||
elements in the "expected" list but not in the "actual" list, and the
|
|
||||||
second contains those elements in the "actual" list but not in the
|
|
||||||
"expected" list. Duplicate elements in either input list are ignored.
|
|
||||||
"""
|
|
||||||
i = j = 0
|
|
||||||
missing = []
|
|
||||||
unexpected = []
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
e = expected[i]
|
|
||||||
a = actual[j]
|
|
||||||
if e < a:
|
|
||||||
missing.append(e)
|
|
||||||
i += 1
|
|
||||||
while expected[i] == e:
|
|
||||||
i += 1
|
|
||||||
elif e > a:
|
|
||||||
unexpected.append(a)
|
|
||||||
j += 1
|
|
||||||
while actual[j] == a:
|
|
||||||
j += 1
|
|
||||||
else:
|
|
||||||
i += 1
|
|
||||||
try:
|
|
||||||
while expected[i] == e:
|
|
||||||
i += 1
|
|
||||||
finally:
|
|
||||||
j += 1
|
|
||||||
while actual[j] == a:
|
|
||||||
j += 1
|
|
||||||
except IndexError:
|
|
||||||
missing.extend(expected[i:])
|
|
||||||
unexpected.extend(actual[j:])
|
|
||||||
break
|
|
||||||
return missing, unexpected
|
|
||||||
|
|
||||||
def unorderable_list_difference(expected, actual, ignore_duplicate=False):
|
|
||||||
"""Same behavior as sorted_list_difference but
|
|
||||||
for lists of unorderable items (like dicts).
|
|
||||||
|
|
||||||
As it does a linear search per item (remove) it
|
|
||||||
has O(n*n) performance.
|
|
||||||
"""
|
|
||||||
missing = []
|
|
||||||
unexpected = []
|
|
||||||
while expected:
|
|
||||||
item = expected.pop()
|
|
||||||
try:
|
|
||||||
actual.remove(item)
|
|
||||||
except ValueError:
|
|
||||||
missing.append(item)
|
|
||||||
if ignore_duplicate:
|
|
||||||
for lst in expected, actual:
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
lst.remove(item)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
if ignore_duplicate:
|
|
||||||
while actual:
|
|
||||||
item = actual.pop()
|
|
||||||
unexpected.append(item)
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
actual.remove(item)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
return missing, unexpected
|
|
||||||
|
|
||||||
# anything left in actual is unexpected
|
|
||||||
return missing, actual
|
|
||||||
|
|
@ -1,467 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
This module provides the XMLTestRunner class, which is heavily based on the
|
|
||||||
default TextTestRunner.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
try:
|
|
||||||
from unittest2.runner import TextTestRunner
|
|
||||||
from unittest2.runner import TextTestResult as _TextTestResult
|
|
||||||
from unittest2.result import TestResult
|
|
||||||
except ImportError:
|
|
||||||
from unittest import TestResult, _TextTestResult, TextTestRunner
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Removed in Python 3
|
|
||||||
from cStringIO import StringIO
|
|
||||||
except ImportError:
|
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
|
|
||||||
# Allow version to be detected at runtime.
|
|
||||||
from .version import __version__, __version_info__
|
|
||||||
|
|
||||||
|
|
||||||
class _DelegateIO(object):
|
|
||||||
"""
|
|
||||||
This class defines an object that captures whatever is written to
|
|
||||||
a stream or file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, delegate):
|
|
||||||
self._captured = StringIO()
|
|
||||||
self.delegate = delegate
|
|
||||||
|
|
||||||
def write(self, text):
|
|
||||||
self._captured.write(text)
|
|
||||||
self.delegate.write(text)
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
return getattr(self._captured, attr)
|
|
||||||
|
|
||||||
|
|
||||||
def testcase_name(test_method):
|
|
||||||
testcase = type(test_method)
|
|
||||||
|
|
||||||
# Ignore module name if it is '__main__'
|
|
||||||
module = testcase.__module__ + '.'
|
|
||||||
if module == '__main__.':
|
|
||||||
module = ''
|
|
||||||
result = module + testcase.__name__
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class _TestInfo(object):
|
|
||||||
"""
|
|
||||||
This class keeps useful information about the execution of a
|
|
||||||
test method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Possible test outcomes
|
|
||||||
(SUCCESS, FAILURE, ERROR, SKIP) = range(4)
|
|
||||||
|
|
||||||
def __init__(self, test_result, test_method, outcome=SUCCESS, err=None):
|
|
||||||
self.test_result = test_result
|
|
||||||
self.test_method = test_method
|
|
||||||
self.outcome = outcome
|
|
||||||
self.elapsed_time = 0
|
|
||||||
self.err = err
|
|
||||||
|
|
||||||
self.test_description = self.test_result.getDescription(test_method)
|
|
||||||
self.test_exception_info = (
|
|
||||||
'' if outcome in (self.SUCCESS, self.SKIP)
|
|
||||||
else self.test_result._exc_info_to_string(
|
|
||||||
self.err, test_method)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.test_name = testcase_name(test_method)
|
|
||||||
self.test_id = test_method.id()
|
|
||||||
|
|
||||||
def id(self):
|
|
||||||
return self.test_method.id()
|
|
||||||
|
|
||||||
def test_finished(self):
|
|
||||||
"""Save info that can only be calculated once a test has run.
|
|
||||||
"""
|
|
||||||
self.elapsed_time = \
|
|
||||||
self.test_result.stop_time - self.test_result.start_time
|
|
||||||
|
|
||||||
def get_description(self):
|
|
||||||
"""
|
|
||||||
Return a text representation of the test method.
|
|
||||||
"""
|
|
||||||
return self.test_description
|
|
||||||
|
|
||||||
def get_error_info(self):
|
|
||||||
"""
|
|
||||||
Return a text representation of an exception thrown by a test
|
|
||||||
method.
|
|
||||||
"""
|
|
||||||
return self.test_exception_info
|
|
||||||
|
|
||||||
|
|
||||||
class _XMLTestResult(_TextTestResult):
|
|
||||||
"""
|
|
||||||
A test result class that can express test results in a XML report.
|
|
||||||
|
|
||||||
Used by XMLTestRunner.
|
|
||||||
"""
|
|
||||||
def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1,
|
|
||||||
elapsed_times=True):
|
|
||||||
_TextTestResult.__init__(self, stream, descriptions, verbosity)
|
|
||||||
self.successes = []
|
|
||||||
self.callback = None
|
|
||||||
self.elapsed_times = elapsed_times
|
|
||||||
|
|
||||||
def _prepare_callback(self, test_info, target_list, verbose_str,
|
|
||||||
short_str):
|
|
||||||
"""
|
|
||||||
Appends a _TestInfo to the given target list and sets a callback
|
|
||||||
method to be called by stopTest method.
|
|
||||||
"""
|
|
||||||
target_list.append(test_info)
|
|
||||||
|
|
||||||
def callback():
|
|
||||||
"""Prints the test method outcome to the stream, as well as
|
|
||||||
the elapsed time.
|
|
||||||
"""
|
|
||||||
|
|
||||||
test_info.test_finished()
|
|
||||||
|
|
||||||
# Ignore the elapsed times for a more reliable unit testing
|
|
||||||
if not self.elapsed_times:
|
|
||||||
self.start_time = self.stop_time = 0
|
|
||||||
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.writeln(
|
|
||||||
'%s (%.3fs)' % (verbose_str, test_info.elapsed_time)
|
|
||||||
)
|
|
||||||
elif self.dots:
|
|
||||||
self.stream.write(short_str)
|
|
||||||
self.callback = callback
|
|
||||||
|
|
||||||
def startTest(self, test):
|
|
||||||
"""
|
|
||||||
Called before execute each test method.
|
|
||||||
"""
|
|
||||||
self.start_time = time.time()
|
|
||||||
TestResult.startTest(self, test)
|
|
||||||
|
|
||||||
if self.showAll:
|
|
||||||
self.stream.write(' ' + self.getDescription(test))
|
|
||||||
self.stream.write(" ... ")
|
|
||||||
|
|
||||||
def stopTest(self, test):
|
|
||||||
"""
|
|
||||||
Called after execute each test method.
|
|
||||||
"""
|
|
||||||
_TextTestResult.stopTest(self, test)
|
|
||||||
self.stop_time = time.time()
|
|
||||||
|
|
||||||
if self.callback and callable(self.callback):
|
|
||||||
self.callback()
|
|
||||||
self.callback = None
|
|
||||||
|
|
||||||
def addSuccess(self, test):
|
|
||||||
"""
|
|
||||||
Called when a test executes successfully.
|
|
||||||
"""
|
|
||||||
self._prepare_callback(
|
|
||||||
_TestInfo(self, test), self.successes, 'OK', '.'
|
|
||||||
)
|
|
||||||
|
|
||||||
def addFailure(self, test, err):
|
|
||||||
"""
|
|
||||||
Called when a test method fails.
|
|
||||||
"""
|
|
||||||
testinfo = _TestInfo(self, test, _TestInfo.ERROR, err)
|
|
||||||
self.errors.append((
|
|
||||||
testinfo,
|
|
||||||
self._exc_info_to_string(err, test)
|
|
||||||
))
|
|
||||||
self._prepare_callback(testinfo, [], 'FAIL', 'F')
|
|
||||||
|
|
||||||
def addError(self, test, err):
|
|
||||||
"""
|
|
||||||
Called when a test method raises an error.
|
|
||||||
"""
|
|
||||||
testinfo = _TestInfo(self, test, _TestInfo.ERROR, err)
|
|
||||||
self.errors.append((
|
|
||||||
testinfo,
|
|
||||||
self._exc_info_to_string(err, test)
|
|
||||||
))
|
|
||||||
self._prepare_callback(testinfo, [], 'ERROR', 'E')
|
|
||||||
|
|
||||||
def addSkip(self, test, reason):
|
|
||||||
"""
|
|
||||||
Called when a test method was skipped.
|
|
||||||
"""
|
|
||||||
testinfo = _TestInfo(self, test, _TestInfo.SKIP, reason)
|
|
||||||
self.skipped.append((testinfo, reason))
|
|
||||||
self._prepare_callback(testinfo, [], 'SKIP', 'S')
|
|
||||||
|
|
||||||
def printErrorList(self, flavour, errors):
|
|
||||||
"""
|
|
||||||
Writes information about the FAIL or ERROR to the stream.
|
|
||||||
"""
|
|
||||||
for test_info, error in errors:
|
|
||||||
self.stream.writeln(self.separator1)
|
|
||||||
self.stream.writeln(
|
|
||||||
'%s [%.3fs]: %s' % (flavour, test_info.elapsed_time,
|
|
||||||
test_info.get_description())
|
|
||||||
)
|
|
||||||
self.stream.writeln(self.separator2)
|
|
||||||
self.stream.writeln('%s' % test_info.get_error_info())
|
|
||||||
|
|
||||||
def _get_info_by_testcase(self, outsuffix):
|
|
||||||
"""
|
|
||||||
Organizes test results by TestCase module. This information is
|
|
||||||
used during the report generation, where a XML report will be created
|
|
||||||
for each TestCase.
|
|
||||||
"""
|
|
||||||
tests_by_testcase = {}
|
|
||||||
|
|
||||||
for tests in (self.successes, self.failures, self.errors, self.skipped):
|
|
||||||
for test_info in tests:
|
|
||||||
if isinstance(test_info, tuple):
|
|
||||||
# This is a skipped, error or a failure test case
|
|
||||||
test_info = test_info[0]
|
|
||||||
testcase_name = test_info.test_name
|
|
||||||
if not testcase_name in tests_by_testcase:
|
|
||||||
tests_by_testcase[testcase_name] = []
|
|
||||||
tests_by_testcase[testcase_name].append(test_info)
|
|
||||||
|
|
||||||
return tests_by_testcase
|
|
||||||
|
|
||||||
def _report_testsuite(suite_name, outsuffix, tests, xml_document):
|
|
||||||
"""
|
|
||||||
Appends the testsuite section to the XML document.
|
|
||||||
"""
|
|
||||||
testsuite = xml_document.createElement('testsuite')
|
|
||||||
xml_document.appendChild(testsuite)
|
|
||||||
|
|
||||||
testsuite.setAttribute('name', "%s-%s" % (suite_name, outsuffix))
|
|
||||||
testsuite.setAttribute('tests', str(len(tests)))
|
|
||||||
|
|
||||||
testsuite.setAttribute(
|
|
||||||
'time', '%.3f' % sum(map(lambda e: e.elapsed_time, tests))
|
|
||||||
)
|
|
||||||
failures = filter(lambda e: e.outcome == _TestInfo.FAILURE, tests)
|
|
||||||
testsuite.setAttribute('failures', str(len(list(failures))))
|
|
||||||
|
|
||||||
errors = filter(lambda e: e.outcome == _TestInfo.ERROR, tests)
|
|
||||||
testsuite.setAttribute('errors', str(len(list(errors))))
|
|
||||||
|
|
||||||
return testsuite
|
|
||||||
|
|
||||||
_report_testsuite = staticmethod(_report_testsuite)
|
|
||||||
|
|
||||||
def _test_method_name(test_id):
|
|
||||||
"""
|
|
||||||
Returns the test method name.
|
|
||||||
"""
|
|
||||||
return test_id.split('.')[-1]
|
|
||||||
|
|
||||||
_test_method_name = staticmethod(_test_method_name)
|
|
||||||
|
|
||||||
def _report_testcase(suite_name, test_result, xml_testsuite, xml_document):
|
|
||||||
"""
|
|
||||||
Appends a testcase section to the XML document.
|
|
||||||
"""
|
|
||||||
testcase = xml_document.createElement('testcase')
|
|
||||||
xml_testsuite.appendChild(testcase)
|
|
||||||
|
|
||||||
testcase.setAttribute('classname', suite_name)
|
|
||||||
testcase.setAttribute(
|
|
||||||
'name', _XMLTestResult._test_method_name(test_result.test_id)
|
|
||||||
)
|
|
||||||
testcase.setAttribute('time', '%.3f' % test_result.elapsed_time)
|
|
||||||
|
|
||||||
if (test_result.outcome != _TestInfo.SUCCESS):
|
|
||||||
elem_name = ('failure', 'error', 'skipped')[test_result.outcome - 1]
|
|
||||||
failure = xml_document.createElement(elem_name)
|
|
||||||
testcase.appendChild(failure)
|
|
||||||
if test_result.outcome != _TestInfo.SKIP:
|
|
||||||
failure.setAttribute('type', test_result.err[0].__name__)
|
|
||||||
failure.setAttribute('message', str(test_result.err[1]))
|
|
||||||
error_info = str(test_result.get_error_info())
|
|
||||||
failureText = xml_document.createCDATASection(error_info)
|
|
||||||
failure.appendChild(failureText)
|
|
||||||
else:
|
|
||||||
failure.setAttribute('type', 'skip')
|
|
||||||
failure.setAttribute('message', test_result.err)
|
|
||||||
|
|
||||||
|
|
||||||
_report_testcase = staticmethod(_report_testcase)
|
|
||||||
|
|
||||||
def _report_output(test_runner, xml_testsuite, xml_document):
|
|
||||||
"""
|
|
||||||
Appends the system-out and system-err sections to the XML document.
|
|
||||||
"""
|
|
||||||
systemout = xml_document.createElement('system-out')
|
|
||||||
xml_testsuite.appendChild(systemout)
|
|
||||||
|
|
||||||
systemout_text = xml_document.createCDATASection(sys.stdout.getvalue())
|
|
||||||
systemout.appendChild(systemout_text)
|
|
||||||
|
|
||||||
systemerr = xml_document.createElement('system-err')
|
|
||||||
xml_testsuite.appendChild(systemerr)
|
|
||||||
|
|
||||||
systemerr_text = xml_document.createCDATASection(sys.stderr.getvalue())
|
|
||||||
systemerr.appendChild(systemerr_text)
|
|
||||||
|
|
||||||
_report_output = staticmethod(_report_output)
|
|
||||||
|
|
||||||
def generate_reports(self, test_runner):
|
|
||||||
"""
|
|
||||||
Generates the XML reports to a given XMLTestRunner object.
|
|
||||||
"""
|
|
||||||
from xml.dom.minidom import Document
|
|
||||||
all_results = self._get_info_by_testcase(test_runner.outsuffix)
|
|
||||||
|
|
||||||
if (isinstance(test_runner.output, str) and not
|
|
||||||
os.path.exists(test_runner.output)):
|
|
||||||
os.makedirs(test_runner.output)
|
|
||||||
|
|
||||||
for suite, tests in all_results.items():
|
|
||||||
doc = Document()
|
|
||||||
|
|
||||||
# Build the XML file
|
|
||||||
testsuite = _XMLTestResult._report_testsuite(
|
|
||||||
suite, test_runner.outsuffix, tests, doc
|
|
||||||
)
|
|
||||||
for test in tests:
|
|
||||||
_XMLTestResult._report_testcase(suite, test, testsuite, doc)
|
|
||||||
_XMLTestResult._report_output(test_runner, testsuite, doc)
|
|
||||||
xml_content = doc.toprettyxml(indent='\t')
|
|
||||||
|
|
||||||
if type(test_runner.output) is str:
|
|
||||||
report_file = open(
|
|
||||||
'%s%sTEST-%s-%s.xml' % (
|
|
||||||
test_runner.output, os.sep, suite,
|
|
||||||
test_runner.outsuffix
|
|
||||||
), 'w'
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
report_file.write(xml_content)
|
|
||||||
finally:
|
|
||||||
report_file.close()
|
|
||||||
else:
|
|
||||||
# Assume that test_runner.output is a stream
|
|
||||||
test_runner.output.write(xml_content)
|
|
||||||
|
|
||||||
|
|
||||||
class XMLTestRunner(TextTestRunner):
|
|
||||||
"""
|
|
||||||
A test runner class that outputs the results in JUnit like XML files.
|
|
||||||
"""
|
|
||||||
def __init__(self, output='.', outsuffix=None, stream=sys.stderr,
|
|
||||||
descriptions=True, verbosity=1, elapsed_times=True):
|
|
||||||
TextTestRunner.__init__(self, stream, descriptions, verbosity)
|
|
||||||
self.verbosity = verbosity
|
|
||||||
self.output = output
|
|
||||||
if outsuffix:
|
|
||||||
self.outsuffix = outsuffix
|
|
||||||
else:
|
|
||||||
self.outsuffix = time.strftime("%Y%m%d%H%M%S")
|
|
||||||
self.elapsed_times = elapsed_times
|
|
||||||
|
|
||||||
def _make_result(self):
|
|
||||||
"""
|
|
||||||
Creates a TestResult object which will be used to store
|
|
||||||
information about the executed tests.
|
|
||||||
"""
|
|
||||||
return _XMLTestResult(
|
|
||||||
self.stream, self.descriptions, self.verbosity, self.elapsed_times
|
|
||||||
)
|
|
||||||
|
|
||||||
def _patch_standard_output(self):
|
|
||||||
"""
|
|
||||||
Replaces stdout and stderr streams with string-based streams
|
|
||||||
in order to capture the tests' output.
|
|
||||||
"""
|
|
||||||
sys.stdout = _DelegateIO(sys.stdout)
|
|
||||||
sys.stderr = _DelegateIO(sys.stderr)
|
|
||||||
|
|
||||||
def _restore_standard_output(self):
|
|
||||||
"""
|
|
||||||
Restores stdout and stderr streams.
|
|
||||||
"""
|
|
||||||
sys.stdout = sys.stdout.delegate
|
|
||||||
sys.stderr = sys.stderr.delegate
|
|
||||||
|
|
||||||
def run(self, test):
|
|
||||||
"""
|
|
||||||
Runs the given test case or test suite.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# Prepare the test execution
|
|
||||||
self._patch_standard_output()
|
|
||||||
result = self._make_result()
|
|
||||||
|
|
||||||
# Print a nice header
|
|
||||||
self.stream.writeln()
|
|
||||||
self.stream.writeln('Running tests...')
|
|
||||||
self.stream.writeln(result.separator2)
|
|
||||||
|
|
||||||
# Execute tests
|
|
||||||
start_time = time.time()
|
|
||||||
test(result)
|
|
||||||
stop_time = time.time()
|
|
||||||
time_taken = stop_time - start_time
|
|
||||||
|
|
||||||
# Print results
|
|
||||||
result.printErrors()
|
|
||||||
self.stream.writeln(result.separator2)
|
|
||||||
run = result.testsRun
|
|
||||||
self.stream.writeln("Ran %d test%s in %.3fs" % (
|
|
||||||
run, run != 1 and "s" or "", time_taken)
|
|
||||||
)
|
|
||||||
self.stream.writeln()
|
|
||||||
|
|
||||||
expectedFails = unexpectedSuccesses = skipped = 0
|
|
||||||
try:
|
|
||||||
results = map(len, (result.expectedFailures,
|
|
||||||
result.unexpectedSuccesses,
|
|
||||||
result.skipped))
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
expectedFails, unexpectedSuccesses, skipped = results
|
|
||||||
|
|
||||||
# Error traces
|
|
||||||
infos = []
|
|
||||||
if not result.wasSuccessful():
|
|
||||||
self.stream.write("FAILED")
|
|
||||||
failed, errored = map(len, (result.failures, result.errors))
|
|
||||||
if failed:
|
|
||||||
infos.append("failures={0}".format(failed))
|
|
||||||
if errored:
|
|
||||||
infos.append("errors={0}".format(errored))
|
|
||||||
else:
|
|
||||||
self.stream.write("OK")
|
|
||||||
|
|
||||||
if skipped:
|
|
||||||
infos.append("skipped={0}".format(skipped))
|
|
||||||
if expectedFails:
|
|
||||||
infos.append("expected failures={0}".format(expectedFails))
|
|
||||||
if unexpectedSuccesses:
|
|
||||||
infos.append("unexpected successes={0}".fornat(unexpectedSuccesses))
|
|
||||||
|
|
||||||
if infos:
|
|
||||||
self.stream.writeln(" ({0})".format(", ".join(infos)))
|
|
||||||
else:
|
|
||||||
self.stream.write("\n")
|
|
||||||
|
|
||||||
# Generate reports
|
|
||||||
self.stream.writeln()
|
|
||||||
self.stream.writeln('Generating XML reports...')
|
|
||||||
result.generate_reports(self)
|
|
||||||
finally:
|
|
||||||
self._restore_standard_output()
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
xmlrunner.version
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Runtime library version information.
|
|
||||||
|
|
||||||
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
|
|
||||||
:copyright: © 2013 Pedro Algarvio.
|
|
||||||
:license: LGPL, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__version_info__ = (1, 7, 0)
|
|
||||||
__version__ = '.'.join(map(str, __version_info__))
|
|
||||||
Loading…
Reference in New Issue