##// END OF EJS Templates
Small fixes for wx-dependent tests and include clearcmd....
Fernando Perez -
Show More
@@ -1,300 +1,305 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 have_wx_aui = test_for('wx.aui')
53 54 have_zi = test_for('zope.interface')
54 55 have_twisted = test_for('twisted')
55 56 have_foolscap = test_for('foolscap')
56 57 have_objc = test_for('objc')
57 58 have_pexpect = test_for('pexpect')
58 59
59 60 # For the IPythonDoctest plugin, we need to exclude certain patterns that cause
60 61 # testing problems. We should strive to minimize the number of skipped
61 62 # modules, since this means untested code. As the testing machinery
62 63 # solidifies, this list should eventually become empty.
63 64 EXCLUDE = [pjoin('IPython', 'external'),
64 65 pjoin('IPython', 'frontend', 'process', 'winprocess.py'),
65 66 pjoin('IPython_doctest_plugin'),
66 67 pjoin('IPython', 'Gnuplot'),
67 68 pjoin('IPython', 'Extensions', 'ipy_'),
68 pjoin('IPython', 'Extensions', 'clearcmd'),
69 pjoin('IPython', 'Extensions', 'PhysicalQInput'),
69 70 pjoin('IPython', 'Extensions', 'PhysicalQInteractive'),
71 pjoin('IPython', 'Extensions', 'InterpreterPasteInput'),
70 72 pjoin('IPython', 'Extensions', 'scitedirector'),
71 73 pjoin('IPython', 'Extensions', 'numeric_formats'),
72 74 pjoin('IPython', 'testing', 'attic'),
73 75 pjoin('IPython', 'testing', 'tutils'),
74 76 pjoin('IPython', 'testing', 'tools'),
75 pjoin('IPython', 'testing', 'mkdoctests')
77 pjoin('IPython', 'testing', 'mkdoctests'),
76 78 ]
77 79
78 80 if not have_wx:
79 81 EXCLUDE.append(pjoin('IPython', 'Extensions', 'igrid'))
80 82 EXCLUDE.append(pjoin('IPython', 'gui'))
81 83 EXCLUDE.append(pjoin('IPython', 'frontend', 'wx'))
82 84
85 if not have_wx_aui:
86 EXCLUDE.append(pjoin('IPython', 'gui', 'wx', 'wxIPython'))
87
83 88 if not have_objc:
84 89 EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa'))
85 90
86 91 if not have_curses:
87 92 EXCLUDE.append(pjoin('IPython', 'Extensions', 'ibrowse'))
88 93
89 94 if not sys.platform == 'win32':
90 95 EXCLUDE.append(pjoin('IPython', 'platutils_win32'))
91 96
92 97 # These have to be skipped on win32 because the use echo, rm, cd, etc.
93 98 # See ticket https://bugs.launchpad.net/bugs/366982
94 99 if sys.platform == 'win32':
95 100 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'test_exampleip'))
96 101 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'dtexample'))
97 102
98 103 if not os.name == 'posix':
99 104 EXCLUDE.append(pjoin('IPython', 'platutils_posix'))
100 105
101 106 if not have_pexpect:
102 107 EXCLUDE.append(pjoin('IPython', 'irunner'))
103 108
104 109 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
105 110 if sys.platform == 'win32':
106 111 EXCLUDE = [s.replace('\\','\\\\') for s in EXCLUDE]
107 112
108 113
109 114 #-----------------------------------------------------------------------------
110 115 # Functions and classes
111 116 #-----------------------------------------------------------------------------
112 117
113 118 def run_iptest():
114 119 """Run the IPython test suite using nose.
115 120
116 121 This function is called when this script is **not** called with the form
117 122 `iptest all`. It simply calls nose with appropriate command line flags
118 123 and accepts all of the standard nose arguments.
119 124 """
120 125
121 126 warnings.filterwarnings('ignore',
122 127 'This will be removed soon. Use IPython.testing.util instead')
123 128
124 129 argv = sys.argv + [
125 130 # Loading ipdoctest causes problems with Twisted.
126 131 # I am removing this as a temporary fix to get the
127 132 # test suite back into working shape. Our nose
128 133 # plugin needs to be gone through with a fine
129 134 # toothed comb to find what is causing the problem.
130 135 '--with-ipdoctest',
131 136 '--ipdoctest-tests','--ipdoctest-extension=txt',
132 137 '--detailed-errors',
133 138
134 139 # We add --exe because of setuptools' imbecility (it
135 140 # blindly does chmod +x on ALL files). Nose does the
136 141 # right thing and it tries to avoid executables,
137 142 # setuptools unfortunately forces our hand here. This
138 143 # has been discussed on the distutils list and the
139 144 # setuptools devs refuse to fix this problem!
140 145 '--exe',
141 146 ]
142 147
143 148 # Detect if any tests were required by explicitly calling an IPython
144 149 # submodule or giving a specific path
145 150 has_tests = False
146 151 for arg in sys.argv:
147 152 if 'IPython' in arg or arg.endswith('.py') or \
148 153 (':' in arg and '.py' in arg):
149 154 has_tests = True
150 155 break
151 156
152 157 # If nothing was specifically requested, test full IPython
153 158 if not has_tests:
154 159 argv.append('IPython')
155 160
156 161 # Construct list of plugins, omitting the existing doctest plugin, which
157 162 # ours replaces (and extends).
158 163 plugins = [IPythonDoctest(EXCLUDE)]
159 164 for p in nose.plugins.builtin.plugins:
160 165 plug = p()
161 166 if plug.name == 'doctest':
162 167 continue
163 168
164 169 #print '*** adding plugin:',plug.name # dbg
165 170 plugins.append(plug)
166 171
167 172 TestProgram(argv=argv,plugins=plugins)
168 173
169 174
170 175 class IPTester(object):
171 176 """Call that calls iptest or trial in a subprocess.
172 177 """
173 178 def __init__(self,runner='iptest',params=None):
174 179 """ """
175 180 if runner == 'iptest':
176 181 self.runner = ['iptest','-v']
177 182 else:
178 183 self.runner = [find_cmd('trial')]
179 184 if params is None:
180 185 params = []
181 186 if isinstance(params,str):
182 187 params = [params]
183 188 self.params = params
184 189
185 190 # Assemble call
186 191 self.call_args = self.runner+self.params
187 192
188 193 def run(self):
189 194 """Run the stored commands"""
190 195 return subprocess.call(self.call_args)
191 196
192 197
193 198 def make_runners():
194 199 """Define the modules and packages that need to be tested.
195 200 """
196 201
197 202 # This omits additional top-level modules that should not be doctested.
198 203 # XXX: Shell.py is also ommited because of a bug in the skip_doctest
199 204 # decorator. See ticket https://bugs.launchpad.net/bugs/366209
200 205 top_mod = \
201 206 ['background_jobs.py', 'ColorANSI.py', 'completer.py', 'ConfigLoader.py',
202 207 'CrashHandler.py', 'Debugger.py', 'deep_reload.py', 'demo.py',
203 208 'DPyGetOpt.py', 'dtutils.py', 'excolors.py', 'FakeModule.py',
204 209 'generics.py', 'genutils.py', 'history.py', 'hooks.py', 'ipapi.py',
205 210 'iplib.py', 'ipmaker.py', 'ipstruct.py', 'Itpl.py',
206 211 'Logger.py', 'macro.py', 'Magic.py', 'OInspect.py',
207 212 'OutputTrap.py', 'platutils.py', 'prefilter.py', 'Prompts.py',
208 213 'PyColorize.py', 'Release.py', 'rlineimpl.py', 'shadowns.py',
209 214 'shellglobals.py', 'strdispatch.py', 'twshell.py',
210 215 'ultraTB.py', 'upgrade_dir.py', 'usage.py', 'wildcard.py',
211 216 # See note above for why this is skipped
212 217 # 'Shell.py',
213 218 'winconsole.py']
214 219
215 220 if have_pexpect:
216 221 top_mod.append('irunner.py')
217 222
218 223 if sys.platform == 'win32':
219 224 top_mod.append('platutils_win32.py')
220 225 elif os.name == 'posix':
221 226 top_mod.append('platutils_posix.py')
222 227 else:
223 228 top_mod.append('platutils_dummy.py')
224 229
225 230 # These are tested by nose, so skip IPython.kernel
226 231 top_pack = ['config','Extensions','frontend',
227 232 'testing','tests','tools','UserConfig']
228 233
229 234 if have_wx:
230 235 top_pack.append('gui')
231 236
232 237 modules = ['IPython.%s' % m[:-3] for m in top_mod ]
233 238 packages = ['IPython.%s' % m for m in top_pack ]
234 239
235 240 # Make runners
236 241 runners = dict(zip(top_pack, [IPTester(params=v) for v in packages]))
237 242
238 243 # Test IPython.kernel using trial if twisted is installed
239 244 if have_zi and have_twisted and have_foolscap:
240 245 runners['trial'] = IPTester('trial',['IPython'])
241 246
242 247 runners['modules'] = IPTester(params=modules)
243 248
244 249 return runners
245 250
246 251
247 252 def run_iptestall():
248 253 """Run the entire IPython test suite by calling nose and trial.
249 254
250 255 This function constructs :class:`IPTester` instances for all IPython
251 256 modules and package and then runs each of them. This causes the modules
252 257 and packages of IPython to be tested each in their own subprocess using
253 258 nose or twisted.trial appropriately.
254 259 """
255 260 runners = make_runners()
256 261 # Run all test runners, tracking execution time
257 262 failed = {}
258 263 t_start = time.time()
259 264 for name,runner in runners.iteritems():
260 265 print '*'*77
261 print 'IPython test set:',name
266 print 'IPython test group:',name
262 267 res = runner.run()
263 268 if res:
264 269 failed[name] = res
265 270 t_end = time.time()
266 271 t_tests = t_end - t_start
267 272 nrunners = len(runners)
268 273 nfail = len(failed)
269 274 # summarize results
270 275 print
271 276 print '*'*77
272 print 'Ran %s test sets in %.3fs' % (nrunners, t_tests)
277 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
273 278 print
274 279 if not failed:
275 280 print 'OK'
276 281 else:
277 282 # If anything went wrong, point out what command to rerun manually to
278 283 # see the actual errors and individual summary
279 print 'ERROR - %s out of %s test sets failed.' % (nfail, nrunners)
284 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
280 285 for name in failed:
281 286 failed_runner = runners[name]
282 287 print '-'*40
283 288 print 'Runner failed:',name
284 289 print 'You may wish to rerun this one individually, with:'
285 290 print ' '.join(failed_runner.call_args)
286 291 print
287 292
288 293
289 294 def main():
290 295 if len(sys.argv) == 1:
291 296 run_iptestall()
292 297 else:
293 298 if sys.argv[1] == 'all':
294 299 run_iptestall()
295 300 else:
296 301 run_iptest()
297 302
298 303
299 304 if __name__ == '__main__':
300 main() No newline at end of file
305 main()
General Comments 0
You need to be logged in to leave comments. Login now