##// END OF EJS Templates
run-tests: add --first switch to exit on first error
Matt Mackall -
r3301:3cd51b98 default
parent child Browse files
Show More
@@ -1,387 +1,391 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # run-tests.py - Run a set of tests on Mercurial
3 # run-tests.py - Run a set of tests on Mercurial
4 #
4 #
5 # Copyright 2006 Matt Mackall <mpm@selenic.com>
5 # Copyright 2006 Matt Mackall <mpm@selenic.com>
6 #
6 #
7 # This software may be used and distributed according to the terms
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import optparse
12 import optparse
13 import os
13 import os
14 import popen2
14 import popen2
15 import re
15 import re
16 import shutil
16 import shutil
17 import signal
17 import signal
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import time
20 import time
21
21
22 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed", "merge"]
22 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed", "merge"]
23
23
24 parser = optparse.OptionParser("%prog [options] [tests]")
24 parser = optparse.OptionParser("%prog [options] [tests]")
25 parser.add_option("-v", "--verbose", action="store_true",
25 parser.add_option("-v", "--verbose", action="store_true",
26 help="output verbose messages")
26 help="output verbose messages")
27 parser.add_option("-t", "--timeout", type="int",
27 parser.add_option("-t", "--timeout", type="int",
28 help="kill errant tests after TIMEOUT seconds")
28 help="kill errant tests after TIMEOUT seconds")
29 parser.add_option("-c", "--cover", action="store_true",
29 parser.add_option("-c", "--cover", action="store_true",
30 help="print a test coverage report")
30 help="print a test coverage report")
31 parser.add_option("-s", "--cover_stdlib", action="store_true",
31 parser.add_option("-s", "--cover_stdlib", action="store_true",
32 help="print a test coverage report inc. standard libraries")
32 help="print a test coverage report inc. standard libraries")
33 parser.add_option("-C", "--annotate", action="store_true",
33 parser.add_option("-C", "--annotate", action="store_true",
34 help="output files annotated with coverage")
34 help="output files annotated with coverage")
35 parser.add_option("-r", "--retest", action="store_true",
35 parser.add_option("-r", "--retest", action="store_true",
36 help="retest failed tests")
36 help="retest failed tests")
37 parser.add_option("-f", "--first", action="store_true",
38 help="exit on the first test failure")
37
39
38 parser.set_defaults(timeout=180)
40 parser.set_defaults(timeout=180)
39 (options, args) = parser.parse_args()
41 (options, args) = parser.parse_args()
40 verbose = options.verbose
42 verbose = options.verbose
41 coverage = options.cover or options.cover_stdlib or options.annotate
43 coverage = options.cover or options.cover_stdlib or options.annotate
42
44
43 def vlog(*msg):
45 def vlog(*msg):
44 if verbose:
46 if verbose:
45 for m in msg:
47 for m in msg:
46 print m,
48 print m,
47 print
49 print
48
50
49 def splitnewlines(text):
51 def splitnewlines(text):
50 '''like str.splitlines, but only split on newlines.
52 '''like str.splitlines, but only split on newlines.
51 keep line endings.'''
53 keep line endings.'''
52 i = 0
54 i = 0
53 lines = []
55 lines = []
54 while True:
56 while True:
55 n = text.find('\n', i)
57 n = text.find('\n', i)
56 if n == -1:
58 if n == -1:
57 last = text[i:]
59 last = text[i:]
58 if last:
60 if last:
59 lines.append(last)
61 lines.append(last)
60 return lines
62 return lines
61 lines.append(text[i:n+1])
63 lines.append(text[i:n+1])
62 i = n + 1
64 i = n + 1
63
65
64 def show_diff(expected, output):
66 def show_diff(expected, output):
65 for line in difflib.unified_diff(expected, output,
67 for line in difflib.unified_diff(expected, output,
66 "Expected output", "Test output"):
68 "Expected output", "Test output"):
67 sys.stdout.write(line)
69 sys.stdout.write(line)
68
70
69 def find_program(program):
71 def find_program(program):
70 """Search PATH for a executable program"""
72 """Search PATH for a executable program"""
71 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
73 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
72 name = os.path.join(p, program)
74 name = os.path.join(p, program)
73 if os.access(name, os.X_OK):
75 if os.access(name, os.X_OK):
74 return name
76 return name
75 return None
77 return None
76
78
77 def check_required_tools():
79 def check_required_tools():
78 # Before we go any further, check for pre-requisite tools
80 # Before we go any further, check for pre-requisite tools
79 # stuff from coreutils (cat, rm, etc) are not tested
81 # stuff from coreutils (cat, rm, etc) are not tested
80 for p in required_tools:
82 for p in required_tools:
81 if os.name == 'nt':
83 if os.name == 'nt':
82 p += '.exe'
84 p += '.exe'
83 found = find_program(p)
85 found = find_program(p)
84 if found:
86 if found:
85 vlog("# Found prerequisite", p, "at", found)
87 vlog("# Found prerequisite", p, "at", found)
86 else:
88 else:
87 print "WARNING: Did not find prerequisite tool: "+p
89 print "WARNING: Did not find prerequisite tool: "+p
88
90
89 def cleanup_exit():
91 def cleanup_exit():
90 if verbose:
92 if verbose:
91 print "# Cleaning up HGTMP", HGTMP
93 print "# Cleaning up HGTMP", HGTMP
92 shutil.rmtree(HGTMP, True)
94 shutil.rmtree(HGTMP, True)
93
95
94 def use_correct_python():
96 def use_correct_python():
95 # some tests run python interpreter. they must use same
97 # some tests run python interpreter. they must use same
96 # interpreter we use or bad things will happen.
98 # interpreter we use or bad things will happen.
97 exedir, exename = os.path.split(sys.executable)
99 exedir, exename = os.path.split(sys.executable)
98 if exename == 'python':
100 if exename == 'python':
99 path = find_program('python')
101 path = find_program('python')
100 if os.path.dirname(path) == exedir:
102 if os.path.dirname(path) == exedir:
101 return
103 return
102 vlog('# Making python executable in test path use correct Python')
104 vlog('# Making python executable in test path use correct Python')
103 my_python = os.path.join(BINDIR, 'python')
105 my_python = os.path.join(BINDIR, 'python')
104 try:
106 try:
105 os.symlink(sys.executable, my_python)
107 os.symlink(sys.executable, my_python)
106 except AttributeError:
108 except AttributeError:
107 # windows fallback
109 # windows fallback
108 shutil.copyfile(sys.executable, my_python)
110 shutil.copyfile(sys.executable, my_python)
109 shutil.copymode(sys.executable, my_python)
111 shutil.copymode(sys.executable, my_python)
110
112
111 def install_hg():
113 def install_hg():
112 vlog("# Performing temporary installation of HG")
114 vlog("# Performing temporary installation of HG")
113 installerrs = os.path.join("tests", "install.err")
115 installerrs = os.path.join("tests", "install.err")
114
116
115 os.chdir("..") # Get back to hg root
117 os.chdir("..") # Get back to hg root
116 cmd = ('%s setup.py clean --all'
118 cmd = ('%s setup.py clean --all'
117 ' install --force --home="%s" --install-lib="%s" >%s 2>&1'
119 ' install --force --home="%s" --install-lib="%s" >%s 2>&1'
118 % (sys.executable, INST, PYTHONDIR, installerrs))
120 % (sys.executable, INST, PYTHONDIR, installerrs))
119 vlog("# Running", cmd)
121 vlog("# Running", cmd)
120 if os.system(cmd) == 0:
122 if os.system(cmd) == 0:
121 if not verbose:
123 if not verbose:
122 os.remove(installerrs)
124 os.remove(installerrs)
123 else:
125 else:
124 f = open(installerrs)
126 f = open(installerrs)
125 for line in f:
127 for line in f:
126 print line,
128 print line,
127 f.close()
129 f.close()
128 sys.exit(1)
130 sys.exit(1)
129 os.chdir(TESTDIR)
131 os.chdir(TESTDIR)
130
132
131 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
133 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
132 os.environ["PYTHONPATH"] = PYTHONDIR
134 os.environ["PYTHONPATH"] = PYTHONDIR
133
135
134 use_correct_python()
136 use_correct_python()
135
137
136 if coverage:
138 if coverage:
137 vlog("# Installing coverage wrapper")
139 vlog("# Installing coverage wrapper")
138 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
140 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
139 if os.path.exists(COVERAGE_FILE):
141 if os.path.exists(COVERAGE_FILE):
140 os.unlink(COVERAGE_FILE)
142 os.unlink(COVERAGE_FILE)
141 # Create a wrapper script to invoke hg via coverage.py
143 # Create a wrapper script to invoke hg via coverage.py
142 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
144 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
143 f = open(os.path.join(BINDIR, 'hg'), 'w')
145 f = open(os.path.join(BINDIR, 'hg'), 'w')
144 f.write('#!' + sys.executable + '\n')
146 f.write('#!' + sys.executable + '\n')
145 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '+ \
147 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '+ \
146 '"%s", "-x", "%s"] + sys.argv[1:])\n' % (
148 '"%s", "-x", "%s"] + sys.argv[1:])\n' % (
147 os.path.join(TESTDIR, 'coverage.py'),
149 os.path.join(TESTDIR, 'coverage.py'),
148 os.path.join(BINDIR, '_hg.py')))
150 os.path.join(BINDIR, '_hg.py')))
149 f.close()
151 f.close()
150 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
152 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
151
153
152 def output_coverage():
154 def output_coverage():
153 vlog("# Producing coverage report")
155 vlog("# Producing coverage report")
154 omit = [BINDIR, TESTDIR, PYTHONDIR]
156 omit = [BINDIR, TESTDIR, PYTHONDIR]
155 if not options.cover_stdlib:
157 if not options.cover_stdlib:
156 # Exclude as system paths (ignoring empty strings seen on win)
158 # Exclude as system paths (ignoring empty strings seen on win)
157 omit += [x for x in sys.path if x != '']
159 omit += [x for x in sys.path if x != '']
158 omit = ','.join(omit)
160 omit = ','.join(omit)
159 os.chdir(PYTHONDIR)
161 os.chdir(PYTHONDIR)
160 cmd = '"%s" "%s" -r "--omit=%s"' % (
162 cmd = '"%s" "%s" -r "--omit=%s"' % (
161 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
163 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
162 vlog("# Running: "+cmd)
164 vlog("# Running: "+cmd)
163 os.system(cmd)
165 os.system(cmd)
164 if options.annotate:
166 if options.annotate:
165 adir = os.path.join(TESTDIR, 'annotated')
167 adir = os.path.join(TESTDIR, 'annotated')
166 if not os.path.isdir(adir):
168 if not os.path.isdir(adir):
167 os.mkdir(adir)
169 os.mkdir(adir)
168 cmd = '"%s" "%s" -a "--directory=%s" "--omit=%s"' % (
170 cmd = '"%s" "%s" -a "--directory=%s" "--omit=%s"' % (
169 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
171 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
170 adir, omit)
172 adir, omit)
171 vlog("# Running: "+cmd)
173 vlog("# Running: "+cmd)
172 os.system(cmd)
174 os.system(cmd)
173
175
174 class Timeout(Exception):
176 class Timeout(Exception):
175 pass
177 pass
176
178
177 def alarmed(signum, frame):
179 def alarmed(signum, frame):
178 raise Timeout
180 raise Timeout
179
181
180 def run(cmd):
182 def run(cmd):
181 """Run command in a sub-process, capturing the output (stdout and stderr).
183 """Run command in a sub-process, capturing the output (stdout and stderr).
182 Return the exist code, and output."""
184 Return the exist code, and output."""
183 # TODO: Use subprocess.Popen if we're running on Python 2.4
185 # TODO: Use subprocess.Popen if we're running on Python 2.4
184 if os.name == 'nt':
186 if os.name == 'nt':
185 tochild, fromchild = os.popen4(cmd)
187 tochild, fromchild = os.popen4(cmd)
186 tochild.close()
188 tochild.close()
187 output = fromchild.read()
189 output = fromchild.read()
188 ret = fromchild.close()
190 ret = fromchild.close()
189 if ret == None:
191 if ret == None:
190 ret = 0
192 ret = 0
191 else:
193 else:
192 proc = popen2.Popen4(cmd)
194 proc = popen2.Popen4(cmd)
193 try:
195 try:
194 output = ''
196 output = ''
195 proc.tochild.close()
197 proc.tochild.close()
196 output = proc.fromchild.read()
198 output = proc.fromchild.read()
197 ret = proc.wait()
199 ret = proc.wait()
198 except Timeout:
200 except Timeout:
199 vlog('# Process %d timed out - killing it' % proc.pid)
201 vlog('# Process %d timed out - killing it' % proc.pid)
200 os.kill(proc.pid, signal.SIGTERM)
202 os.kill(proc.pid, signal.SIGTERM)
201 ret = proc.wait()
203 ret = proc.wait()
202 if ret == 0:
204 if ret == 0:
203 ret = signal.SIGTERM << 8
205 ret = signal.SIGTERM << 8
204 return ret, splitnewlines(output)
206 return ret, splitnewlines(output)
205
207
206 def run_one(test):
208 def run_one(test):
207 '''tristate output:
209 '''tristate output:
208 None -> skipped
210 None -> skipped
209 True -> passed
211 True -> passed
210 False -> failed'''
212 False -> failed'''
211
213
212 vlog("# Test", test)
214 vlog("# Test", test)
213 if not verbose:
215 if not verbose:
214 sys.stdout.write('.')
216 sys.stdout.write('.')
215 sys.stdout.flush()
217 sys.stdout.flush()
216
218
217 # create a fresh hgrc
219 # create a fresh hgrc
218 hgrc = file(HGRCPATH, 'w+')
220 hgrc = file(HGRCPATH, 'w+')
219 hgrc.close()
221 hgrc.close()
220
222
221 err = os.path.join(TESTDIR, test+".err")
223 err = os.path.join(TESTDIR, test+".err")
222 ref = os.path.join(TESTDIR, test+".out")
224 ref = os.path.join(TESTDIR, test+".out")
223
225
224 if os.path.exists(err):
226 if os.path.exists(err):
225 os.remove(err) # Remove any previous output files
227 os.remove(err) # Remove any previous output files
226
228
227 # Make a tmp subdirectory to work in
229 # Make a tmp subdirectory to work in
228 tmpd = os.path.join(HGTMP, test)
230 tmpd = os.path.join(HGTMP, test)
229 os.mkdir(tmpd)
231 os.mkdir(tmpd)
230 os.chdir(tmpd)
232 os.chdir(tmpd)
231
233
232 lctest = test.lower()
234 lctest = test.lower()
233
235
234 if lctest.endswith('.py'):
236 if lctest.endswith('.py'):
235 cmd = '%s "%s"' % (sys.executable, os.path.join(TESTDIR, test))
237 cmd = '%s "%s"' % (sys.executable, os.path.join(TESTDIR, test))
236 elif lctest.endswith('.bat'):
238 elif lctest.endswith('.bat'):
237 # do not run batch scripts on non-windows
239 # do not run batch scripts on non-windows
238 if os.name != 'nt':
240 if os.name != 'nt':
239 print '\nSkipping %s: batch script' % test
241 print '\nSkipping %s: batch script' % test
240 return None
242 return None
241 # To reliably get the error code from batch files on WinXP,
243 # To reliably get the error code from batch files on WinXP,
242 # the "cmd /c call" prefix is needed. Grrr
244 # the "cmd /c call" prefix is needed. Grrr
243 cmd = 'cmd /c call "%s"' % (os.path.join(TESTDIR, test))
245 cmd = 'cmd /c call "%s"' % (os.path.join(TESTDIR, test))
244 else:
246 else:
245 # do not run shell scripts on windows
247 # do not run shell scripts on windows
246 if os.name == 'nt':
248 if os.name == 'nt':
247 print '\nSkipping %s: shell script' % test
249 print '\nSkipping %s: shell script' % test
248 return None
250 return None
249 # do not try to run non-executable programs
251 # do not try to run non-executable programs
250 if not os.access(os.path.join(TESTDIR, test), os.X_OK):
252 if not os.access(os.path.join(TESTDIR, test), os.X_OK):
251 print '\nSkipping %s: not executable' % test
253 print '\nSkipping %s: not executable' % test
252 return None
254 return None
253 cmd = '"%s"' % (os.path.join(TESTDIR, test))
255 cmd = '"%s"' % (os.path.join(TESTDIR, test))
254
256
255 if options.timeout > 0:
257 if options.timeout > 0:
256 signal.alarm(options.timeout)
258 signal.alarm(options.timeout)
257
259
258 vlog("# Running", cmd)
260 vlog("# Running", cmd)
259 ret, out = run(cmd)
261 ret, out = run(cmd)
260 vlog("# Ret was:", ret)
262 vlog("# Ret was:", ret)
261
263
262 if options.timeout > 0:
264 if options.timeout > 0:
263 signal.alarm(0)
265 signal.alarm(0)
264
266
265 diffret = 0
267 diffret = 0
266 # If reference output file exists, check test output against it
268 # If reference output file exists, check test output against it
267 if os.path.exists(ref):
269 if os.path.exists(ref):
268 f = open(ref, "r")
270 f = open(ref, "r")
269 ref_out = splitnewlines(f.read())
271 ref_out = splitnewlines(f.read())
270 f.close()
272 f.close()
271 else:
273 else:
272 ref_out = []
274 ref_out = []
273 if out != ref_out:
275 if out != ref_out:
274 diffret = 1
276 diffret = 1
275 print "\nERROR: %s output changed" % (test)
277 print "\nERROR: %s output changed" % (test)
276 show_diff(ref_out, out)
278 show_diff(ref_out, out)
277 if ret:
279 if ret:
278 print "\nERROR: %s failed with error code %d" % (test, ret)
280 print "\nERROR: %s failed with error code %d" % (test, ret)
279 elif diffret:
281 elif diffret:
280 ret = diffret
282 ret = diffret
281
283
282 if ret != 0: # Save errors to a file for diagnosis
284 if ret != 0: # Save errors to a file for diagnosis
283 f = open(err, "wb")
285 f = open(err, "wb")
284 for line in out:
286 for line in out:
285 f.write(line)
287 f.write(line)
286 f.close()
288 f.close()
287
289
288 # Kill off any leftover daemon processes
290 # Kill off any leftover daemon processes
289 try:
291 try:
290 fp = file(DAEMON_PIDS)
292 fp = file(DAEMON_PIDS)
291 for line in fp:
293 for line in fp:
292 try:
294 try:
293 pid = int(line)
295 pid = int(line)
294 except ValueError:
296 except ValueError:
295 continue
297 continue
296 try:
298 try:
297 os.kill(pid, 0)
299 os.kill(pid, 0)
298 vlog('# Killing daemon process %d' % pid)
300 vlog('# Killing daemon process %d' % pid)
299 os.kill(pid, signal.SIGTERM)
301 os.kill(pid, signal.SIGTERM)
300 time.sleep(0.25)
302 time.sleep(0.25)
301 os.kill(pid, 0)
303 os.kill(pid, 0)
302 vlog('# Daemon process %d is stuck - really killing it' % pid)
304 vlog('# Daemon process %d is stuck - really killing it' % pid)
303 os.kill(pid, signal.SIGKILL)
305 os.kill(pid, signal.SIGKILL)
304 except OSError, err:
306 except OSError, err:
305 if err.errno != errno.ESRCH:
307 if err.errno != errno.ESRCH:
306 raise
308 raise
307 fp.close()
309 fp.close()
308 os.unlink(DAEMON_PIDS)
310 os.unlink(DAEMON_PIDS)
309 except IOError:
311 except IOError:
310 pass
312 pass
311
313
312 os.chdir(TESTDIR)
314 os.chdir(TESTDIR)
313 shutil.rmtree(tmpd, True)
315 shutil.rmtree(tmpd, True)
314 return ret == 0
316 return ret == 0
315
317
316
318
317 os.umask(022)
319 os.umask(022)
318
320
319 check_required_tools()
321 check_required_tools()
320
322
321 # Reset some environment variables to well-known values so that
323 # Reset some environment variables to well-known values so that
322 # the tests produce repeatable output.
324 # the tests produce repeatable output.
323 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
325 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
324 os.environ['TZ'] = 'GMT'
326 os.environ['TZ'] = 'GMT'
325
327
326 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
328 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
327 os.environ["HGMERGE"] = sys.executable + ' -c "import sys; sys.exit(0)"'
329 os.environ["HGMERGE"] = sys.executable + ' -c "import sys; sys.exit(0)"'
328 os.environ["HGUSER"] = "test"
330 os.environ["HGUSER"] = "test"
329
331
330 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
332 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
331 HGTMP = os.environ["HGTMP"] = tempfile.mkdtemp("", "hgtests.")
333 HGTMP = os.environ["HGTMP"] = tempfile.mkdtemp("", "hgtests.")
332 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
334 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
333 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
335 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
334
336
335 vlog("# Using TESTDIR", TESTDIR)
337 vlog("# Using TESTDIR", TESTDIR)
336 vlog("# Using HGTMP", HGTMP)
338 vlog("# Using HGTMP", HGTMP)
337
339
338 INST = os.path.join(HGTMP, "install")
340 INST = os.path.join(HGTMP, "install")
339 BINDIR = os.path.join(INST, "bin")
341 BINDIR = os.path.join(INST, "bin")
340 PYTHONDIR = os.path.join(INST, "lib", "python")
342 PYTHONDIR = os.path.join(INST, "lib", "python")
341 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
343 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
342
344
343 try:
345 try:
344 try:
346 try:
345 install_hg()
347 install_hg()
346
348
347 if options.timeout > 0:
349 if options.timeout > 0:
348 try:
350 try:
349 signal.signal(signal.SIGALRM, alarmed)
351 signal.signal(signal.SIGALRM, alarmed)
350 vlog('# Running tests with %d-second timeout' %
352 vlog('# Running tests with %d-second timeout' %
351 options.timeout)
353 options.timeout)
352 except AttributeError:
354 except AttributeError:
353 print 'WARNING: cannot run tests with timeouts'
355 print 'WARNING: cannot run tests with timeouts'
354 options.timeout = 0
356 options.timeout = 0
355
357
356 tests = 0
358 tests = 0
357 failed = 0
359 failed = 0
358 skipped = 0
360 skipped = 0
359
361
360 if len(args) == 0:
362 if len(args) == 0:
361 args = os.listdir(".")
363 args = os.listdir(".")
362 for test in args:
364 for test in args:
363 if (test.startswith("test-") and '~' not in test and
365 if (test.startswith("test-") and '~' not in test and
364 ('.' not in test or test.endswith('.py') or
366 ('.' not in test or test.endswith('.py') or
365 test.endswith('.bat'))):
367 test.endswith('.bat'))):
366 if options.retest and not os.path.exists(test + ".err"):
368 if options.retest and not os.path.exists(test + ".err"):
367 skipped += 1
369 skipped += 1
368 continue
370 continue
369 ret = run_one(test)
371 ret = run_one(test)
370 if ret is None:
372 if ret is None:
371 skipped += 1
373 skipped += 1
372 elif not ret:
374 elif not ret:
373 failed += 1
375 failed += 1
376 if options.first:
377 break
374 tests += 1
378 tests += 1
375
379
376 print "\n# Ran %d tests, %d skipped, %d failed." % (tests, skipped,
380 print "\n# Ran %d tests, %d skipped, %d failed." % (tests, skipped,
377 failed)
381 failed)
378 if coverage:
382 if coverage:
379 output_coverage()
383 output_coverage()
380 except KeyboardInterrupt:
384 except KeyboardInterrupt:
381 failed = True
385 failed = True
382 print "\ninterrupted!"
386 print "\ninterrupted!"
383 finally:
387 finally:
384 cleanup_exit()
388 cleanup_exit()
385
389
386 if failed:
390 if failed:
387 sys.exit(1)
391 sys.exit(1)
General Comments 0
You need to be logged in to leave comments. Login now