Changeset 21
- Timestamp:
- Mon Apr 10 21:50:10 2006
- Files:
-
- trunk/st/unit_tests (deleted)
- trunk/unit_tests (added)
- trunk/unit_tests/mock.py (added)
- trunk/unit_tests/test_utils.py (added)
- trunk/unit_tests/test_tools.py (added)
- trunk/unit_tests/test_plugin_interfaces.py (added)
- trunk/unit_tests/test_importer.py (added)
- trunk/unit_tests/test_config.py (added)
- trunk/unit_tests/test_loader.py (added)
- trunk/unit_tests/test_inspector.py (added)
- trunk/unit_tests/test_result.py (added)
- trunk/unit_tests/test_selector.py (added)
- trunk/unit_tests/test_selector_plugins.py (added)
- trunk/unit_tests/test_proxy.py (added)
- trunk/unit_tests/test_plugins.py (added)
- trunk/unit_tests/test_collector.py (added)
- trunk/unit_tests/support (added)
- trunk/unit_tests/support/other (added)
- trunk/unit_tests/support/other/file.txt (added)
- trunk/unit_tests/support/foo (added)
- trunk/unit_tests/support/foo/tests (added)
- trunk/unit_tests/support/foo/tests/dir_test_file.py (added)
- trunk/unit_tests/support/foo/bar (added)
- trunk/unit_tests/support/foo/bar/__init__.py (added)
- trunk/unit_tests/support/foo/bar/buz.py (added)
- trunk/unit_tests/support/foo/__init__.py (added)
- trunk/unit_tests/support/foo/doctests.txt (added)
- trunk/unit_tests/support/foo/test_foo.py (added)
- trunk/unit_tests/support/test.py (added)
- trunk/unit_tests/support/test-dir (added)
- trunk/unit_tests/support/test-dir/test.py (added)
- trunk/unit_tests/test_lazy_suite.py (added)
- trunk/nose/core.py (modified) (diff)
- trunk/nose/suite.py (modified) (diff)
- trunk/nose/plugins/doctests.py (modified) (diff)
- trunk/nose/plugins/base.py (modified) (diff)
- trunk/nose/case.py (modified) (diff)
- trunk/nose/util.py (modified) (diff)
- trunk/nose/result.py (modified) (diff)
- trunk/nose/__init__.py (modified) (diff)
- trunk/nose/selector.py (modified) (diff)
- trunk/nose/tools.py (modified) (diff)
- trunk/nose/importer.py (modified) (diff)
- trunk/nose/proxy.py (added)
- trunk/nose/inspector.py (modified) (diff)
- trunk/nose/loader.py (modified) (diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
trunk/nose/core.py
r20 r21 10 10 11 11 from nose.plugins import load_plugins, call_plugins 12 from nose.result import install_patch, start_capture, end_capture, \ 13 TextTestResult 12 from nose.result import start_capture, end_capture, TextTestResult 14 13 from nose.config import Config 15 14 from nose.loader import defaultTestLoader 15 from nose.proxy import ResultProxy, ResultProxySuite 16 16 from nose.selector import defaultSelector 17 from nose.suite import LazySuite , ResultProxySuite17 from nose.suite import LazySuite 17 17 from nose.util import absdir, absfile, try_run 18 18 … … 60 60 # FIXME somehow restrict plugin methods 61 61 conf = configure(env=os.environ) 62 ResultProxy.conf = conf 62 63 loader = defaultTestLoader(conf) 63 64 loader.suiteClass = ResultProxySuite … … 208 209 return self.success 209 210 210 211 211 def configure(argv=None, env=None, help=False): 212 212 """Configure the nose running environment. Execute configure before … … 317 317 if conf.where is None: 318 318 raise Exception("Working directory %s not found, or " 319 "not a directory") 319 "not a directory" % options.where) 319 319 log.info("Looking for tests in %s", conf.where) 320 320 … … 339 339 return conf 340 340 341 342 341 def configure_logging(options): 343 342 loggers = [ '', 'nose', 'nose.case', 'nose.core', 'nose.importer', … … 361 360 elif options.verbosity >= 3: 362 361 lvl = logging.INFO 363 for logger in loggers: 364 l = logging.getLogger(logger) 365 l.setLevel(lvl) 362 363 logging.getLogger('').setLevel(lvl) 366 364 367 365 # individual overrides … … 371 369 l = logging.getLogger(logger) 372 370 l.setLevel(logging.DEBUG) 373 374 371 375 372 def main(*arg, **kw): … … 385 382 """ 386 383 return TestProgram(*arg, **kw).success 387 388 389 # FIXME move to tools? 390 def with_setup(setup=None, teardown=None): 391 """Decorator to add setup and/or teardown methods to a test function 392 393 @with_setup(setup, teardown) 394 def test_something(): 395 # ... 396 """ 397 def decorate(func, setup=setup, teardown=teardown): 398 if setup: 399 func.setup = setup 400 if teardown: 401 func.teardown = teardown 402 return func 403 return decorate 404 405 384 406 385 if __name__ == '__main__': 407 run_exit()386 main() -
trunk/nose/suite.py
r20 r21 2 2 import sys 3 3 import unittest 4 from nose.case import MethodTestCase 4 5 from nose.config import Config 5 6 from nose.importer import _import … … 8 9 log = logging.getLogger('nose.suite') 9 10 11 10 12 class LazySuite(unittest.TestSuite): 11 13 … … 62 64 63 65 64 class ResultProxySuite(LazySuite): 65 pass 66 66 class GeneratorMethodTestSuite(LazySuite): 67 67 68 def __init__(self, cls, method): 69 self.cls = cls 70 self.method = method 71 72 def loadtests(self): 73 inst = self.cls() 74 suite = getattr(inst, self.method) 75 76 for test in suite(): 77 try: 78 test_method, arg = (test[0], test[1:]) 79 except ValueError: 80 test_method, arg = test[0], tuple() 81 log.debug('test_method: %s, arg: %s', test_method, arg) 82 if callable(test_method): 83 name = test_method.__name__ 84 else: 85 name = test_method 86 yield MethodTestCase(self.cls, name, self.method, *arg) 87 88 68 89 class TestClass(LazySuite): 69 90 """Collects tests from a class. … … 109 130 self.module = None 110 131 super(TestModule, self).__init__(loadtests, conf) 111 self.plugins = self.conf.plugins112 132 113 133 def __repr__(self): -
trunk/nose/plugins/doctests.py
r20 r21 31 31 def add_options(self, parser, env=os.environ): 32 32 super(Doctest, self).add_options(parser, env) 33 parser.add_option('--doctest-tests', action='store_true', 34 dest='doctest_tests', 35 default=env.get('NOSE_DOCTEST_TESTS'), 36 help="Also look for doctests in test modules") 33 37 try: 34 38 # 2.4 or better supports loading tests from non-modules … … 44 48 def configure(self, options, config): 45 49 super(Doctest, self).configure(options, config) 50 self.doctest_tests = options.doctest_tests 46 51 try: 47 52 self.extension = self.tolist(options.doctestExtension) … … 83 88 if name == '__init__.py': 84 89 return False 85 # FIXME don't think we need include/exclude checks here 86 return ((not self.conf.testMatch.search(name) 90 # FIXME don't think we need include/exclude checks here? 91 return ((self.doctest_tests or not self.conf.testMatch.search(name) 87 92 or (self.conf.include is not None 88 93 and self.conf.include.search(name))) -
trunk/nose/plugins/base.py
r20 r21 240 240 pass 241 241 242 def loadTestsFromName(self, name, package=None, importPath=None):242 def loadTestsFromName(self, name, module=None, importPath=None): 242 242 """Return tests in this file or module. Return None if you are not able 243 243 to load any tests, or an iterable if you are. May be a … … 249 249 The test name. May be a file or module name plus a test 250 250 callable. Use split_test_name to split into parts. 251 * package: 252 Package in which the file is found 251 * module: 252 Module in which the file is found 253 253 * importPath: 254 254 Path from which file (must be a python module) was found … … 256 256 pass 257 257 258 def loadTestsFromPath(self, path, package=None, importPath=None):258 def loadTestsFromPath(self, path, module=None, importPath=None): 258 258 """Return tests in this file or directory. Return None if you are not 259 259 able to load any tests, or an iterable if you are. May be a … … 264 264 * path: 265 265 The full path to the file or directory. 266 * package: 267 Package in which the file/dir is found 266 * module: 267 Module in which the file/dir is found 268 268 * importPath: 269 269 Path from which file (must be a python module) was found -
trunk/nose/case.py
r17 r21 73 73 name = "%s.%s" % (self.testFunc.__module__, name) 74 74 75 if self._seen.has_key(name): 75 if self._seen.has_key(name) and self.fromDirectory is not None: 75 75 # already seen this exact test name; put the 76 76 # module dir in front to disambiguate the tests … … 87 87 class MethodTestCase(unittest.TestCase): 88 88 """Test case that wraps one method in a test class. 89 """ 90 def __init__(self, cls, method): 89 """ 90 def __init__(self, cls, method, method_desc=None, *arg): 91 91 self.cls = cls 92 92 self.method = method 93 self.method_desc = method_desc 93 94 self.testInstance = self.cls() 94 self.testCase = getattr(self.testInstance, self.method) 95 self.testCase = getattr(self.testInstance, method) 96 self.arg = arg 97 log.debug('Test case: %s%s', self.testCase, self.arg) 95 98 super(MethodTestCase, self).__init__() 96 99 97 100 def __str__(self): 98 101 return self.id() 99 102 103 def desc(self): 104 if self.method_desc is not None: 105 desc = self.method_desc 106 else: 107 desc = self.method 108 if self.arg: 109 desc = "%s:%s" % (desc, self.arg) 110 return desc 111 100 112 def id(self): 101 113 return "%s.%s.%s" % (self.cls.__module__, 102 114 self.cls.__name__, 103 self. method)115 self.desc()) 103 115 104 116 def setUp(self): … … 111 123 112 124 def runTest(self): 113 self.testCase() 125 self.testCase(*self.arg) 113 125 114 126 def tearDown(self): … … 128 140 self.testCase.__doc__) 129 141 return None 142 143 -
trunk/nose/util.py
r18 r21 10 10 log = logging.getLogger('nose') 11 11 12 from compiler.consts import CO_GENERATOR 13 12 14 try: 13 15 from cStringIO import StringIO … … 17 19 from nose.config import Config 18 20 19 20 21 def absdir(path): 21 22 """Return absolute, normalized path to directory, if it exists; None … … 29 30 return path 30 31 31 32 32 def absfile(path, where=None): 33 33 """Return absolute, normalized path to file (optionally in directory … … 48 48 return None 49 49 if os.path.isdir(path): 50 # might want in __init__.py from pacakge50 # might want an __init__.py from pacakge 50 50 init = os.path.join(path,'__init__.py') 51 51 if os.path.isfile(init): … … 56 56 return None 57 57 58 59 58 def anyp(predicate, iterable): 60 59 for item in iterable: … … 63 62 return False 64 63 65 66 64 def file_like(name): 67 65 return os.path.dirname(name) or name.endswith('.py') 68 66 67 def is_generator(func): 68 try: 69 return func.func_code.co_flags & CO_GENERATOR != 0 70 except AttributeError: 71 return False 69 72 70 73 def split_test_name(test): … … 119 122 raise TypeError("I don't know what %s is (%s)" % (test, t)) 120 123 121 122 124 def try_run(obj, names): 123 125 """Given a list of possible method names, try to run them with the … … 136 138 log.debug("call fixture %s.%s", obj, name) 137 139 return func() 138 139 140 def msg(message, min_verbosity=0, stream=None):141 """Output a status message, if configured verbosity is greater than142 the minimum verbosity rating of the message.143 """144 145 # FIXME ... de-globalize146 if 2 > min_verbosity:147 if stream is None:148 stream = sys.stderr149 stream.write(" " * (min_verbosity-1))150 stream.write(message)151 stream.write("\n")152 140 -
trunk/nose/result.py
r18 r21 3 3 import sys 4 4 import tokenize 5 import unittest5 from unittest import _TextTestResult 5 5 try: 6 6 from cStringIO import StringIO … … 12 12 from nose.exc import DeprecatedTest, SkipTest 13 13 from nose.plugins import call_plugins 14 14 14 14 buffer = StringIO() 15 stdout = sys.stdout 16 _TextTestResult = unittest._TextTestResult 15 stdout = [] 16 17 18 class Result(object): 19 """Base class for results handlers. 20 """ 21 capt = None 22 conf = None 23 tbinfo = None 24 25 def addDeprecated(self, test): 26 self.resetBuffer() 27 call_plugins(self.conf.plugins, 'addDeprecated', test) 28 29 def addError(self, test, err): 30 if self.isDeprecated(err): 31 self.addDeprecated(test) 32 elif self.isSkip(err): 33 self.addSkip(test) 34 else: 35 self.capt = buffer.getvalue() 36 if self.conf.debugErrors: 37 if self.conf.capture: 38 end_capture() 39 pdb.post_mortem(err[2]) 40 if self.conf.capture: 41 start_capture() 42 self.resetBuffer() 43 call_plugins(self.conf.plugins, 'addError', 44 test, err, self.capt) 45 46 def addFailure(self, test, err): 47 self.capt = buffer.getvalue() 48 if self.conf.debugFailures: 49 if self.conf.capture: 50 end_capture() 51 pdb.post_mortem(err[2]) 52 if self.conf.capture: 53 start_capture() 54 if self.conf.detailedErrors: 55 try: 56 self.tbinfo = inspect_traceback(err[2]) 57 except tokenize.TokenError: 58 self.tbinfo = "ERR: unable to inspect traceback" 59 else: 60 self.tbinfo = '' 61 self.resetBuffer() 62 call_plugins(self.conf.plugins, 'addFailure', 63 test, err, self.capt, self.tbinfo) 64 65 def addSkip(self, test): 66 self.resetBuffer() 67 call_plugins(self.conf.plugins, 'addSkip', test) 17 68 69 def addSuccess(self, test): 70 self.resetBuffer() 71 call_plugins(self.conf.plugins, 'addSuccess', test) 72 73 def isDeprecated(self, err): 74 if err[0] is DeprecatedTest: 75 return True 76 # FIXME also if is subclass or instance of DeprecatedTest 77 78 return False 79 80 def isSkip(self, err): 81 if err[0] is SkipTest: 82 return True 83 # FIXME also if is subclass or instance of DeprecatedTest 18 84 19 class TextTestResult(_TextTestResult): 85 return False 86 87 def resetBuffer(self): 88 buffer.truncate(0) 89 90 def startTest(self, test): 91 if self.conf.capture: 92 self.resetBuffer() 93 self.capt = None 94 self.tbinfo = None 95 call_plugins(self.conf.plugins, 'startTest', test) 96 97 def stopTest(self, test): 98 if self.conf.capture: 99 self.resetBuffer() 100 self.capt = None 101 self.tbinfo = None 102 call_plugins(self.conf.plugins, 'stopTest', test) 103 104 105 class TextTestResult(Result, _TextTestResult): 20 106 """Text test result that extends unittest's default test result with 21 107 several optional features: … … 48 134 49 135 def addDeprecated(self, test): 136 super(TextTestResult, self).addDeprecated(test) 50 137 self.deprecated.append((test, '', '')) 51 self.resetBuffer()52 138 self.writeRes('DEPRECATED','D') 53 call_plugins(self.conf.plugins, 'addDeprecated', test)54 139 55 140 def addError(self, test, err): 56 if err[0] is DeprecatedTest: 57 self.addDeprecated(test) 58 elif err[0] is SkipTest: 59 self.addSkip(test) 60 else: 61 capt = buffer.getvalue() 62 if self.conf.debugErrors: 63 if self.capture: 64 end_capture() 65 pdb.post_mortem(err[2]) 66 if self.capture: 67 start_capture() 141 super(TextTestResult, self).addError(test, err) 142 if not self.isDeprecated(err) and not self.isSkip(err): 68 143 self.errors.append((test, 69 144 self._exc_info_to_string(err, test), 70 capt)) 71 self.resetBuffer() 145 self.capt)) 72 146 self.writeRes('ERROR','E') 73 call_plugins(self.conf.plugins, 'addError', test, err, capt)74 147 75 148 def addFailure(self, test, err): 76 capt = buffer.getvalue() 77 if self.conf.debugFailures: 78 if self.capture: 79 end_capture() 80 pdb.post_mortem(err[2]) 81 if self.capture: 82 start_capture() 83 if self.conf.detailedErrors: 84 try: 85 tb = inspect_traceback(err[2]) 86 except tokenize.TokenError: 87 tb = "ERR: unable to inspect traceback" 88 else: 89 tb = '' 149 super(TextTestResult, self).addFailure(test, err) 90 150 self.failures.append((test, 91 self._exc_info_to_string(err, test) + tb, 92 capt)) 93 self.resetBuffer() 151 self._exc_info_to_string(err, test) + self.tbinfo, 152 self.capt)) 94 153 self.writeRes('FAIL','F') 95 call_plugins(self.conf.plugins, 'addFailure', test, err, capt, tb)96 154 97 155 def addSkip(self, test): 156 super(TextTestResult, self).addSkip(test) 98 157 self.skip.append((test, '', '')) 99 self.resetBuffer()100 158 self.writeRes('SKIP','S') 101 call_plugins(self.conf.plugins, 'addSkip', test)102 159 103 160 def addSuccess(self, test): 104 s elf.resetBuffer()161 super(TextTestResult, self).addSuccess(test) 104 161 self.writeRes('ok', '.') 105 call_plugins(self.conf.plugins, 'addSuccess', test)106 162 107 163 def printErrors(self): … … 123 179 self.stream.writeln(ln('>> end captured stdout <<')) 124 180 125 def resetBuffer(self):126 buffer.truncate(0)127 128 181 def startTest(self, test): 129 if self.capture: 130 self.resetBuffer() 131 super(TextTestResult, self).startTest(test) 132 call_plugins(self.conf.plugins, 'startTest', test) 182 Result.startTest(self, test) 183 _TextTestResult.startTest(self, test) 133 184 134 185 def stopTest(self, test): 135 if self.capture: 136 self.resetBuffer() 137 super(TextTestResult, self).stopTest(test) 138 call_plugins(self.conf.plugins, 'stopTest', test) 186 Result.stopTest(self, test) 187 _TextTestResult.stopTest(self, test) 139 188 140 189 def writeRes(self, long, short): … … 148 197 """Start capturing output to stdout. DOES NOT reset the buffer. 149 198 """ 199 stdout.append(sys.stdout) 150 200 sys.stdout = buffer 151 201 … … 154 204 """Stop capturing output to stdout. DOES NOT reset the buffer.x 155 205 """ 156 if sys.stdout is not stdout: 157 sys.stdout = stdout 206 if stdout: 207 sys.stdout = stdout.pop() 158 208 159 209 160 def install_patch(conf):161 """Install TextTestResult as unittest._TextTestResult.162 """163 def result(stream, descriptions, verbosity, conf=conf):164 return TextTestResult(stream, descriptions, verbosity, conf)165 unittest._TextTestResult = result166 167 168 def remove_patch():169 """Reset unittest._TextTestResult to the default implementation170 """171 unittest._TextTestResult = _TextTestResult172 173 174 210 def ln(label): 175 211 label_len = len(label) + 2 -
trunk/nose/__init__.py
r20 r21 283 283 from nose.core import * 284 284 from nose.exc import * 285 from nose.util import *286 from nose.suite import LazySuite287 285 from nose.loader import TestLoader 286 from nose.suite import LazySuite 288 287 from nose.result import TextTestResult 288 from nose.tools import with_setup # backwards compatibility 289 from nose.util import * 289 290 290 291 __author__ = 'Jason Pellerin' … … 294 295 'SkipTest', 'DeprecatedTest', 295 296 'TestCollector', 'TestLoader', 296 'collector', 'main', 'run_exit', 'with_setup', 297 'collector', 'main', 'run', 'run_exit', 'with_setup', 296 297 'file_like', 'split_test_name', 'test_address' 297 298 ] -
trunk/nose/selector.py
r18 r21 5 5 from nose.config import Config 6 6 from nose.plugins import call_plugins 7 from nose.util import file_like, split_test_name, test_address 7 from nose.util import absfile, file_like, split_test_name, test_address 7 7 8 8 log = logging.getLogger(__name__) … … 50 50 containerMatch = False 51 51 if filename is not None: 52 if sys.modules[clb.__module__].__file__ == filename: 52 if not os.path.isabs(filename): 53 filename = absfile(filename) 54 log.debug("Check file match for callable %s in module %s", 55 clb, clb.__module__) 56 try: 57 mod_file = sys.modules[clb.__module__].__file__ 58 if not os.path.isabs(mod_file): 59 mod_file = absfile(mod_file, self.conf.where)
