178 lines
5.2 KiB
Python
178 lines
5.2 KiB
Python
"""
|
|
Test OutcomeExceptions and helpers for creating them.
|
|
py.test.skip|fail|raises helper implementations
|
|
|
|
"""
|
|
|
|
import py
|
|
import sys
|
|
|
|
class OutcomeException(Exception):
|
|
""" OutcomeException and its subclass instances indicate and
|
|
contain info about test and collection outcomes.
|
|
"""
|
|
def __init__(self, msg=None, excinfo=None):
|
|
self.msg = msg
|
|
self.excinfo = excinfo
|
|
|
|
def __repr__(self):
|
|
if self.msg:
|
|
return repr(self.msg)
|
|
return "<%s instance>" %(self.__class__.__name__,)
|
|
__str__ = __repr__
|
|
|
|
class Passed(OutcomeException):
|
|
pass
|
|
|
|
class Skipped(OutcomeException):
|
|
pass
|
|
|
|
class Failed(OutcomeException):
|
|
pass
|
|
|
|
class ExceptionFailure(Failed):
|
|
def __init__(self, expr, expected, msg=None, excinfo=None):
|
|
Failed.__init__(self, msg=msg, excinfo=excinfo)
|
|
self.expr = expr
|
|
self.expected = expected
|
|
|
|
class Exit(Exception):
|
|
""" for immediate program exits without tracebacks and reporter/summary. """
|
|
def __init__(self, msg="unknown reason"):
|
|
self.msg = msg
|
|
Exception.__init__(self, msg)
|
|
|
|
# exposed helper methods
|
|
|
|
def exit(msg):
|
|
""" exit testing process immediately. """
|
|
__tracebackhide__ = True
|
|
raise Exit(msg)
|
|
|
|
def skip(msg=""):
|
|
""" skip with the given message. """
|
|
__tracebackhide__ = True
|
|
raise Skipped(msg=msg)
|
|
|
|
def importorskip(modname, minversion=None):
|
|
""" return imported module or skip() """
|
|
compile(modname, '', 'eval') # to catch syntaxerrors
|
|
try:
|
|
mod = __import__(modname)
|
|
except ImportError:
|
|
py.test.skip("could not import %r" %(modname,))
|
|
if minversion is None:
|
|
return mod
|
|
verattr = getattr(mod, '__version__', None)
|
|
if isinstance(minversion, str):
|
|
minver = minversion.split(".")
|
|
else:
|
|
minver = list(minversion)
|
|
if verattr is None or verattr.split(".") < minver:
|
|
py.test.skip("module %r has __version__ %r, required is: %r" %(
|
|
modname, verattr, minversion))
|
|
return mod
|
|
|
|
def fail(msg="unknown failure"):
|
|
""" fail with the given Message. """
|
|
__tracebackhide__ = True
|
|
raise Failed(msg=msg)
|
|
|
|
def raises(ExpectedException, *args, **kwargs):
|
|
""" raise AssertionError, if target code does not raise the expected
|
|
exception.
|
|
"""
|
|
__tracebackhide__ = True
|
|
assert args
|
|
if isinstance(args[0], str):
|
|
code, = args
|
|
assert isinstance(code, str)
|
|
frame = sys._getframe(1)
|
|
loc = frame.f_locals.copy()
|
|
loc.update(kwargs)
|
|
#print "raises frame scope: %r" % frame.f_locals
|
|
try:
|
|
code = py.code.Source(code).compile()
|
|
exec code in frame.f_globals, loc
|
|
# XXX didn'T mean f_globals == f_locals something special?
|
|
# this is destroyed here ...
|
|
except ExpectedException:
|
|
return py.code.ExceptionInfo()
|
|
else:
|
|
func = args[0]
|
|
assert callable
|
|
try:
|
|
func(*args[1:], **kwargs)
|
|
except ExpectedException:
|
|
return py.code.ExceptionInfo()
|
|
k = ", ".join(["%s=%r" % x for x in kwargs.items()])
|
|
if k:
|
|
k = ', ' + k
|
|
expr = '%s(%r%s)' %(func.__name__, args, k)
|
|
raise ExceptionFailure(msg="DID NOT RAISE",
|
|
expr=args, expected=ExpectedException)
|
|
|
|
def deprecated_call(func, *args, **kwargs):
|
|
""" assert that calling func(*args, **kwargs)
|
|
triggers a DeprecationWarning.
|
|
"""
|
|
warningmodule = py.std.warnings
|
|
l = []
|
|
oldwarn_explicit = getattr(warningmodule, 'warn_explicit')
|
|
def warn_explicit(*args, **kwargs):
|
|
l.append(args)
|
|
oldwarn_explicit(*args, **kwargs)
|
|
oldwarn = getattr(warningmodule, 'warn')
|
|
def warn(*args, **kwargs):
|
|
l.append(args)
|
|
oldwarn(*args, **kwargs)
|
|
|
|
warningmodule.warn_explicit = warn_explicit
|
|
warningmodule.warn = warn
|
|
try:
|
|
ret = func(*args, **kwargs)
|
|
finally:
|
|
warningmodule.warn_explicit = warn_explicit
|
|
warningmodule.warn = warn
|
|
if not l:
|
|
#print warningmodule
|
|
raise AssertionError("%r did not produce DeprecationWarning" %(func,))
|
|
return ret
|
|
|
|
class KeywordDecorator:
|
|
""" decorator for setting function attributes. """
|
|
def __init__(self, keywords, lastname=None):
|
|
self._keywords = keywords
|
|
self._lastname = lastname
|
|
|
|
def __call__(self, func=None, **kwargs):
|
|
if func is None:
|
|
kw = self._keywords.copy()
|
|
kw.update(kwargs)
|
|
return KeywordDecorator(kw)
|
|
elif not hasattr(func, 'func_dict'):
|
|
kw = self._keywords.copy()
|
|
name = self._lastname
|
|
if name is None:
|
|
name = "mark"
|
|
kw[name] = func
|
|
return KeywordDecorator(kw)
|
|
func.func_dict.update(self._keywords)
|
|
return func
|
|
|
|
def __getattr__(self, name):
|
|
if name[0] == "_":
|
|
raise AttributeError(name)
|
|
kw = self._keywords.copy()
|
|
kw[name] = True
|
|
return self.__class__(kw, lastname=name)
|
|
|
|
mark = KeywordDecorator({})
|
|
|
|
# exitcodes for the command line
|
|
EXIT_OK = 0
|
|
EXIT_TESTSFAILED = 1
|
|
EXIT_INTERRUPTED = 2
|
|
EXIT_INTERNALERROR = 3
|
|
EXIT_NOHOSTS = 4
|