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