test_ok2/_pytest/outcomes.py

158 lines
4.7 KiB
Python
Raw Normal View History

"""
exception classes and constants handling test outcomes
as well as functions creating them
"""
from __future__ import absolute_import, division, print_function
import py
import sys
class OutcomeException(BaseException):
""" OutcomeException and its subclass instances indicate and
contain info about test and collection outcomes.
"""
2018-05-23 22:48:46 +08:00
def __init__(self, msg=None, pytrace=True):
BaseException.__init__(self, msg)
self.msg = msg
self.pytrace = pytrace
def __repr__(self):
if self.msg:
val = self.msg
if isinstance(val, bytes):
2018-05-23 22:48:46 +08:00
val = py._builtin._totext(val, errors="replace")
return val
2017-07-29 00:27:59 +08:00
return "<%s instance>" % (self.__class__.__name__,)
2018-05-23 22:48:46 +08:00
__str__ = __repr__
TEST_OUTCOME = (OutcomeException, Exception)
class Skipped(OutcomeException):
# XXX hackish: on 3k we fake to live in the builtins
# in order to have Skipped exception printing shorter/nicer
2018-05-23 22:48:46 +08:00
__module__ = "builtins"
def __init__(self, msg=None, pytrace=True, allow_module_level=False):
OutcomeException.__init__(self, msg=msg, pytrace=pytrace)
self.allow_module_level = allow_module_level
class Failed(OutcomeException):
""" raised from an explicit call to pytest.fail() """
2018-05-23 22:48:46 +08:00
__module__ = "builtins"
class Exit(KeyboardInterrupt):
""" raised for immediate program exits (no tracebacks/summaries)"""
2018-05-23 22:48:46 +08:00
def __init__(self, msg="unknown reason"):
self.msg = msg
KeyboardInterrupt.__init__(self, msg)
2018-05-23 22:48:46 +08:00
# exposed helper methods
2017-07-29 00:27:59 +08:00
def exit(msg):
""" exit testing process as if KeyboardInterrupt was triggered. """
__tracebackhide__ = True
raise Exit(msg)
exit.Exception = Exit
def skip(msg="", **kwargs):
""" skip an executing test with the given message. Note: it's usually
better to use the pytest.mark.skipif marker to declare a test to be
skipped under certain conditions like mismatching platforms or
dependencies. See the pytest_skipping plugin for details.
:kwarg bool allow_module_level: allows this function to be called at
2017-10-03 08:24:52 +08:00
module level, skipping the rest of the module. Default to False.
"""
__tracebackhide__ = True
2018-05-23 22:48:46 +08:00
allow_module_level = kwargs.pop("allow_module_level", False)
if kwargs:
keys = [k for k in kwargs.keys()]
2018-05-23 22:48:46 +08:00
raise TypeError("unexpected keyword arguments: {}".format(keys))
raise Skipped(msg=msg, allow_module_level=allow_module_level)
skip.Exception = Skipped
def fail(msg="", pytrace=True):
2018-05-13 18:06:09 +08:00
""" explicitly fail a currently-executing test with the given Message.
:arg pytrace: if false the msg represents the full failure information
and no python traceback will be reported.
"""
__tracebackhide__ = True
raise Failed(msg=msg, pytrace=pytrace)
fail.Exception = Failed
class XFailed(fail.Exception):
""" raised from an explicit call to pytest.xfail() """
def xfail(reason=""):
""" xfail an executing test or setup functions with the given reason."""
__tracebackhide__ = True
raise XFailed(reason)
xfail.Exception = XFailed
def importorskip(modname, minversion=None):
""" return imported module if it has at least "minversion" as its
__version__ attribute. If no minversion is specified the a skip
is only triggered if the module can not be imported.
"""
import warnings
2018-05-23 22:48:46 +08:00
__tracebackhide__ = True
2018-05-23 22:48:46 +08:00
compile(modname, "", "eval") # to catch syntaxerrors
should_skip = False
with warnings.catch_warnings():
# make sure to ignore ImportWarnings that might happen because
# of existing directories with the same name we're trying to
# import but without a __init__.py file
2018-05-23 22:48:46 +08:00
warnings.simplefilter("ignore")
try:
__import__(modname)
except ImportError:
# Do not raise chained exception here(#1485)
should_skip = True
if should_skip:
2017-07-29 00:27:59 +08:00
raise Skipped("could not import %r" % (modname,), allow_module_level=True)
mod = sys.modules[modname]
if minversion is None:
return mod
2018-05-23 22:48:46 +08:00
verattr = getattr(mod, "__version__", None)
if minversion is not None:
try:
from pkg_resources import parse_version as pv
except ImportError:
2018-05-23 22:48:46 +08:00
raise Skipped(
"we have a required version for %r but can not import "
"pkg_resources to parse version strings." % (modname,),
allow_module_level=True,
)
if verattr is None or pv(verattr) < pv(minversion):
2018-05-23 22:48:46 +08:00
raise Skipped(
"module %r has __version__ %r, required is: %r"
% (modname, verattr, minversion),
allow_module_level=True,
)
return mod