Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/numpy/testing/_private/decorators.py : 18%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2Decorators for labeling and modifying behavior of test objects.
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::
9 nose.tools.make_decorator(original_function)(decorator)
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.
15"""
16import collections.abc
18from .utils import SkipTest, assert_warns, HAS_REFCOUNT
20__all__ = ['slow', 'setastest', 'skipif', 'knownfailureif', 'deprecated',
21 'parametrize', '_needs_refcount',]
24def slow(t):
25 """
26 Label a test as 'slow'.
28 The exact definition of a slow test is obviously both subjective and
29 hardware-dependent, but in general any individual test that requires more
30 than a second or two should be labeled as slow (the whole suite consists of
31 thousands of tests, so even a second is significant).
33 Parameters
34 ----------
35 t : callable
36 The test to label as slow.
38 Returns
39 -------
40 t : callable
41 The decorated test `t`.
43 Examples
44 --------
45 The `numpy.testing` module includes ``import decorators as dec``.
46 A test can be decorated as slow like this::
48 from numpy.testing import *
50 @dec.slow
51 def test_big(self):
52 print('Big, slow test')
54 """
56 t.slow = True
57 return t
59def setastest(tf=True):
60 """
61 Signals to nose that this function is or is not a test.
63 Parameters
64 ----------
65 tf : bool
66 If True, specifies that the decorated callable is a test.
67 If False, specifies that the decorated callable is not a test.
68 Default is True.
70 Notes
71 -----
72 This decorator can't use the nose namespace, because it can be
73 called from a non-test module. See also ``istest`` and ``nottest`` in
74 ``nose.tools``.
76 Examples
77 --------
78 `setastest` can be used in the following way::
80 from numpy.testing import dec
82 @dec.setastest(False)
83 def func_with_test_in_name(arg1, arg2):
84 pass
86 """
87 def set_test(t):
88 t.__test__ = tf
89 return t
90 return set_test
92def skipif(skip_condition, msg=None):
93 """
94 Make function raise SkipTest exception if a given condition is true.
96 If the condition is a callable, it is used at runtime to dynamically
97 make the decision. This is useful for tests that may require costly
98 imports, to delay the cost until the test suite is actually executed.
100 Parameters
101 ----------
102 skip_condition : bool or callable
103 Flag to determine whether to skip the decorated test.
104 msg : str, optional
105 Message to give on raising a SkipTest exception. Default is None.
107 Returns
108 -------
109 decorator : function
110 Decorator which, when applied to a function, causes SkipTest
111 to be raised when `skip_condition` is True, and the function
112 to be called normally otherwise.
114 Notes
115 -----
116 The decorator itself is decorated with the ``nose.tools.make_decorator``
117 function in order to transmit function name, and various other metadata.
119 """
121 def skip_decorator(f):
122 # Local import to avoid a hard nose dependency and only incur the
123 # import time overhead at actual test-time.
124 import nose
126 # Allow for both boolean or callable skip conditions.
127 if isinstance(skip_condition, collections.abc.Callable):
128 skip_val = lambda: skip_condition()
129 else:
130 skip_val = lambda: skip_condition
132 def get_msg(func,msg=None):
133 """Skip message with information about function being skipped."""
134 if msg is None:
135 out = 'Test skipped due to test condition'
136 else:
137 out = msg
139 return "Skipping test: %s: %s" % (func.__name__, out)
141 # We need to define *two* skippers because Python doesn't allow both
142 # return with value and yield inside the same function.
143 def skipper_func(*args, **kwargs):
144 """Skipper for normal test functions."""
145 if skip_val():
146 raise SkipTest(get_msg(f, msg))
147 else:
148 return f(*args, **kwargs)
150 def skipper_gen(*args, **kwargs):
151 """Skipper for test generators."""
152 if skip_val():
153 raise SkipTest(get_msg(f, msg))
154 else:
155 yield from f(*args, **kwargs)
157 # Choose the right skipper to use when building the actual decorator.
158 if nose.util.isgenerator(f):
159 skipper = skipper_gen
160 else:
161 skipper = skipper_func
163 return nose.tools.make_decorator(f)(skipper)
165 return skip_decorator
168def knownfailureif(fail_condition, msg=None):
169 """
170 Make function raise KnownFailureException exception if given condition is true.
172 If the condition is a callable, it is used at runtime to dynamically
173 make the decision. This is useful for tests that may require costly
174 imports, to delay the cost until the test suite is actually executed.
176 Parameters
177 ----------
178 fail_condition : bool or callable
179 Flag to determine whether to mark the decorated test as a known
180 failure (if True) or not (if False).
181 msg : str, optional
182 Message to give on raising a KnownFailureException exception.
183 Default is None.
185 Returns
186 -------
187 decorator : function
188 Decorator, which, when applied to a function, causes
189 KnownFailureException to be raised when `fail_condition` is True,
190 and the function to be called normally otherwise.
192 Notes
193 -----
194 The decorator itself is decorated with the ``nose.tools.make_decorator``
195 function in order to transmit function name, and various other metadata.
197 """
198 if msg is None:
199 msg = 'Test skipped due to known failure'
201 # Allow for both boolean or callable known failure conditions.
202 if isinstance(fail_condition, collections.abc.Callable):
203 fail_val = lambda: fail_condition()
204 else:
205 fail_val = lambda: fail_condition
207 def knownfail_decorator(f):
208 # Local import to avoid a hard nose dependency and only incur the
209 # import time overhead at actual test-time.
210 import nose
211 from .noseclasses import KnownFailureException
213 def knownfailer(*args, **kwargs):
214 if fail_val():
215 raise KnownFailureException(msg)
216 else:
217 return f(*args, **kwargs)
218 return nose.tools.make_decorator(f)(knownfailer)
220 return knownfail_decorator
222def deprecated(conditional=True):
223 """
224 Filter deprecation warnings while running the test suite.
226 This decorator can be used to filter DeprecationWarning's, to avoid
227 printing them during the test suite run, while checking that the test
228 actually raises a DeprecationWarning.
230 Parameters
231 ----------
232 conditional : bool or callable, optional
233 Flag to determine whether to mark test as deprecated or not. If the
234 condition is a callable, it is used at runtime to dynamically make the
235 decision. Default is True.
237 Returns
238 -------
239 decorator : function
240 The `deprecated` decorator itself.
242 Notes
243 -----
244 .. versionadded:: 1.4.0
246 """
247 def deprecate_decorator(f):
248 # Local import to avoid a hard nose dependency and only incur the
249 # import time overhead at actual test-time.
250 import nose
252 def _deprecated_imp(*args, **kwargs):
253 # Poor man's replacement for the with statement
254 with assert_warns(DeprecationWarning):
255 f(*args, **kwargs)
257 if isinstance(conditional, collections.abc.Callable):
258 cond = conditional()
259 else:
260 cond = conditional
261 if cond:
262 return nose.tools.make_decorator(f)(_deprecated_imp)
263 else:
264 return f
265 return deprecate_decorator
268def parametrize(vars, input):
269 """
270 Pytest compatibility class. This implements the simplest level of
271 pytest.mark.parametrize for use in nose as an aid in making the transition
272 to pytest. It achieves that by adding a dummy var parameter and ignoring
273 the doc_func parameter of the base class. It does not support variable
274 substitution by name, nor does it support nesting or classes. See the
275 pytest documentation for usage.
277 .. versionadded:: 1.14.0
279 """
280 from .parameterized import parameterized
282 return parameterized(input)
284_needs_refcount = skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")