##// END OF EJS Templates
check linux with startswith('linux') instead of =='linux2'...
MinRK -
Show More
@@ -1,335 +1,335 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Decorators for labeling test objects.
2 """Decorators for labeling test objects.
3
3
4 Decorators that merely return a modified version of the original function
4 Decorators that merely return a modified version of the original function
5 object are straightforward. Decorators that return a new function object need
5 object are straightforward. Decorators that return a new function object need
6 to use nose.tools.make_decorator(original_function)(decorator) in returning the
6 to use nose.tools.make_decorator(original_function)(decorator) in returning the
7 decorator, in order to preserve metadata such as function name, setup and
7 decorator, in order to preserve metadata such as function name, setup and
8 teardown functions and so on - see nose.tools for more information.
8 teardown functions and so on - see nose.tools for more information.
9
9
10 This module provides a set of useful decorators meant to be ready to use in
10 This module provides a set of useful decorators meant to be ready to use in
11 your own tests. See the bottom of the file for the ready-made ones, and if you
11 your own tests. See the bottom of the file for the ready-made ones, and if you
12 find yourself writing a new one that may be of generic use, add it here.
12 find yourself writing a new one that may be of generic use, add it here.
13
13
14 Included decorators:
14 Included decorators:
15
15
16
16
17 Lightweight testing that remains unittest-compatible.
17 Lightweight testing that remains unittest-compatible.
18
18
19 - @parametric, for parametric test support that is vastly easier to use than
19 - @parametric, for parametric test support that is vastly easier to use than
20 nose's for debugging. With ours, if a test fails, the stack under inspection
20 nose's for debugging. With ours, if a test fails, the stack under inspection
21 is that of the test and not that of the test framework.
21 is that of the test and not that of the test framework.
22
22
23 - An @as_unittest decorator can be used to tag any normal parameter-less
23 - An @as_unittest decorator can be used to tag any normal parameter-less
24 function as a unittest TestCase. Then, both nose and normal unittest will
24 function as a unittest TestCase. Then, both nose and normal unittest will
25 recognize it as such. This will make it easier to migrate away from Nose if
25 recognize it as such. This will make it easier to migrate away from Nose if
26 we ever need/want to while maintaining very lightweight tests.
26 we ever need/want to while maintaining very lightweight tests.
27
27
28 NOTE: This file contains IPython-specific decorators. Using the machinery in
28 NOTE: This file contains IPython-specific decorators. Using the machinery in
29 IPython.external.decorators, we import either numpy.testing.decorators if numpy is
29 IPython.external.decorators, we import either numpy.testing.decorators if numpy is
30 available, OR use equivalent code in IPython.external._decorators, which
30 available, OR use equivalent code in IPython.external._decorators, which
31 we've copied verbatim from numpy.
31 we've copied verbatim from numpy.
32
32
33 Authors
33 Authors
34 -------
34 -------
35
35
36 - Fernando Perez <Fernando.Perez@berkeley.edu>
36 - Fernando Perez <Fernando.Perez@berkeley.edu>
37 """
37 """
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Copyright (C) 2009-2010 The IPython Development Team
40 # Copyright (C) 2009-2010 The IPython Development Team
41 #
41 #
42 # Distributed under the terms of the BSD License. The full license is in
42 # Distributed under the terms of the BSD License. The full license is in
43 # the file COPYING, distributed as part of this software.
43 # the file COPYING, distributed as part of this software.
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Imports
47 # Imports
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 # Stdlib imports
50 # Stdlib imports
51 import inspect
51 import inspect
52 import sys
52 import sys
53 import tempfile
53 import tempfile
54 import unittest
54 import unittest
55
55
56 # Third-party imports
56 # Third-party imports
57
57
58 # This is Michele Simionato's decorator module, kept verbatim.
58 # This is Michele Simionato's decorator module, kept verbatim.
59 from IPython.external.decorator import decorator
59 from IPython.external.decorator import decorator
60
60
61 # We already have python3-compliant code for parametric tests
61 # We already have python3-compliant code for parametric tests
62 if sys.version[0]=='2':
62 if sys.version[0]=='2':
63 from _paramtestpy2 import parametric, ParametricTestCase
63 from _paramtestpy2 import parametric, ParametricTestCase
64 else:
64 else:
65 from _paramtestpy3 import parametric, ParametricTestCase
65 from _paramtestpy3 import parametric, ParametricTestCase
66
66
67 # Expose the unittest-driven decorators
67 # Expose the unittest-driven decorators
68 from ipunittest import ipdoctest, ipdocstring
68 from ipunittest import ipdoctest, ipdocstring
69
69
70 # Grab the numpy-specific decorators which we keep in a file that we
70 # Grab the numpy-specific decorators which we keep in a file that we
71 # occasionally update from upstream: decorators.py is a copy of
71 # occasionally update from upstream: decorators.py is a copy of
72 # numpy.testing.decorators, we expose all of it here.
72 # numpy.testing.decorators, we expose all of it here.
73 from IPython.external.decorators import *
73 from IPython.external.decorators import *
74
74
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76 # Classes and functions
76 # Classes and functions
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78
78
79 # Simple example of the basic idea
79 # Simple example of the basic idea
80 def as_unittest(func):
80 def as_unittest(func):
81 """Decorator to make a simple function into a normal test via unittest."""
81 """Decorator to make a simple function into a normal test via unittest."""
82 class Tester(unittest.TestCase):
82 class Tester(unittest.TestCase):
83 def test(self):
83 def test(self):
84 func()
84 func()
85
85
86 Tester.__name__ = func.__name__
86 Tester.__name__ = func.__name__
87
87
88 return Tester
88 return Tester
89
89
90 # Utility functions
90 # Utility functions
91
91
92 def apply_wrapper(wrapper,func):
92 def apply_wrapper(wrapper,func):
93 """Apply a wrapper to a function for decoration.
93 """Apply a wrapper to a function for decoration.
94
94
95 This mixes Michele Simionato's decorator tool with nose's make_decorator,
95 This mixes Michele Simionato's decorator tool with nose's make_decorator,
96 to apply a wrapper in a decorator so that all nose attributes, as well as
96 to apply a wrapper in a decorator so that all nose attributes, as well as
97 function signature and other properties, survive the decoration cleanly.
97 function signature and other properties, survive the decoration cleanly.
98 This will ensure that wrapped functions can still be well introspected via
98 This will ensure that wrapped functions can still be well introspected via
99 IPython, for example.
99 IPython, for example.
100 """
100 """
101 import nose.tools
101 import nose.tools
102
102
103 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
103 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
104
104
105
105
106 def make_label_dec(label,ds=None):
106 def make_label_dec(label,ds=None):
107 """Factory function to create a decorator that applies one or more labels.
107 """Factory function to create a decorator that applies one or more labels.
108
108
109 Parameters
109 Parameters
110 ----------
110 ----------
111 label : string or sequence
111 label : string or sequence
112 One or more labels that will be applied by the decorator to the functions
112 One or more labels that will be applied by the decorator to the functions
113 it decorates. Labels are attributes of the decorated function with their
113 it decorates. Labels are attributes of the decorated function with their
114 value set to True.
114 value set to True.
115
115
116 ds : string
116 ds : string
117 An optional docstring for the resulting decorator. If not given, a
117 An optional docstring for the resulting decorator. If not given, a
118 default docstring is auto-generated.
118 default docstring is auto-generated.
119
119
120 Returns
120 Returns
121 -------
121 -------
122 A decorator.
122 A decorator.
123
123
124 Examples
124 Examples
125 --------
125 --------
126
126
127 A simple labeling decorator:
127 A simple labeling decorator:
128 >>> slow = make_label_dec('slow')
128 >>> slow = make_label_dec('slow')
129 >>> print slow.__doc__
129 >>> print slow.__doc__
130 Labels a test as 'slow'.
130 Labels a test as 'slow'.
131
131
132 And one that uses multiple labels and a custom docstring:
132 And one that uses multiple labels and a custom docstring:
133 >>> rare = make_label_dec(['slow','hard'],
133 >>> rare = make_label_dec(['slow','hard'],
134 ... "Mix labels 'slow' and 'hard' for rare tests.")
134 ... "Mix labels 'slow' and 'hard' for rare tests.")
135 >>> print rare.__doc__
135 >>> print rare.__doc__
136 Mix labels 'slow' and 'hard' for rare tests.
136 Mix labels 'slow' and 'hard' for rare tests.
137
137
138 Now, let's test using this one:
138 Now, let's test using this one:
139 >>> @rare
139 >>> @rare
140 ... def f(): pass
140 ... def f(): pass
141 ...
141 ...
142 >>>
142 >>>
143 >>> f.slow
143 >>> f.slow
144 True
144 True
145 >>> f.hard
145 >>> f.hard
146 True
146 True
147 """
147 """
148
148
149 if isinstance(label,basestring):
149 if isinstance(label,basestring):
150 labels = [label]
150 labels = [label]
151 else:
151 else:
152 labels = label
152 labels = label
153
153
154 # Validate that the given label(s) are OK for use in setattr() by doing a
154 # Validate that the given label(s) are OK for use in setattr() by doing a
155 # dry run on a dummy function.
155 # dry run on a dummy function.
156 tmp = lambda : None
156 tmp = lambda : None
157 for label in labels:
157 for label in labels:
158 setattr(tmp,label,True)
158 setattr(tmp,label,True)
159
159
160 # This is the actual decorator we'll return
160 # This is the actual decorator we'll return
161 def decor(f):
161 def decor(f):
162 for label in labels:
162 for label in labels:
163 setattr(f,label,True)
163 setattr(f,label,True)
164 return f
164 return f
165
165
166 # Apply the user's docstring, or autogenerate a basic one
166 # Apply the user's docstring, or autogenerate a basic one
167 if ds is None:
167 if ds is None:
168 ds = "Labels a test as %r." % label
168 ds = "Labels a test as %r." % label
169 decor.__doc__ = ds
169 decor.__doc__ = ds
170
170
171 return decor
171 return decor
172
172
173
173
174 # Inspired by numpy's skipif, but uses the full apply_wrapper utility to
174 # Inspired by numpy's skipif, but uses the full apply_wrapper utility to
175 # preserve function metadata better and allows the skip condition to be a
175 # preserve function metadata better and allows the skip condition to be a
176 # callable.
176 # callable.
177 def skipif(skip_condition, msg=None):
177 def skipif(skip_condition, msg=None):
178 ''' Make function raise SkipTest exception if skip_condition is true
178 ''' Make function raise SkipTest exception if skip_condition is true
179
179
180 Parameters
180 Parameters
181 ----------
181 ----------
182 skip_condition : bool or callable.
182 skip_condition : bool or callable.
183 Flag to determine whether to skip test. If the condition is a
183 Flag to determine whether to skip test. If the condition is a
184 callable, it is used at runtime to dynamically make the decision. This
184 callable, it is used at runtime to dynamically make the decision. This
185 is useful for tests that may require costly imports, to delay the cost
185 is useful for tests that may require costly imports, to delay the cost
186 until the test suite is actually executed.
186 until the test suite is actually executed.
187 msg : string
187 msg : string
188 Message to give on raising a SkipTest exception
188 Message to give on raising a SkipTest exception
189
189
190 Returns
190 Returns
191 -------
191 -------
192 decorator : function
192 decorator : function
193 Decorator, which, when applied to a function, causes SkipTest
193 Decorator, which, when applied to a function, causes SkipTest
194 to be raised when the skip_condition was True, and the function
194 to be raised when the skip_condition was True, and the function
195 to be called normally otherwise.
195 to be called normally otherwise.
196
196
197 Notes
197 Notes
198 -----
198 -----
199 You will see from the code that we had to further decorate the
199 You will see from the code that we had to further decorate the
200 decorator with the nose.tools.make_decorator function in order to
200 decorator with the nose.tools.make_decorator function in order to
201 transmit function name, and various other metadata.
201 transmit function name, and various other metadata.
202 '''
202 '''
203
203
204 def skip_decorator(f):
204 def skip_decorator(f):
205 # Local import to avoid a hard nose dependency and only incur the
205 # Local import to avoid a hard nose dependency and only incur the
206 # import time overhead at actual test-time.
206 # import time overhead at actual test-time.
207 import nose
207 import nose
208
208
209 # Allow for both boolean or callable skip conditions.
209 # Allow for both boolean or callable skip conditions.
210 if callable(skip_condition):
210 if callable(skip_condition):
211 skip_val = skip_condition
211 skip_val = skip_condition
212 else:
212 else:
213 skip_val = lambda : skip_condition
213 skip_val = lambda : skip_condition
214
214
215 def get_msg(func,msg=None):
215 def get_msg(func,msg=None):
216 """Skip message with information about function being skipped."""
216 """Skip message with information about function being skipped."""
217 if msg is None: out = 'Test skipped due to test condition.'
217 if msg is None: out = 'Test skipped due to test condition.'
218 else: out = msg
218 else: out = msg
219 return "Skipping test: %s. %s" % (func.__name__,out)
219 return "Skipping test: %s. %s" % (func.__name__,out)
220
220
221 # We need to define *two* skippers because Python doesn't allow both
221 # We need to define *two* skippers because Python doesn't allow both
222 # return with value and yield inside the same function.
222 # return with value and yield inside the same function.
223 def skipper_func(*args, **kwargs):
223 def skipper_func(*args, **kwargs):
224 """Skipper for normal test functions."""
224 """Skipper for normal test functions."""
225 if skip_val():
225 if skip_val():
226 raise nose.SkipTest(get_msg(f,msg))
226 raise nose.SkipTest(get_msg(f,msg))
227 else:
227 else:
228 return f(*args, **kwargs)
228 return f(*args, **kwargs)
229
229
230 def skipper_gen(*args, **kwargs):
230 def skipper_gen(*args, **kwargs):
231 """Skipper for test generators."""
231 """Skipper for test generators."""
232 if skip_val():
232 if skip_val():
233 raise nose.SkipTest(get_msg(f,msg))
233 raise nose.SkipTest(get_msg(f,msg))
234 else:
234 else:
235 for x in f(*args, **kwargs):
235 for x in f(*args, **kwargs):
236 yield x
236 yield x
237
237
238 # Choose the right skipper to use when building the actual generator.
238 # Choose the right skipper to use when building the actual generator.
239 if nose.util.isgenerator(f):
239 if nose.util.isgenerator(f):
240 skipper = skipper_gen
240 skipper = skipper_gen
241 else:
241 else:
242 skipper = skipper_func
242 skipper = skipper_func
243
243
244 return nose.tools.make_decorator(f)(skipper)
244 return nose.tools.make_decorator(f)(skipper)
245
245
246 return skip_decorator
246 return skip_decorator
247
247
248 # A version with the condition set to true, common case just to attacha message
248 # A version with the condition set to true, common case just to attacha message
249 # to a skip decorator
249 # to a skip decorator
250 def skip(msg=None):
250 def skip(msg=None):
251 """Decorator factory - mark a test function for skipping from test suite.
251 """Decorator factory - mark a test function for skipping from test suite.
252
252
253 Parameters
253 Parameters
254 ----------
254 ----------
255 msg : string
255 msg : string
256 Optional message to be added.
256 Optional message to be added.
257
257
258 Returns
258 Returns
259 -------
259 -------
260 decorator : function
260 decorator : function
261 Decorator, which, when applied to a function, causes SkipTest
261 Decorator, which, when applied to a function, causes SkipTest
262 to be raised, with the optional message added.
262 to be raised, with the optional message added.
263 """
263 """
264
264
265 return skipif(True,msg)
265 return skipif(True,msg)
266
266
267
267
268 def onlyif(condition, msg):
268 def onlyif(condition, msg):
269 """The reverse from skipif, see skipif for details."""
269 """The reverse from skipif, see skipif for details."""
270
270
271 if callable(condition):
271 if callable(condition):
272 skip_condition = lambda : not condition()
272 skip_condition = lambda : not condition()
273 else:
273 else:
274 skip_condition = lambda : not condition
274 skip_condition = lambda : not condition
275
275
276 return skipif(skip_condition, msg)
276 return skipif(skip_condition, msg)
277
277
278 #-----------------------------------------------------------------------------
278 #-----------------------------------------------------------------------------
279 # Utility functions for decorators
279 # Utility functions for decorators
280 def module_not_available(module):
280 def module_not_available(module):
281 """Can module be imported? Returns true if module does NOT import.
281 """Can module be imported? Returns true if module does NOT import.
282
282
283 This is used to make a decorator to skip tests that require module to be
283 This is used to make a decorator to skip tests that require module to be
284 available, but delay the 'import numpy' to test execution time.
284 available, but delay the 'import numpy' to test execution time.
285 """
285 """
286 try:
286 try:
287 mod = __import__(module)
287 mod = __import__(module)
288 mod_not_avail = False
288 mod_not_avail = False
289 except ImportError:
289 except ImportError:
290 mod_not_avail = True
290 mod_not_avail = True
291
291
292 return mod_not_avail
292 return mod_not_avail
293
293
294 #-----------------------------------------------------------------------------
294 #-----------------------------------------------------------------------------
295 # Decorators for public use
295 # Decorators for public use
296
296
297 # Decorators to skip certain tests on specific platforms.
297 # Decorators to skip certain tests on specific platforms.
298 skip_win32 = skipif(sys.platform == 'win32',
298 skip_win32 = skipif(sys.platform == 'win32',
299 "This test does not run under Windows")
299 "This test does not run under Windows")
300 skip_linux = skipif(sys.platform == 'linux2',
300 skip_linux = skipif(sys.platform.startswith('linux'),
301 "This test does not run under Linux")
301 "This test does not run under Linux")
302 skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X")
302 skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X")
303
303
304
304
305 # Decorators to skip tests if not on specific platforms.
305 # Decorators to skip tests if not on specific platforms.
306 skip_if_not_win32 = skipif(sys.platform != 'win32',
306 skip_if_not_win32 = skipif(sys.platform != 'win32',
307 "This test only runs under Windows")
307 "This test only runs under Windows")
308 skip_if_not_linux = skipif(sys.platform != 'linux2',
308 skip_if_not_linux = skipif(not sys.platform.startswith('linux'),
309 "This test only runs under Linux")
309 "This test only runs under Linux")
310 skip_if_not_osx = skipif(sys.platform != 'darwin',
310 skip_if_not_osx = skipif(sys.platform != 'darwin',
311 "This test only runs under OSX")
311 "This test only runs under OSX")
312
312
313 # Other skip decorators
313 # Other skip decorators
314 skipif_not_numpy = skipif(module_not_available('numpy'),"This test requires numpy")
314 skipif_not_numpy = skipif(module_not_available('numpy'),"This test requires numpy")
315
315
316 skipif_not_sympy = skipif(module_not_available('sympy'),"This test requires sympy")
316 skipif_not_sympy = skipif(module_not_available('sympy'),"This test requires sympy")
317
317
318 skip_known_failure = knownfailureif(True,'This test is known to fail')
318 skip_known_failure = knownfailureif(True,'This test is known to fail')
319
319
320 # A null 'decorator', useful to make more readable code that needs to pick
320 # A null 'decorator', useful to make more readable code that needs to pick
321 # between different decorators based on OS or other conditions
321 # between different decorators based on OS or other conditions
322 null_deco = lambda f: f
322 null_deco = lambda f: f
323
323
324 # Some tests only run where we can use unicode paths. Note that we can't just
324 # Some tests only run where we can use unicode paths. Note that we can't just
325 # check os.path.supports_unicode_filenames, which is always False on Linux.
325 # check os.path.supports_unicode_filenames, which is always False on Linux.
326 try:
326 try:
327 f = tempfile.NamedTemporaryFile(prefix=u"tmp€")
327 f = tempfile.NamedTemporaryFile(prefix=u"tmp€")
328 except UnicodeEncodeError:
328 except UnicodeEncodeError:
329 unicode_paths = False
329 unicode_paths = False
330 else:
330 else:
331 unicode_paths = True
331 unicode_paths = True
332 f.close()
332 f.close()
333
333
334 onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable "
334 onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable "
335 "where we can use unicode in filenames."))
335 "where we can use unicode in filenames."))
@@ -1,188 +1,188 b''
1 """Tests for the decorators we've created for IPython.
1 """Tests for the decorators we've created for IPython.
2 """
2 """
3
3
4 # Module imports
4 # Module imports
5 # Std lib
5 # Std lib
6 import inspect
6 import inspect
7 import sys
7 import sys
8 import unittest
8 import unittest
9
9
10 # Third party
10 # Third party
11 import nose.tools as nt
11 import nose.tools as nt
12
12
13 # Our own
13 # Our own
14 from IPython.testing import decorators as dec
14 from IPython.testing import decorators as dec
15 from IPython.testing.skipdoctest import skip_doctest
15 from IPython.testing.skipdoctest import skip_doctest
16 from IPython.testing.ipunittest import ParametricTestCase
16 from IPython.testing.ipunittest import ParametricTestCase
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Utilities
19 # Utilities
20
20
21 # Note: copied from OInspect, kept here so the testing stuff doesn't create
21 # Note: copied from OInspect, kept here so the testing stuff doesn't create
22 # circular dependencies and is easier to reuse.
22 # circular dependencies and is easier to reuse.
23 def getargspec(obj):
23 def getargspec(obj):
24 """Get the names and default values of a function's arguments.
24 """Get the names and default values of a function's arguments.
25
25
26 A tuple of four things is returned: (args, varargs, varkw, defaults).
26 A tuple of four things is returned: (args, varargs, varkw, defaults).
27 'args' is a list of the argument names (it may contain nested lists).
27 'args' is a list of the argument names (it may contain nested lists).
28 'varargs' and 'varkw' are the names of the * and ** arguments or None.
28 'varargs' and 'varkw' are the names of the * and ** arguments or None.
29 'defaults' is an n-tuple of the default values of the last n arguments.
29 'defaults' is an n-tuple of the default values of the last n arguments.
30
30
31 Modified version of inspect.getargspec from the Python Standard
31 Modified version of inspect.getargspec from the Python Standard
32 Library."""
32 Library."""
33
33
34 if inspect.isfunction(obj):
34 if inspect.isfunction(obj):
35 func_obj = obj
35 func_obj = obj
36 elif inspect.ismethod(obj):
36 elif inspect.ismethod(obj):
37 func_obj = obj.im_func
37 func_obj = obj.im_func
38 else:
38 else:
39 raise TypeError, 'arg is not a Python function'
39 raise TypeError, 'arg is not a Python function'
40 args, varargs, varkw = inspect.getargs(func_obj.func_code)
40 args, varargs, varkw = inspect.getargs(func_obj.func_code)
41 return args, varargs, varkw, func_obj.func_defaults
41 return args, varargs, varkw, func_obj.func_defaults
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Testing functions
44 # Testing functions
45
45
46 @dec.as_unittest
46 @dec.as_unittest
47 def trivial():
47 def trivial():
48 """A trivial test"""
48 """A trivial test"""
49 pass
49 pass
50
50
51 # Some examples of parametric tests.
51 # Some examples of parametric tests.
52
52
53 def is_smaller(i,j):
53 def is_smaller(i,j):
54 assert i<j,"%s !< %s" % (i,j)
54 assert i<j,"%s !< %s" % (i,j)
55
55
56 class Tester(ParametricTestCase):
56 class Tester(ParametricTestCase):
57
57
58 def test_parametric(self):
58 def test_parametric(self):
59 yield is_smaller(3, 4)
59 yield is_smaller(3, 4)
60 x, y = 1, 2
60 x, y = 1, 2
61 yield is_smaller(x, y)
61 yield is_smaller(x, y)
62
62
63 @dec.parametric
63 @dec.parametric
64 def test_par_standalone():
64 def test_par_standalone():
65 yield is_smaller(3, 4)
65 yield is_smaller(3, 4)
66 x, y = 1, 2
66 x, y = 1, 2
67 yield is_smaller(x, y)
67 yield is_smaller(x, y)
68
68
69
69
70 @dec.skip
70 @dec.skip
71 def test_deliberately_broken():
71 def test_deliberately_broken():
72 """A deliberately broken test - we want to skip this one."""
72 """A deliberately broken test - we want to skip this one."""
73 1/0
73 1/0
74
74
75 @dec.skip('Testing the skip decorator')
75 @dec.skip('Testing the skip decorator')
76 def test_deliberately_broken2():
76 def test_deliberately_broken2():
77 """Another deliberately broken test - we want to skip this one."""
77 """Another deliberately broken test - we want to skip this one."""
78 1/0
78 1/0
79
79
80
80
81 # Verify that we can correctly skip the doctest for a function at will, but
81 # Verify that we can correctly skip the doctest for a function at will, but
82 # that the docstring itself is NOT destroyed by the decorator.
82 # that the docstring itself is NOT destroyed by the decorator.
83 @skip_doctest
83 @skip_doctest
84 def doctest_bad(x,y=1,**k):
84 def doctest_bad(x,y=1,**k):
85 """A function whose doctest we need to skip.
85 """A function whose doctest we need to skip.
86
86
87 >>> 1+1
87 >>> 1+1
88 3
88 3
89 """
89 """
90 print 'x:',x
90 print 'x:',x
91 print 'y:',y
91 print 'y:',y
92 print 'k:',k
92 print 'k:',k
93
93
94
94
95 def call_doctest_bad():
95 def call_doctest_bad():
96 """Check that we can still call the decorated functions.
96 """Check that we can still call the decorated functions.
97
97
98 >>> doctest_bad(3,y=4)
98 >>> doctest_bad(3,y=4)
99 x: 3
99 x: 3
100 y: 4
100 y: 4
101 k: {}
101 k: {}
102 """
102 """
103 pass
103 pass
104
104
105
105
106 def test_skip_dt_decorator():
106 def test_skip_dt_decorator():
107 """Doctest-skipping decorator should preserve the docstring.
107 """Doctest-skipping decorator should preserve the docstring.
108 """
108 """
109 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
109 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
110 check = """A function whose doctest we need to skip.
110 check = """A function whose doctest we need to skip.
111
111
112 >>> 1+1
112 >>> 1+1
113 3
113 3
114 """
114 """
115 # Fetch the docstring from doctest_bad after decoration.
115 # Fetch the docstring from doctest_bad after decoration.
116 val = doctest_bad.__doc__
116 val = doctest_bad.__doc__
117
117
118 nt.assert_equal(check,val,"doctest_bad docstrings don't match")
118 nt.assert_equal(check,val,"doctest_bad docstrings don't match")
119
119
120
120
121 # Doctest skipping should work for class methods too
121 # Doctest skipping should work for class methods too
122 class FooClass(object):
122 class FooClass(object):
123 """FooClass
123 """FooClass
124
124
125 Example:
125 Example:
126
126
127 >>> 1+1
127 >>> 1+1
128 2
128 2
129 """
129 """
130
130
131 @skip_doctest
131 @skip_doctest
132 def __init__(self,x):
132 def __init__(self,x):
133 """Make a FooClass.
133 """Make a FooClass.
134
134
135 Example:
135 Example:
136
136
137 >>> f = FooClass(3)
137 >>> f = FooClass(3)
138 junk
138 junk
139 """
139 """
140 print 'Making a FooClass.'
140 print 'Making a FooClass.'
141 self.x = x
141 self.x = x
142
142
143 @skip_doctest
143 @skip_doctest
144 def bar(self,y):
144 def bar(self,y):
145 """Example:
145 """Example:
146
146
147 >>> ff = FooClass(3)
147 >>> ff = FooClass(3)
148 >>> ff.bar(0)
148 >>> ff.bar(0)
149 boom!
149 boom!
150 >>> 1/0
150 >>> 1/0
151 bam!
151 bam!
152 """
152 """
153 return 1/y
153 return 1/y
154
154
155 def baz(self,y):
155 def baz(self,y):
156 """Example:
156 """Example:
157
157
158 >>> ff2 = FooClass(3)
158 >>> ff2 = FooClass(3)
159 Making a FooClass.
159 Making a FooClass.
160 >>> ff2.baz(3)
160 >>> ff2.baz(3)
161 True
161 True
162 """
162 """
163 return self.x==y
163 return self.x==y
164
164
165
165
166 def test_skip_dt_decorator2():
166 def test_skip_dt_decorator2():
167 """Doctest-skipping decorator should preserve function signature.
167 """Doctest-skipping decorator should preserve function signature.
168 """
168 """
169 # Hardcoded correct answer
169 # Hardcoded correct answer
170 dtargs = (['x', 'y'], None, 'k', (1,))
170 dtargs = (['x', 'y'], None, 'k', (1,))
171 # Introspect out the value
171 # Introspect out the value
172 dtargsr = getargspec(doctest_bad)
172 dtargsr = getargspec(doctest_bad)
173 assert dtargsr==dtargs, \
173 assert dtargsr==dtargs, \
174 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
174 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
175
175
176
176
177 @dec.skip_linux
177 @dec.skip_linux
178 def test_linux():
178 def test_linux():
179 nt.assert_not_equals(sys.platform,'linux2',"This test can't run under linux")
179 nt.assert_false(sys.platform.startswith('linux'),"This test can't run under linux")
180
180
181 @dec.skip_win32
181 @dec.skip_win32
182 def test_win32():
182 def test_win32():
183 nt.assert_not_equals(sys.platform,'win32',"This test can't run under windows")
183 nt.assert_not_equals(sys.platform,'win32',"This test can't run under windows")
184
184
185 @dec.skip_osx
185 @dec.skip_osx
186 def test_osx():
186 def test_osx():
187 nt.assert_not_equals(sys.platform,'darwin',"This test can't run under osx")
187 nt.assert_not_equals(sys.platform,'darwin',"This test can't run under osx")
188
188
General Comments 0
You need to be logged in to leave comments. Login now