Hide keyboard shortcuts

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. 

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""" 

16import collections.abc 

17 

18from .utils import SkipTest, assert_warns, HAS_REFCOUNT 

19 

20__all__ = ['slow', 'setastest', 'skipif', 'knownfailureif', 'deprecated', 

21 'parametrize', '_needs_refcount',] 

22 

23 

24def slow(t): 

25 """ 

26 Label a test as 'slow'. 

27 

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). 

32 

33 Parameters 

34 ---------- 

35 t : callable 

36 The test to label as slow. 

37 

38 Returns 

39 ------- 

40 t : callable 

41 The decorated test `t`. 

42 

43 Examples 

44 -------- 

45 The `numpy.testing` module includes ``import decorators as dec``. 

46 A test can be decorated as slow like this:: 

47 

48 from numpy.testing import * 

49 

50 @dec.slow 

51 def test_big(self): 

52 print('Big, slow test') 

53 

54 """ 

55 

56 t.slow = True 

57 return t 

58 

59def setastest(tf=True): 

60 """ 

61 Signals to nose that this function is or is not a test. 

62 

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. 

69 

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``. 

75 

76 Examples 

77 -------- 

78 `setastest` can be used in the following way:: 

79 

80 from numpy.testing import dec 

81 

82 @dec.setastest(False) 

83 def func_with_test_in_name(arg1, arg2): 

84 pass 

85 

86 """ 

87 def set_test(t): 

88 t.__test__ = tf 

89 return t 

90 return set_test 

91 

92def skipif(skip_condition, msg=None): 

93 """ 

94 Make function raise SkipTest exception if a given condition is true. 

95 

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. 

99 

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. 

106 

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. 

113 

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. 

118 

119 """ 

120 

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 

125 

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 

131 

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 

138 

139 return "Skipping test: %s: %s" % (func.__name__, out) 

140 

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) 

149 

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) 

156 

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 

162 

163 return nose.tools.make_decorator(f)(skipper) 

164 

165 return skip_decorator 

166 

167 

168def knownfailureif(fail_condition, msg=None): 

169 """ 

170 Make function raise KnownFailureException exception if given condition is true. 

171 

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. 

175 

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. 

184 

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. 

191 

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. 

196 

197 """ 

198 if msg is None: 

199 msg = 'Test skipped due to known failure' 

200 

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 

206 

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 

212 

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) 

219 

220 return knownfail_decorator 

221 

222def deprecated(conditional=True): 

223 """ 

224 Filter deprecation warnings while running the test suite. 

225 

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. 

229 

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. 

236 

237 Returns 

238 ------- 

239 decorator : function 

240 The `deprecated` decorator itself. 

241 

242 Notes 

243 ----- 

244 .. versionadded:: 1.4.0 

245 

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 

251 

252 def _deprecated_imp(*args, **kwargs): 

253 # Poor man's replacement for the with statement 

254 with assert_warns(DeprecationWarning): 

255 f(*args, **kwargs) 

256 

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 

266 

267 

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. 

276 

277 .. versionadded:: 1.14.0 

278 

279 """ 

280 from .parameterized import parameterized 

281 

282 return parameterized(input) 

283 

284_needs_refcount = skipif(not HAS_REFCOUNT, "python has no sys.getrefcount")