1""" 2exception classes and constants handling test outcomes 3as well as functions creating them 4""" 5from __future__ import absolute_import, division, print_function 6import py 7import sys 8 9 10class OutcomeException(BaseException): 11 """ OutcomeException and its subclass instances indicate and 12 contain info about test and collection outcomes. 13 """ 14 def __init__(self, msg=None, pytrace=True): 15 BaseException.__init__(self, msg) 16 self.msg = msg 17 self.pytrace = pytrace 18 19 def __repr__(self): 20 if self.msg: 21 val = self.msg 22 if isinstance(val, bytes): 23 val = py._builtin._totext(val, errors='replace') 24 return val 25 return "<%s instance>" % (self.__class__.__name__,) 26 __str__ = __repr__ 27 28 29TEST_OUTCOME = (OutcomeException, Exception) 30 31 32class Skipped(OutcomeException): 33 # XXX hackish: on 3k we fake to live in the builtins 34 # in order to have Skipped exception printing shorter/nicer 35 __module__ = 'builtins' 36 37 def __init__(self, msg=None, pytrace=True, allow_module_level=False): 38 OutcomeException.__init__(self, msg=msg, pytrace=pytrace) 39 self.allow_module_level = allow_module_level 40 41 42class Failed(OutcomeException): 43 """ raised from an explicit call to pytest.fail() """ 44 __module__ = 'builtins' 45 46 47class Exit(KeyboardInterrupt): 48 """ raised for immediate program exits (no tracebacks/summaries)""" 49 def __init__(self, msg="unknown reason"): 50 self.msg = msg 51 KeyboardInterrupt.__init__(self, msg) 52 53# exposed helper methods 54 55 56def exit(msg): 57 """ exit testing process as if KeyboardInterrupt was triggered. """ 58 __tracebackhide__ = True 59 raise Exit(msg) 60 61 62exit.Exception = Exit 63 64 65def skip(msg="", **kwargs): 66 """ skip an executing test with the given message. Note: it's usually 67 better to use the pytest.mark.skipif marker to declare a test to be 68 skipped under certain conditions like mismatching platforms or 69 dependencies. See the pytest_skipping plugin for details. 70 71 :kwarg bool allow_module_level: allows this function to be called at 72 module level, skipping the rest of the module. Default to False. 73 """ 74 __tracebackhide__ = True 75 allow_module_level = kwargs.pop('allow_module_level', False) 76 if kwargs: 77 keys = [k for k in kwargs.keys()] 78 raise TypeError('unexpected keyword arguments: {0}'.format(keys)) 79 raise Skipped(msg=msg, allow_module_level=allow_module_level) 80 81 82skip.Exception = Skipped 83 84 85def fail(msg="", pytrace=True): 86 """ explicitly fail an currently-executing test with the given Message. 87 88 :arg pytrace: if false the msg represents the full failure information 89 and no python traceback will be reported. 90 """ 91 __tracebackhide__ = True 92 raise Failed(msg=msg, pytrace=pytrace) 93 94 95fail.Exception = Failed 96 97 98class XFailed(fail.Exception): 99 """ raised from an explicit call to pytest.xfail() """ 100 101 102def xfail(reason=""): 103 """ xfail an executing test or setup functions with the given reason.""" 104 __tracebackhide__ = True 105 raise XFailed(reason) 106 107 108xfail.Exception = XFailed 109 110 111def importorskip(modname, minversion=None): 112 """ return imported module if it has at least "minversion" as its 113 __version__ attribute. If no minversion is specified the a skip 114 is only triggered if the module can not be imported. 115 """ 116 import warnings 117 __tracebackhide__ = True 118 compile(modname, '', 'eval') # to catch syntaxerrors 119 should_skip = False 120 121 with warnings.catch_warnings(): 122 # make sure to ignore ImportWarnings that might happen because 123 # of existing directories with the same name we're trying to 124 # import but without a __init__.py file 125 warnings.simplefilter('ignore') 126 try: 127 __import__(modname) 128 except ImportError: 129 # Do not raise chained exception here(#1485) 130 should_skip = True 131 if should_skip: 132 raise Skipped("could not import %r" % (modname,), allow_module_level=True) 133 mod = sys.modules[modname] 134 if minversion is None: 135 return mod 136 verattr = getattr(mod, '__version__', None) 137 if minversion is not None: 138 try: 139 from pkg_resources import parse_version as pv 140 except ImportError: 141 raise Skipped("we have a required version for %r but can not import " 142 "pkg_resources to parse version strings." % (modname,), 143 allow_module_level=True) 144 if verattr is None or pv(verattr) < pv(minversion): 145 raise Skipped("module %r has __version__ %r, required is: %r" % ( 146 modname, verattr, minversion), allow_module_level=True) 147 return mod 148