1""" 2Decorators for labeling and modifying behavior of test objects. 3 4Decorators that merely return a modified version of the original 5function object are straightforward. Decorators that return a new 6function object need to use 7:: 8 9 nose.tools.make_decorator(original_function)(decorator) 10 11in returning the decorator, in order to preserve meta-data such as 12function name, setup and teardown functions and so on - see 13``nose.tools`` for more information. 14 15""" 16 17# IPython changes: make this work if numpy not available 18# Original code: 19try: 20 from ._numpy_testing_noseclasses import KnownFailureTest 21except: 22 pass 23 24# End IPython changes 25 26 27def skipif(skip_condition, msg=None): 28 """ 29 Make function raise SkipTest exception if a given condition is true. 30 31 If the condition is a callable, it is used at runtime to dynamically 32 make the decision. This is useful for tests that may require costly 33 imports, to delay the cost until the test suite is actually executed. 34 35 Parameters 36 ---------- 37 skip_condition : bool or callable 38 Flag to determine whether to skip the decorated test. 39 msg : str, optional 40 Message to give on raising a SkipTest exception. Default is None. 41 42 Returns 43 ------- 44 decorator : function 45 Decorator which, when applied to a function, causes SkipTest 46 to be raised when `skip_condition` is True, and the function 47 to be called normally otherwise. 48 49 Notes 50 ----- 51 The decorator itself is decorated with the ``nose.tools.make_decorator`` 52 function in order to transmit function name, and various other metadata. 53 54 """ 55 56 def skip_decorator(f): 57 # Local import to avoid a hard nose dependency and only incur the 58 # import time overhead at actual test-time. 59 import nose 60 61 # Allow for both boolean or callable skip conditions. 62 if callable(skip_condition): 63 skip_val = lambda : skip_condition() 64 else: 65 skip_val = lambda : skip_condition 66 67 def get_msg(func,msg=None): 68 """Skip message with information about function being skipped.""" 69 if msg is None: 70 out = 'Test skipped due to test condition' 71 else: 72 out = '\n'+msg 73 74 return "Skipping test: %s%s" % (func.__name__,out) 75 76 # We need to define *two* skippers because Python doesn't allow both 77 # return with value and yield inside the same function. 78 def skipper_func(*args, **kwargs): 79 """Skipper for normal test functions.""" 80 if skip_val(): 81 raise nose.SkipTest(get_msg(f,msg)) 82 else: 83 return f(*args, **kwargs) 84 85 def skipper_gen(*args, **kwargs): 86 """Skipper for test generators.""" 87 if skip_val(): 88 raise nose.SkipTest(get_msg(f,msg)) 89 else: 90 for x in f(*args, **kwargs): 91 yield x 92 93 # Choose the right skipper to use when building the actual decorator. 94 if nose.util.isgenerator(f): 95 skipper = skipper_gen 96 else: 97 skipper = skipper_func 98 99 return nose.tools.make_decorator(f)(skipper) 100 101 return skip_decorator 102 103def knownfailureif(fail_condition, msg=None): 104 """ 105 Make function raise KnownFailureTest exception if given condition is true. 106 107 Parameters 108 ---------- 109 fail_condition : bool 110 Flag to determine whether to mark the decorated test as a known 111 failure (if True) or not (if False). 112 msg : str, optional 113 Message to give on raising a KnownFailureTest exception. 114 Default is None. 115 116 Returns 117 ------- 118 decorator : function 119 Decorator, which, when applied to a function, causes KnownFailureTest to 120 be raised when `fail_condition` is True and the test fails. 121 122 Notes 123 ----- 124 The decorator itself is decorated with the ``nose.tools.make_decorator`` 125 function in order to transmit function name, and various other metadata. 126 127 """ 128 if msg is None: 129 msg = 'Test skipped due to known failure' 130 131 def knownfail_decorator(f): 132 # Local import to avoid a hard nose dependency and only incur the 133 # import time overhead at actual test-time. 134 import nose 135 136 def knownfailer(*args, **kwargs): 137 if fail_condition: 138 raise KnownFailureTest(msg) 139 else: 140 return f(*args, **kwargs) 141 return nose.tools.make_decorator(f)(knownfailer) 142 143 return knownfail_decorator 144