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