##// END OF EJS Templates
More fixes for testing on win32.
Administrator -
Show More
@@ -1,97 +1,90 b''
1 1 """Decorators for labeling test objects
2 2
3 3 Decorators that merely return a modified version of the original
4 4 function object are straightforward. Decorators that return a new
5 5 function object need to use
6 6 nose.tools.make_decorator(original_function)(decorator) in returning
7 7 the decorator, in order to preserve metadata such as function name,
8 8 setup and teardown functions and so on - see nose.tools for more
9 9 information.
10 10
11 11 """
12 12
13 13 def slow(t):
14 14 """Labels a test as 'slow'.
15 15
16 16 The exact definition of a slow test is obviously both subjective and
17 17 hardware-dependent, but in general any individual test that requires more
18 18 than a second or two should be labeled as slow (the whole suite consits of
19 19 thousands of tests, so even a second is significant)."""
20 20
21 21 t.slow = True
22 22 return t
23 23
24 24 def setastest(tf=True):
25 25 ''' Signals to nose that this function is or is not a test
26 26
27 27 Parameters
28 28 ----------
29 29 tf : bool
30 30 If True specifies this is a test, not a test otherwise
31 31
32 e.g
33 >>> from numpy.testing.decorators import setastest
34 >>> @setastest(False)
35 ... def func_with_test_in_name(arg1, arg2): pass
36 ...
37 >>>
38
39 32 This decorator cannot use the nose namespace, because it can be
40 33 called from a non-test module. See also istest and nottest in
41 34 nose.tools
42 35
43 36 '''
44 37 def set_test(t):
45 38 t.__test__ = tf
46 39 return t
47 40 return set_test
48 41
49 42 def skipif(skip_condition=True, msg=None):
50 43 ''' Make function raise SkipTest exception if skip_condition is true
51 44
52 45 Parameters
53 46 ----------
54 47 skip_condition : bool or callable.
55 48 Flag to determine whether to skip test. If the condition is a
56 49 callable, it is used at runtime to dynamically make the decision. This
57 50 is useful for tests that may require costly imports, to delay the cost
58 51 until the test suite is actually executed.
59 52 msg : string
60 53 Message to give on raising a SkipTest exception
61 54
62 55 Returns
63 56 -------
64 57 decorator : function
65 58 Decorator, which, when applied to a function, causes SkipTest
66 59 to be raised when the skip_condition was True, and the function
67 60 to be called normally otherwise.
68 61
69 62 Notes
70 63 -----
71 64 You will see from the code that we had to further decorate the
72 65 decorator with the nose.tools.make_decorator function in order to
73 66 transmit function name, and various other metadata.
74 67 '''
75 68 if msg is None:
76 69 msg = 'Test skipped due to test condition'
77 70 def skip_decorator(f):
78 71 # Local import to avoid a hard nose dependency and only incur the
79 72 # import time overhead at actual test-time.
80 73 import nose
81 74 def skipper(*args, **kwargs):
82 75 if skip_condition:
83 76 raise nose.SkipTest, msg
84 77 else:
85 78 return f(*args, **kwargs)
86 79 return nose.tools.make_decorator(f)(skipper)
87 80 return skip_decorator
88 81
89 82 def skipknownfailure(f):
90 83 ''' Decorator to raise SkipTest for test known to fail
91 84 '''
92 85 # Local import to avoid a hard nose dependency and only incur the
93 86 # import time overhead at actual test-time.
94 87 import nose
95 88 def skipper(*args, **kwargs):
96 89 raise nose.SkipTest, 'This test is known to fail'
97 90 return nose.tools.make_decorator(f)(skipper)
@@ -1,283 +1,288 b''
1 1 # -*- coding: utf-8 -*-
2 2 """IPython Test Suite Runner.
3 3
4 4 This module provides a main entry point to a user script to test IPython
5 5 itself from the command line. There are two ways of running this script:
6 6
7 7 1. With the syntax `iptest all`. This runs our entire test suite by
8 8 calling this script (with different arguments) or trial recursively. This
9 9 causes modules and package to be tested in different processes, using nose
10 10 or trial where appropriate.
11 11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
12 12 the script simply calls nose, but with special command line flags and
13 13 plugins loaded.
14 14
15 15 For now, this script requires that both nose and twisted are installed. This
16 16 will change in the future.
17 17 """
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Module imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import os.path as path
25 25 import sys
26 26 import subprocess
27 27 import time
28 28 import warnings
29 29
30 30 import nose.plugins.builtin
31 31 from nose.core import TestProgram
32 32
33 33 from IPython.platutils import find_cmd
34 34 from IPython.testing.plugin.ipdoctest import IPythonDoctest
35 35
36 36 pjoin = path.join
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Logic for skipping doctests
40 40 #-----------------------------------------------------------------------------
41 41
42 42 def test_for(mod):
43 43 """Test to see if mod is importable."""
44 44 try:
45 45 __import__(mod)
46 46 except ImportError:
47 47 return False
48 48 else:
49 49 return True
50 50
51 51 have_curses = test_for('_curses')
52 52 have_wx = test_for('wx')
53 53 have_zi = test_for('zope.interface')
54 54 have_twisted = test_for('twisted')
55 55 have_foolscap = test_for('foolscap')
56 56 have_objc = test_for('objc')
57 57 have_pexpect = test_for('pexpect')
58 58
59 59 # For the IPythonDoctest plugin, we need to exclude certain patterns that cause
60 60 # testing problems. We should strive to minimize the number of skipped
61 61 # modules, since this means untested code. As the testing machinery
62 62 # solidifies, this list should eventually become empty.
63 63 EXCLUDE = [pjoin('IPython', 'external'),
64 64 pjoin('IPython', 'frontend', 'process', 'winprocess.py'),
65 65 pjoin('IPython_doctest_plugin'),
66 66 pjoin('IPython', 'Gnuplot'),
67 67 pjoin('IPython', 'Extensions', 'ipy_'),
68 68 pjoin('IPython', 'Extensions', 'clearcmd'),
69 69 pjoin('IPython', 'Extensions', 'PhysicalQInteractive'),
70 70 pjoin('IPython', 'Extensions', 'scitedirector'),
71 71 pjoin('IPython', 'Extensions', 'numeric_formats'),
72 72 pjoin('IPython', 'testing', 'attic'),
73 73 pjoin('IPython', 'testing', 'tutils'),
74 pjoin('IPython', 'testing', 'tools')
74 pjoin('IPython', 'testing', 'tools'),
75 pjoin('IPython', 'testing', 'mkdoctests')
75 76 ]
76 77
77 78 if not have_wx:
78 79 EXCLUDE.append(pjoin('IPython', 'Extensions', 'igrid'))
79 80 EXCLUDE.append(pjoin('IPython', 'gui'))
80 81 EXCLUDE.append(pjoin('IPython', 'frontend', 'wx'))
81 82
82 83 if not have_objc:
83 84 EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa'))
84 85
85 86 if not have_curses:
86 87 EXCLUDE.append(pjoin('IPython', 'Extensions', 'ibrowse'))
87 88
88 89 if not sys.platform == 'win32':
89 90 EXCLUDE.append(pjoin('IPython', 'platutils_win32'))
90 91
92 if sys.platform == 'win32':
93 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'test_exampleip'))
94 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'dtexample'))
95
91 96 if not os.name == 'posix':
92 97 EXCLUDE.append(pjoin('IPython', 'platutils_posix'))
93 98
94 99 if not have_pexpect:
95 100 EXCLUDE.append(pjoin('IPython', 'irunner'))
96 101
97 102 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
98 103 if sys.platform == 'win32':
99 104 EXCLUDE = [s.replace('\\','\\\\') for s in EXCLUDE]
100 105
101 106
102 107 #-----------------------------------------------------------------------------
103 108 # Functions and classes
104 109 #-----------------------------------------------------------------------------
105 110
106 111 def run_iptest():
107 112 """Run the IPython test suite using nose.
108 113
109 114 This function is called when this script is **not** called with the form
110 115 `iptest all`. It simply calls nose with appropriate command line flags
111 116 and accepts all of the standard nose arguments.
112 117 """
113 118
114 119 warnings.filterwarnings('ignore',
115 120 'This will be removed soon. Use IPython.testing.util instead')
116 121
117 122 argv = sys.argv + [
118 123 # Loading ipdoctest causes problems with Twisted.
119 124 # I am removing this as a temporary fix to get the
120 125 # test suite back into working shape. Our nose
121 126 # plugin needs to be gone through with a fine
122 127 # toothed comb to find what is causing the problem.
123 128 '--with-ipdoctest',
124 129 '--ipdoctest-tests','--ipdoctest-extension=txt',
125 130 '--detailed-errors',
126 131
127 132 # We add --exe because of setuptools' imbecility (it
128 133 # blindly does chmod +x on ALL files). Nose does the
129 134 # right thing and it tries to avoid executables,
130 135 # setuptools unfortunately forces our hand here. This
131 136 # has been discussed on the distutils list and the
132 137 # setuptools devs refuse to fix this problem!
133 138 '--exe',
134 139 ]
135 140
136 141 # Detect if any tests were required by explicitly calling an IPython
137 142 # submodule or giving a specific path
138 143 has_tests = False
139 144 for arg in sys.argv:
140 145 if 'IPython' in arg or arg.endswith('.py') or \
141 146 (':' in arg and '.py' in arg):
142 147 has_tests = True
143 148 break
144 149
145 150 # If nothing was specifically requested, test full IPython
146 151 if not has_tests:
147 152 argv.append('IPython')
148 153
149 154 # Construct list of plugins, omitting the existing doctest plugin, which
150 155 # ours replaces (and extends).
151 156 plugins = [IPythonDoctest(EXCLUDE)]
152 157 for p in nose.plugins.builtin.plugins:
153 158 plug = p()
154 159 if plug.name == 'doctest':
155 160 continue
156 161
157 162 #print '*** adding plugin:',plug.name # dbg
158 163 plugins.append(plug)
159 164
160 165 TestProgram(argv=argv,plugins=plugins)
161 166
162 167
163 168 class IPTester(object):
164 169 """Call that calls iptest or trial in a subprocess.
165 170 """
166 171 def __init__(self,runner='iptest',params=None):
167 172 """ """
168 173 if runner == 'iptest':
169 174 self.runner = ['iptest','-v']
170 175 else:
171 176 self.runner = [find_cmd('trial')]
172 177 if params is None:
173 178 params = []
174 179 if isinstance(params,str):
175 180 params = [params]
176 181 self.params = params
177 182
178 183 # Assemble call
179 184 self.call_args = self.runner+self.params
180 185
181 186 def run(self):
182 187 """Run the stored commands"""
183 188 return subprocess.call(self.call_args)
184 189
185 190
186 191 def make_runners():
187 192 """Define the modules and packages that need to be tested.
188 193 """
189 194
190 195 # This omits additional top-level modules that should not be doctested.
191 196 # XXX: Shell.py is also ommited because of a bug in the skip_doctest
192 197 # decorator. See ticket https://bugs.launchpad.net/bugs/366209
193 198 top_mod = \
194 199 ['background_jobs.py', 'ColorANSI.py', 'completer.py', 'ConfigLoader.py',
195 200 'CrashHandler.py', 'Debugger.py', 'deep_reload.py', 'demo.py',
196 201 'DPyGetOpt.py', 'dtutils.py', 'excolors.py', 'FakeModule.py',
197 202 'generics.py', 'genutils.py', 'history.py', 'hooks.py', 'ipapi.py',
198 203 'iplib.py', 'ipmaker.py', 'ipstruct.py', 'Itpl.py',
199 204 'Logger.py', 'macro.py', 'Magic.py', 'OInspect.py',
200 205 'OutputTrap.py', 'platutils.py', 'prefilter.py', 'Prompts.py',
201 206 'PyColorize.py', 'Release.py', 'rlineimpl.py', 'shadowns.py',
202 207 'shellglobals.py', 'strdispatch.py', 'twshell.py',
203 208 'ultraTB.py', 'upgrade_dir.py', 'usage.py', 'wildcard.py',
204 209 # See note above for why this is skipped
205 210 # 'Shell.py',
206 211 'winconsole.py']
207 212
208 213 if have_pexpect:
209 214 top_mod.append('irunner.py')
210 215
211 216 # These are tested by nose, so skip IPython.kernel
212 217 top_pack = ['config','Extensions','frontend',
213 218 'testing','tests','tools','UserConfig']
214 219
215 220 if have_wx:
216 221 top_pack.append('gui')
217 222
218 223 modules = ['IPython.%s' % m[:-3] for m in top_mod ]
219 224 packages = ['IPython.%s' % m for m in top_pack ]
220 225
221 226 # Make runners
222 227 runners = dict(zip(top_pack, [IPTester(params=v) for v in packages]))
223 228
224 229 # Test IPython.kernel using trial if twisted is installed
225 230 if have_zi and have_twisted and have_foolscap:
226 231 runners['trial'] = IPTester('trial',['IPython'])
227 232
228 233 runners['modules'] = IPTester(params=modules)
229 234
230 235 return runners
231 236
232 237
233 238 def run_iptestall():
234 239 """Run the entire IPython test suite by calling nose and trial.
235 240
236 241 This function constructs :class:`IPTester` instances for all IPython
237 242 modules and package and then runs each of them. This causes the modules
238 243 and packages of IPython to be tested each in their own subprocess using
239 244 nose or twisted.trial appropriately.
240 245 """
241 246 runners = make_runners()
242 247 # Run all test runners, tracking execution time
243 248 failed = {}
244 249 t_start = time.time()
245 250 for name,runner in runners.iteritems():
246 251 print '*'*77
247 252 print 'IPython test set:',name
248 253 res = runner.run()
249 254 if res:
250 255 failed[name] = res
251 256 t_end = time.time()
252 257 t_tests = t_end - t_start
253 258 nrunners = len(runners)
254 259 nfail = len(failed)
255 260 # summarize results
256 261 print
257 262 print '*'*77
258 263 print 'Ran %s test sets in %.3fs' % (nrunners, t_tests)
259 264 print
260 265 if not failed:
261 266 print 'OK'
262 267 else:
263 268 # If anything went wrong, point out what command to rerun manually to
264 269 # see the actual errors and individual summary
265 270 print 'ERROR - %s out of %s test sets failed.' % (nfail, nrunners)
266 271 for name in failed:
267 272 failed_runner = runners[name]
268 273 print '-'*40
269 274 print 'Runner failed:',name
270 275 print 'You may wish to rerun this one individually, with:'
271 276 print ' '.join(failed_runner.call_args)
272 277 print
273 278
274 279
275 280 def main():
276 281 if sys.argv[1] == 'all':
277 282 run_iptestall()
278 283 else:
279 284 run_iptest()
280 285
281 286
282 287 if __name__ == '__main__':
283 288 main() No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now