/nose/tools.py
Python | 194 lines | 182 code | 0 blank | 12 comment | 2 complexity | 8187b9d8b8fc9b69c2ca0459e50602fd MD5 | raw file
1""" 2Tools for testing 3----------------- 4 5nose.tools provides a few convenience functions to make writing tests 6easier. You don't have to use them; nothing in the rest of nose depends 7on any of these methods. 8""" 9import re 10import time 11import unittest 12 13 14__all__ = ['ok_', 'eq_', 'make_decorator', 'raises', 'set_trace', 'timed', 15 'with_setup', 'TimeExpired', 'istest', 'nottest'] 16 17 18class TimeExpired(AssertionError): 19 pass 20 21 22def ok_(expr, msg=None): 23 """Shorthand for assert. Saves 3 whole characters! 24 """ 25 assert expr, msg 26 27 28def eq_(a, b, msg=None): 29 """Shorthand for 'assert a == b, "%r != %r" % (a, b) 30 """ 31 assert a == b, msg or "%r != %r" % (a, b) 32 33 34def make_decorator(func): 35 """ 36 Wraps a test decorator so as to properly replicate metadata 37 of the decorated function, including nose's additional stuff 38 (namely, setup and teardown). 39 """ 40 def decorate(newfunc): 41 if hasattr(func, 'compat_func_name'): 42 name = func.compat_func_name 43 else: 44 name = func.__name__ 45 newfunc.__dict__ = func.__dict__ 46 newfunc.__doc__ = func.__doc__ 47 newfunc.__module__ = func.__module__ 48 if not hasattr(newfunc, 'compat_co_firstlineno'): 49 newfunc.compat_co_firstlineno = func.func_code.co_firstlineno 50 try: 51 newfunc.__name__ = name 52 except TypeError: 53 # can't set func name in 2.3 54 newfunc.compat_func_name = name 55 return newfunc 56 return decorate 57 58 59def raises(*exceptions): 60 """Test must raise one of expected exceptions to pass. 61 62 Example use:: 63 64 @raises(TypeError, ValueError) 65 def test_raises_type_error(): 66 raise TypeError("This test passes") 67 68 @raises(Exception) 69 def test_that_fails_by_passing(): 70 pass 71 72 If you want to test many assertions about exceptions in a single test, 73 you may want to use `assert_raises` instead. 74 """ 75 valid = ' or '.join([e.__name__ for e in exceptions]) 76 def decorate(func): 77 name = func.__name__ 78 def newfunc(*arg, **kw): 79 try: 80 func(*arg, **kw) 81 except exceptions: 82 pass 83 except: 84 raise 85 else: 86 message = "%s() did not raise %s" % (name, valid) 87 raise AssertionError(message) 88 newfunc = make_decorator(func)(newfunc) 89 return newfunc 90 return decorate 91 92 93def set_trace(): 94 """Call pdb.set_trace in the calling frame, first restoring 95 sys.stdout to the real output stream. Note that sys.stdout is NOT 96 reset to whatever it was before the call once pdb is done! 97 """ 98 import pdb 99 import sys 100 stdout = sys.stdout 101 sys.stdout = sys.__stdout__ 102 pdb.Pdb().set_trace(sys._getframe().f_back) 103 104 105def timed(limit): 106 """Test must finish within specified time limit to pass. 107 108 Example use:: 109 110 @timed(.1) 111 def test_that_fails(): 112 time.sleep(.2) 113 """ 114 def decorate(func): 115 def newfunc(*arg, **kw): 116 start = time.time() 117 func(*arg, **kw) 118 end = time.time() 119 if end - start > limit: 120 raise TimeExpired("Time limit (%s) exceeded" % limit) 121 newfunc = make_decorator(func)(newfunc) 122 return newfunc 123 return decorate 124 125 126def with_setup(setup=None, teardown=None): 127 """Decorator to add setup and/or teardown methods to a test function:: 128 129 @with_setup(setup, teardown) 130 def test_something(): 131 " ... " 132 133 Note that `with_setup` is useful *only* for test functions, not for test 134 methods or inside of TestCase subclasses. 135 """ 136 def decorate(func, setup=setup, teardown=teardown): 137 if setup: 138 if hasattr(func, 'setup'): 139 _old_s = func.setup 140 def _s(): 141 setup() 142 _old_s() 143 func.setup = _s 144 else: 145 func.setup = setup 146 if teardown: 147 if hasattr(func, 'teardown'): 148 _old_t = func.teardown 149 def _t(): 150 _old_t() 151 teardown() 152 func.teardown = _t 153 else: 154 func.teardown = teardown 155 return func 156 return decorate 157 158 159def istest(func): 160 """Decorator to mark a function or method as a test 161 """ 162 func.__test__ = True 163 return func 164 165 166def nottest(func): 167 """Decorator to mark a function or method as *not* a test 168 """ 169 func.__test__ = False 170 return func 171 172# 173# Expose assert* from unittest.TestCase 174# - give them pep8 style names 175# 176caps = re.compile('([A-Z])') 177 178def pep8(name): 179 return caps.sub(lambda m: '_' + m.groups()[0].lower(), name) 180 181class Dummy(unittest.TestCase): 182 def nop(): 183 pass 184_t = Dummy('nop') 185 186for at in [ at for at in dir(_t) 187 if at.startswith('assert') and not '_' in at ]: 188 pepd = pep8(at) 189 vars()[pepd] = getattr(_t, at) 190 __all__.append(pepd) 191 192del Dummy 193del _t 194del pep8