diff options
author | Benjamin Peterson <benjamin@python.org> | 2009-10-04 14:49:41 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2009-10-04 14:49:41 (GMT) |
commit | 4ac9ce4f9a33a330a555ae8015e2f2ae2780fafb (patch) | |
tree | b9bbcfd8f4aae362d8335d13e592f605b674ea19 /Lib/unittest | |
parent | bd27aef8a0f776cc72387be31e1e74ecbcbbdf54 (diff) | |
download | cpython-4ac9ce4f9a33a330a555ae8015e2f2ae2780fafb.zip cpython-4ac9ce4f9a33a330a555ae8015e2f2ae2780fafb.tar.gz cpython-4ac9ce4f9a33a330a555ae8015e2f2ae2780fafb.tar.bz2 |
Merged revisions 74779-74786,74793,74795,74811,74860-74861,74863,74876,74886,74896,74901,74903,74908,74912,74930,74933,74943,74946,74952-74955,75015,75019,75032,75068,75076,75095,75098,75102,75129,75139,75230 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r74779 | michael.foord | 2009-09-13 11:13:36 -0500 (Sun, 13 Sep 2009) | 1 line
Change to tutorial wording for reading text / binary files on Windows. Issue #6301.
........
r74780 | michael.foord | 2009-09-13 11:40:02 -0500 (Sun, 13 Sep 2009) | 1 line
Objects that compare equal automatically pass or fail assertAlmostEqual and assertNotAlmostEqual tests on unittest.TestCase. Issue 6567.
........
r74781 | michael.foord | 2009-09-13 11:46:19 -0500 (Sun, 13 Sep 2009) | 1 line
Note that sys._getframe is not guaranteed to exist in all implementations of Python, and a corresponding note in inspect.currentframe. Issue 6712.
........
r74782 | michael.foord | 2009-09-13 12:07:46 -0500 (Sun, 13 Sep 2009) | 1 line
Tutorial tweaks. Issue 6849.
........
r74783 | michael.foord | 2009-09-13 12:28:35 -0500 (Sun, 13 Sep 2009) | 1 line
unittest.TestLoader.loadTestsFromName honors the loader suiteClass attribute. Issue 6866.
........
r74784 | georg.brandl | 2009-09-13 13:15:07 -0500 (Sun, 13 Sep 2009) | 1 line
Typo fix.
........
r74785 | michael.foord | 2009-09-13 14:07:03 -0500 (Sun, 13 Sep 2009) | 1 line
Test discovery in unittest will only attempt to import modules that are importable; i.e. their names are valid Python identifiers. If an import fails during discovery this will be recorded as an error and test discovery will continue. Issue 6568.
........
r74786 | michael.foord | 2009-09-13 14:08:18 -0500 (Sun, 13 Sep 2009) | 1 line
Remove an extraneous space in unittest documentation.
........
r74793 | georg.brandl | 2009-09-14 09:50:47 -0500 (Mon, 14 Sep 2009) | 1 line
#6908: fix association of hashlib hash attributes.
........
r74795 | benjamin.peterson | 2009-09-14 22:36:26 -0500 (Mon, 14 Sep 2009) | 1 line
Py_SetPythonHome uses static storage #6913
........
r74811 | georg.brandl | 2009-09-15 15:26:59 -0500 (Tue, 15 Sep 2009) | 1 line
Add Armin Ronacher.
........
r74860 | benjamin.peterson | 2009-09-16 21:46:54 -0500 (Wed, 16 Sep 2009) | 1 line
kill bare except
........
r74861 | benjamin.peterson | 2009-09-16 22:18:28 -0500 (Wed, 16 Sep 2009) | 1 line
pep 8 defaults
........
r74863 | benjamin.peterson | 2009-09-16 22:27:33 -0500 (Wed, 16 Sep 2009) | 1 line
rationalize a bit
........
r74876 | georg.brandl | 2009-09-17 11:15:53 -0500 (Thu, 17 Sep 2009) | 1 line
#6932: remove paragraph that advises relying on __del__ being called.
........
r74886 | benjamin.peterson | 2009-09-17 16:33:46 -0500 (Thu, 17 Sep 2009) | 1 line
use macros
........
r74896 | georg.brandl | 2009-09-18 02:22:41 -0500 (Fri, 18 Sep 2009) | 1 line
#6936: for interactive use, quit() is just fine.
........
r74901 | georg.brandl | 2009-09-18 04:14:52 -0500 (Fri, 18 Sep 2009) | 1 line
#6905: use better exception messages in inspect when the argument is of the wrong type.
........
r74903 | georg.brandl | 2009-09-18 04:18:27 -0500 (Fri, 18 Sep 2009) | 1 line
#6938: "ident" is always a string, so use a format code which works.
........
r74908 | georg.brandl | 2009-09-18 08:57:11 -0500 (Fri, 18 Sep 2009) | 1 line
Use str.format() to fix beginner's mistake with %-style string formatting.
........
r74912 | georg.brandl | 2009-09-18 11:19:56 -0500 (Fri, 18 Sep 2009) | 1 line
Optimize optimization and fix method name in docstring.
........
r74930 | georg.brandl | 2009-09-18 16:21:41 -0500 (Fri, 18 Sep 2009) | 1 line
#6925: rewrite docs for locals() and vars() a bit.
........
r74933 | georg.brandl | 2009-09-18 16:35:59 -0500 (Fri, 18 Sep 2009) | 1 line
#6930: clarify description about byteorder handling in UTF decoder routines.
........
r74943 | georg.brandl | 2009-09-19 02:35:07 -0500 (Sat, 19 Sep 2009) | 1 line
#6944: the argument to PyArg_ParseTuple should be a tuple, otherwise a SystemError is set. Also clean up another usage of PyArg_ParseTuple.
........
r74946 | georg.brandl | 2009-09-19 03:43:16 -0500 (Sat, 19 Sep 2009) | 1 line
Update bug tracker reference.
........
r74952 | georg.brandl | 2009-09-19 05:42:34 -0500 (Sat, 19 Sep 2009) | 1 line
#6946: fix duplicate index entries for datetime classes.
........
r74953 | georg.brandl | 2009-09-19 07:04:16 -0500 (Sat, 19 Sep 2009) | 1 line
Fix references to threading.enumerate().
........
r74954 | georg.brandl | 2009-09-19 08:13:56 -0500 (Sat, 19 Sep 2009) | 1 line
Add Doug.
........
r74955 | georg.brandl | 2009-09-19 08:20:49 -0500 (Sat, 19 Sep 2009) | 1 line
Add Mark Summerfield.
........
r75015 | georg.brandl | 2009-09-22 05:55:08 -0500 (Tue, 22 Sep 2009) | 1 line
Fix encoding name.
........
r75019 | vinay.sajip | 2009-09-22 12:23:41 -0500 (Tue, 22 Sep 2009) | 1 line
Fixed a typo, and added sections on optimization and using arbitrary objects as messages.
........
r75032 | benjamin.peterson | 2009-09-22 17:15:28 -0500 (Tue, 22 Sep 2009) | 1 line
fix typos/rephrase
........
r75068 | benjamin.peterson | 2009-09-25 21:57:59 -0500 (Fri, 25 Sep 2009) | 1 line
comment out ugly xxx
........
r75076 | vinay.sajip | 2009-09-26 09:53:32 -0500 (Sat, 26 Sep 2009) | 1 line
Tidied up name of parameter in StreamHandler
........
r75095 | michael.foord | 2009-09-27 14:15:41 -0500 (Sun, 27 Sep 2009) | 1 line
Test creation moved from TestProgram.parseArgs to TestProgram.createTests exclusively. Issue 6956.
........
r75098 | michael.foord | 2009-09-27 15:08:23 -0500 (Sun, 27 Sep 2009) | 1 line
Documentation improvement for load_tests protocol in unittest. Issue 6515.
........
r75102 | skip.montanaro | 2009-09-27 21:12:27 -0500 (Sun, 27 Sep 2009) | 3 lines
Patch from Thomas Barr so that csv.Sniffer will set doublequote property.
Closes issue 6606.
........
r75129 | vinay.sajip | 2009-09-29 02:08:54 -0500 (Tue, 29 Sep 2009) | 1 line
Issue #7014: logging: Improved IronPython 2.6 compatibility.
........
r75139 | raymond.hettinger | 2009-09-29 13:53:24 -0500 (Tue, 29 Sep 2009) | 3 lines
Issue 7008: Better document str.title and show how to work around the apostrophe problem.
........
r75230 | benjamin.peterson | 2009-10-04 08:38:38 -0500 (Sun, 04 Oct 2009) | 1 line
test logging
........
Diffstat (limited to 'Lib/unittest')
-rw-r--r-- | Lib/unittest/case.py | 10 | ||||
-rw-r--r-- | Lib/unittest/loader.py | 63 | ||||
-rw-r--r-- | Lib/unittest/main.py | 13 | ||||
-rw-r--r-- | Lib/unittest/suite.py | 3 |
4 files changed, 65 insertions, 24 deletions
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 48f3ef1..77ca278 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -468,7 +468,13 @@ class TestCase(object): Note that decimal places (from zero) are usually not the same as significant digits (measured from the most signficant digit). + + If the two objects compare equal then they will automatically + compare almost equal. """ + if first == second: + # shortcut for ite + return if round(abs(second-first), places) != 0: standardMsg = '%r != %r within %r places' % (first, second, places) msg = self._formatMessage(msg, standardMsg) @@ -481,8 +487,10 @@ class TestCase(object): Note that decimal places (from zero) are usually not the same as significant digits (measured from the most signficant digit). + + Objects that are equal automatically fail. """ - if round(abs(second-first), places) == 0: + if (first == second) or round(abs(second-first), places) == 0: standardMsg = '%r == %r within %r places' % (first, second, places) msg = self._formatMessage(msg, standardMsg) raise self.failureException(msg) diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py index c687b1b..68f954c 100644 --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -1,7 +1,9 @@ """Loading unittests.""" import os +import re import sys +import traceback import types from fnmatch import fnmatch @@ -9,6 +11,26 @@ from fnmatch import fnmatch from . import case, suite, util +# 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() + + def testImportFailure(self): + raise ImportError(message) + attrs = {name: testImportFailure} + ModuleImportFailure = type('ModuleImportFailure', (case.TestCase,), attrs) + return suiteClass((ModuleImportFailure(name),)) + + class TestLoader(object): """ This class is responsible for loading tests according to various criteria @@ -79,7 +101,7 @@ class TestLoader(object): inst = parent(name) # static methods follow a different path if not isinstance(getattr(inst, name), types.FunctionType): - return suite.TestSuite([inst]) + return self.suiteClass([inst]) elif isinstance(obj, suite.TestSuite): return obj if hasattr(obj, '__call__'): @@ -87,7 +109,7 @@ class TestLoader(object): if isinstance(test, suite.TestSuite): return test elif isinstance(test, case.TestCase): - return suite.TestSuite([test]) + return self.suiteClass([test]) else: raise TypeError("calling %s returned %s, not a test" % (obj, test)) @@ -156,17 +178,17 @@ class TestLoader(object): tests = list(self._find_tests(start_dir, pattern)) return self.suiteClass(tests) - - def _get_module_from_path(self, path): - """Load a module from a path relative to the top-level directory - of a project. Used by discovery.""" + def _get_name_from_path(self, path): path = os.path.splitext(os.path.normpath(path))[0] - relpath = os.path.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" + _relpath = os.path.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 - name = relpath.replace(os.path.sep, '.') + def _get_module_from_name(self, name): __import__(name) return sys.modules[name] @@ -176,14 +198,20 @@ class TestLoader(object): for path in paths: full_path = os.path.join(start_dir, path) - # what about __init__.pyc or pyo (etc) - # we would need to avoid loading the same tests multiple times - # from '.py', '.pyc' *and* '.pyo' - if os.path.isfile(full_path) and path.lower().endswith('.py'): + if os.path.isfile(full_path): + if not VALID_MODULE_NAME.match(path): + # valid Python identifiers only + continue + if fnmatch(path, pattern): # if the test file matches, load it - module = self._get_module_from_path(full_path) - yield self.loadTestsFromModule(module) + 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: + yield self.loadTestsFromModule(module) elif os.path.isdir(full_path): if not os.path.isfile(os.path.join(full_path, '__init__.py')): continue @@ -192,7 +220,8 @@ class TestLoader(object): tests = None if fnmatch(path, pattern): # only check load_tests if the package directory itself matches the filter - package = self._get_module_from_path(full_path) + 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) diff --git a/Lib/unittest/main.py b/Lib/unittest/main.py index 4a5c22b..e6237b0 100644 --- a/Lib/unittest/main.py +++ b/Lib/unittest/main.py @@ -109,9 +109,9 @@ class TestProgram(object): if opt in ('-v','--verbose'): self.verbosity = 2 if len(args) == 0 and self.defaultTest is None: - self.test = self.testLoader.loadTestsFromModule(self.module) - return - if len(args) > 0: + # 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 ... @@ -123,8 +123,11 @@ class TestProgram(object): self.usageExit(msg) def createTests(self): - self.test = self.testLoader.loadTestsFromNames(self.testNames, - self.module) + 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 diff --git a/Lib/unittest/suite.py b/Lib/unittest/suite.py index baf8414..8672aab 100644 --- a/Lib/unittest/suite.py +++ b/Lib/unittest/suite.py @@ -1,6 +1,7 @@ """TestSuite""" from . import case +from . import util class TestSuite(object): @@ -17,7 +18,7 @@ class TestSuite(object): self.addTests(tests) def __repr__(self): - return "<%s tests=%s>" % (_strclass(self.__class__), list(self)) + return "<%s tests=%s>" % (util.strclass(self.__class__), list(self)) def __eq__(self, other): if not isinstance(other, self.__class__): |