PageRenderTime 28ms CodeModel.GetById 11ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/nose/tools.py

https://bitbucket.org/jpellerin/nose/
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