##// END OF EJS Templates
Update decorators and test scripts.
Fernando Perez -
Show More
@@ -1,12 +1,10 b''
1 """Decorators for labeling test objects.
1 """Decorators for labeling test objects.
2
2
3 Decorators that merely return a modified version of the original
3 Decorators that merely return a modified version of the original function
4 function object are straightforward. Decorators that return a new
4 object are straightforward. Decorators that return a new function object need
5 function object need to use
5 to use nose.tools.make_decorator(original_function)(decorator) in returning the
6 nose.tools.make_decorator(original_function)(decorator) in returning
6 decorator, in order to preserve metadata such as function name, setup and
7 the decorator, in order to preserve metadata such as function name,
7 teardown functions and so on - see nose.tools for more information.
8 setup and teardown functions and so on - see nose.tools for more
9 information.
10
8
11 This module provides a set of useful decorators meant to be ready to use in
9 This module provides a set of useful decorators meant to be ready to use in
12 your own tests. See the bottom of the file for the ready-made ones, and if you
10 your own tests. See the bottom of the file for the ready-made ones, and if you
@@ -115,46 +113,132 b' def make_label_dec(label,ds=None):'
115
113
116 return decor
114 return decor
117
115
118 #-----------------------------------------------------------------------------
119 # Decorators for public use
120
121 skip_doctest = make_label_dec('skip_doctest',
122 """Decorator - mark a function or method for skipping its doctest.
123
116
124 This decorator allows you to mark a function whose docstring you wish to
117 # Inspired by numpy's skipif, but uses the full apply_wrapper utility to
125 omit from testing, while preserving the docstring for introspection, help,
118 # preserve function metadata better and allows the skip condition to be a
126 etc.""")
119 # callable.
127
120 def skipif(skip_condition, msg=None):
128 def skip(msg=''):
121 ''' Make function raise SkipTest exception if skip_condition is true
129 """Decorator - mark a test function for skipping from test suite.
122
130
123 Parameters
131 This function *is* already a decorator, it is not a factory like
124 ---------
132 make_label_dec or some of those in decorators_numpy.
125 skip_condition : bool or callable.
126 Flag to determine whether to skip test. If the condition is a
127 callable, it is used at runtime to dynamically make the decision. This
128 is useful for tests that may require costly imports, to delay the cost
129 until the test suite is actually executed.
130 msg : string
131 Message to give on raising a SkipTest exception
132
133 Returns
134 -------
135 decorator : function
136 Decorator, which, when applied to a function, causes SkipTest
137 to be raised when the skip_condition was True, and the function
138 to be called normally otherwise.
139
140 Notes
141 -----
142 You will see from the code that we had to further decorate the
143 decorator with the nose.tools.make_decorator function in order to
144 transmit function name, and various other metadata.
145 '''
146
147 def skip_decorator(f):
148 # Local import to avoid a hard nose dependency and only incur the
149 # import time overhead at actual test-time.
150 import nose
151
152 # Allow for both boolean or callable skip conditions.
153 if callable(skip_condition):
154 skip_val = lambda : skip_condition()
155 else:
156 skip_val = lambda : skip_condition
157
158 def get_msg(func,msg=None):
159 """Skip message with information about function being skipped."""
160 if msg is None: out = 'Test skipped due to test condition.'
161 else: out = msg
162 return "Skipping test: %s. %s" % (func.__name__,out)
163
164 # We need to define *two* skippers because Python doesn't allow both
165 # return with value and yield inside the same function.
166 def skipper_func(*args, **kwargs):
167 """Skipper for normal test functions."""
168 if skip_val():
169 raise nose.SkipTest(get_msg(f,msg))
170 else:
171 return f(*args, **kwargs)
172
173 def skipper_gen(*args, **kwargs):
174 """Skipper for test generators."""
175 if skip_val():
176 raise nose.SkipTest(get_msg(f,msg))
177 else:
178 for x in f(*args, **kwargs):
179 yield x
180
181 # Choose the right skipper to use when building the actual generator.
182 if nose.util.isgenerator(f):
183 skipper = skipper_gen
184 else:
185 skipper = skipper_func
186
187 return nose.tools.make_decorator(f)(skipper)
188
189 return skip_decorator
190
191 # A version with the condition set to true, common case just to attacha message
192 # to a skip decorator
193 def skip(msg=None):
194 """Decorator factory - mark a test function for skipping from test suite.
133
195
134 :Parameters:
196 :Parameters:
135
136 func : function
137 Test function to be skipped
138
139 msg : string
197 msg : string
140 Optional message to be added.
198 Optional message to be added.
199
200 :Returns:
201 decorator : function
202 Decorator, which, when applied to a function, causes SkipTest
203 to be raised, with the optional message added.
141 """
204 """
142
205
143 import nose
206 return skipif(True,msg)
144
207
145 def inner(func):
146
208
147 def wrapper(*a,**k):
209 #-----------------------------------------------------------------------------
148 if msg: out = '\n'+msg
210 # Utility functions for decorators
149 else: out = ''
211 def numpy_not_available():
150 raise nose.SkipTest("Skipping test for function: %s%s" %
212 """Can numpy be imported? Returns true if numpy does NOT import.
151 (func.__name__,out))
152
213
153 return apply_wrapper(wrapper,func)
214 This is used to make a decorator to skip tests that require numpy to be
215 available, but delay the 'import numpy' to test execution time.
216 """
217 try:
218 import numpy
219 np_not_avail = False
220 except ImportError:
221 np_not_avail = True
222
223 return np_not_avail
224
225 #-----------------------------------------------------------------------------
226 # Decorators for public use
227
228 skip_doctest = make_label_dec('skip_doctest',
229 """Decorator - mark a function or method for skipping its doctest.
154
230
155 return inner
231 This decorator allows you to mark a function whose docstring you wish to
232 omit from testing, while preserving the docstring for introspection, help,
233 etc.""")
156
234
157 # Decorators to skip certain tests on specific platforms.
235 # Decorators to skip certain tests on specific platforms.
158 skip_win32 = skipif(sys.platform=='win32',"This test does not run under Windows")
236 skip_win32 = skipif(sys.platform=='win32',
237 "This test does not run under Windows")
159 skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux")
238 skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux")
160 skip_osx = skipif(sys.platform=='darwin',"This test does not run under OSX")
239 skip_osx = skipif(sys.platform=='darwin',"This test does not run under OS X")
240
241
242 skipif_not_numpy = skipif(numpy_not_available,"This test requires numpy")
243
244 skipknownfailure = skip('This test is known to fail')
@@ -30,13 +30,16 b' def main():'
30 '--exe',
30 '--exe',
31 ]
31 ]
32
32
33 has_ip = False
33 # Detect if any tests were required by explicitly calling an IPython
34 # submodule or giving a specific path
35 has_tests = False
34 for arg in sys.argv:
36 for arg in sys.argv:
35 if 'IPython' in arg:
37 if 'IPython' in arg or arg.endswith('.py') or \
36 has_ip = True
38 (':' in arg and '.py' in arg):
39 has_tests = True
37 break
40 break
38
41 # If nothing was specifically requested, test full IPython
39 if not has_ip:
42 if not has_tests:
40 argv.append('IPython')
43 argv.append('IPython')
41
44
42 # construct list of plugins, omitting the existing doctest plugin
45 # construct list of plugins, omitting the existing doctest plugin
@@ -49,5 +52,4 b' def main():'
49 #print '*** adding plugin:',plug.name # dbg
52 #print '*** adding plugin:',plug.name # dbg
50 plugins.append(plug)
53 plugins.append(plug)
51
54
52
53 TestProgram(argv=argv,plugins=plugins)
55 TestProgram(argv=argv,plugins=plugins)
@@ -1,10 +1,21 b''
1 """ Tests for various magic functions
1 """Tests for various magic functions.
2
2
3 Needs to be run by nose (to make ipython session available)
3 Needs to be run by nose (to make ipython session available).
4 """
4 """
5
5
6 # Standard library imports
7 import os
8 import sys
9
10 # Third-party imports
11 import nose.tools as nt
12
13 # From our own code
6 from IPython.testing import decorators as dec
14 from IPython.testing import decorators as dec
7
15
16 #-----------------------------------------------------------------------------
17 # Test functions begin
18
8 def test_rehashx():
19 def test_rehashx():
9 # clear up everything
20 # clear up everything
10 _ip.IP.alias_table.clear()
21 _ip.IP.alias_table.clear()
@@ -58,14 +69,12 b' def doctest_hist_r():'
58
69
59
70
60 def test_shist():
71 def test_shist():
61 # Simple tests of ShadowHist class
72 # Simple tests of ShadowHist class - test generator.
62 import os, shutil, tempfile
73 import os, shutil, tempfile
63 import nose.tools as nt
64
74
65 from IPython.Extensions import pickleshare
75 from IPython.Extensions import pickleshare
66 from IPython.history import ShadowHist
76 from IPython.history import ShadowHist
67
77
68
69 tfile = tempfile.mktemp('','tmp-ipython-')
78 tfile = tempfile.mktemp('','tmp-ipython-')
70
79
71 db = pickleshare.PickleShareDB(tfile)
80 db = pickleshare.PickleShareDB(tfile)
@@ -82,11 +91,25 b' def test_shist():'
82
91
83 shutil.rmtree(tfile)
92 shutil.rmtree(tfile)
84
93
94 @dec.skipif_not_numpy
95 def test_numpy_clear_array_undec():
96 _ip.ex('import numpy as np')
97 _ip.ex('a = np.empty(2)')
98
99 yield nt.assert_true,'a' in _ip.user_ns
100 _ip.magic('clear array')
101 yield nt.assert_false,'a' in _ip.user_ns
102
85
103
86 @dec.skip_numpy_not_avail
104 @dec.skip()
87 def doctest_clear_array():
105 def test_fail_dec(*a,**k):
88 """Check that array clearing works.
106 yield nt.assert_true, False
107
108 @dec.skip('This one shouldn not run')
109 def test_fail_dec2(*a,**k):
110 yield nt.assert_true, False
111
112 @dec.skipknownfailure
113 def test_fail_dec3(*a,**k):
114 yield nt.assert_true, False
89
115
90 >>> 1/0
91 """
92 pass # doctest only
General Comments 0
You need to be logged in to leave comments. Login now