blob: 6364d7179c36a65296550f6ea5603ec59fe3318b [file] [log] [blame]
Guido van Rossum152494a1996-12-20 03:12:20 +00001#! /usr/bin/env python
2
3"""Regression test.
4
5This will find all modules whose name is "test_*" in the test
6directory, and run them. Various command line options provide
7additional facilities.
8
9Command line options:
10
Barry Warsawe11e3de1999-01-28 19:51:51 +000011-v: verbose -- run tests in verbose mode with output to stdout
12-q: quiet -- don't print anything except if a test fails
Guido van Rossum152494a1996-12-20 03:12:20 +000013-g: generate -- write the output file for a test instead of comparing it
Barry Warsawe11e3de1999-01-28 19:51:51 +000014-x: exclude -- arguments are tests to *exclude*
15-s: single -- run only a single test (see below)
Guido van Rossum152494a1996-12-20 03:12:20 +000016
17If non-option arguments are present, they are names for tests to run,
18unless -x is given, in which case they are names for tests not to run.
19If no test names are given, all tests are run.
Guido van Rossumf58ed251997-03-07 21:04:33 +000020
Guido van Rossuma4122201997-08-18 20:08:24 +000021-v is incompatible with -g and does not compare test output files.
Barry Warsawe11e3de1999-01-28 19:51:51 +000022
23-s means to run only a single test and exit. This is useful when Purifying
24the Python interpreter. The file /tmp/pynexttest is read to find the next
25test to run. If this file is missing, the first test_*.py file in testdir or
26on the command line is used. (actually tempfile.gettempdir() is used instead
27of /tmp).
28
Guido van Rossum152494a1996-12-20 03:12:20 +000029"""
30
31import sys
32import string
33import os
34import getopt
Guido van Rossum9e48b271997-07-16 01:56:13 +000035import traceback
Guido van Rossum152494a1996-12-20 03:12:20 +000036
37import test_support
38
Guido van Rossum6fd83b71998-08-01 17:04:08 +000039def main(tests=None, testdir=None):
40 """Execute a test suite.
41
42 This also parses command-line options and modifies its behaviour
43 accordingly.
44
45 tests -- a list of strings containing test names (optional)
46 testdir -- the directory in which to look for tests (optional)
47
48 Users other than the Python test suite will certainly want to
49 specify testdir; if it's omitted, the directory containing the
50 Python test suite is searched for.
51
52 If the tests argument is omitted, the tests listed on the
53 command-line will be used. If that's empty, too, then all *.py
54 files beginning with test_ will be used.
55
56 """
57
Guido van Rossum152494a1996-12-20 03:12:20 +000058 try:
Barry Warsawe11e3de1999-01-28 19:51:51 +000059 opts, args = getopt.getopt(sys.argv[1:], 'vgqxs')
Guido van Rossum152494a1996-12-20 03:12:20 +000060 except getopt.error, msg:
Guido van Rossum41360a41998-03-26 19:42:58 +000061 print msg
62 print __doc__
63 return 2
Guido van Rossum152494a1996-12-20 03:12:20 +000064 verbose = 0
65 quiet = 0
66 generate = 0
67 exclude = 0
Barry Warsawe11e3de1999-01-28 19:51:51 +000068 single = 0
Guido van Rossum152494a1996-12-20 03:12:20 +000069 for o, a in opts:
Guido van Rossum41360a41998-03-26 19:42:58 +000070 if o == '-v': verbose = verbose+1
71 if o == '-q': quiet = 1; verbose = 0
72 if o == '-g': generate = 1
73 if o == '-x': exclude = 1
Barry Warsawe11e3de1999-01-28 19:51:51 +000074 if o == '-s': single = 1
Guido van Rossuma4122201997-08-18 20:08:24 +000075 if generate and verbose:
Guido van Rossum41360a41998-03-26 19:42:58 +000076 print "-g and -v don't go together!"
77 return 2
Guido van Rossum152494a1996-12-20 03:12:20 +000078 good = []
79 bad = []
80 skipped = []
Barry Warsawe11e3de1999-01-28 19:51:51 +000081
82 if single:
83 from tempfile import gettempdir
84 filename = os.path.join(gettempdir(), 'pynexttest')
85 try:
86 fp = open(filename, 'r')
87 next = string.strip(fp.read())
88 tests = [next]
89 fp.close()
90 except IOError:
91 pass
Guido van Rossuma4122201997-08-18 20:08:24 +000092 for i in range(len(args)):
Guido van Rossum41360a41998-03-26 19:42:58 +000093 # Strip trailing ".py" from arguments
94 if args[i][-3:] == '.py':
95 args[i] = args[i][:-3]
Guido van Rossum6c74fea1998-08-25 12:29:08 +000096 stdtests = STDTESTS[:]
97 nottests = NOTTESTS[:]
Guido van Rossum152494a1996-12-20 03:12:20 +000098 if exclude:
Guido van Rossum6c74fea1998-08-25 12:29:08 +000099 for arg in args:
100 if arg in stdtests:
101 stdtests.remove(arg)
102 nottests[:0] = args
Guido van Rossum41360a41998-03-26 19:42:58 +0000103 args = []
Guido van Rossum747e1ca1998-08-24 13:48:36 +0000104 tests = tests or args or findtests(testdir, stdtests, nottests)
Barry Warsawe11e3de1999-01-28 19:51:51 +0000105 if single:
106 tests = tests[:1]
Guido van Rossum41360a41998-03-26 19:42:58 +0000107 test_support.verbose = verbose # Tell tests to be moderately quiet
Guido van Rossum152494a1996-12-20 03:12:20 +0000108 for test in tests:
Guido van Rossum41360a41998-03-26 19:42:58 +0000109 if not quiet:
110 print test
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000111 ok = runtest(test, generate, verbose, testdir)
Guido van Rossum41360a41998-03-26 19:42:58 +0000112 if ok > 0:
113 good.append(test)
114 elif ok == 0:
115 bad.append(test)
116 else:
117 if not quiet:
118 print "test", test,
119 print "skipped -- an optional feature could not be imported"
120 skipped.append(test)
Guido van Rossum152494a1996-12-20 03:12:20 +0000121 if good and not quiet:
Guido van Rossum41360a41998-03-26 19:42:58 +0000122 if not bad and not skipped and len(good) > 1:
123 print "All",
124 print count(len(good), "test"), "OK."
Guido van Rossum152494a1996-12-20 03:12:20 +0000125 if bad:
Guido van Rossum41360a41998-03-26 19:42:58 +0000126 print count(len(bad), "test"), "failed:",
127 print string.join(bad)
Guido van Rossum152494a1996-12-20 03:12:20 +0000128 if skipped and not quiet:
Guido van Rossum41360a41998-03-26 19:42:58 +0000129 print count(len(skipped), "test"), "skipped:",
130 print string.join(skipped)
Barry Warsawe11e3de1999-01-28 19:51:51 +0000131
132 if single:
133 alltests = findtests(testdir, stdtests, nottests)
134 for i in range(len(alltests)):
135 if tests[0] == alltests[i]:
136 if i == len(alltests) - 1:
137 os.unlink(filename)
138 else:
139 fp = open(filename, 'w')
140 fp.write(alltests[i+1] + '\n')
141 fp.close()
142 break
143 else:
144 os.unlink(filename)
145
Guido van Rossume8387011997-08-14 19:40:34 +0000146 return len(bad) > 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000147
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000148STDTESTS = [
Guido van Rossum152494a1996-12-20 03:12:20 +0000149 'test_grammar',
150 'test_opcodes',
151 'test_operations',
152 'test_builtin',
153 'test_exceptions',
154 'test_types',
155 ]
156
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000157NOTTESTS = [
Guido van Rossum152494a1996-12-20 03:12:20 +0000158 'test_support',
159 'test_b1',
160 'test_b2',
161 ]
162
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000163def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
Guido van Rossum152494a1996-12-20 03:12:20 +0000164 """Return a list of all applicable test modules."""
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000165 if not testdir: testdir = findtestdir()
Guido van Rossum152494a1996-12-20 03:12:20 +0000166 names = os.listdir(testdir)
167 tests = []
168 for name in names:
Guido van Rossum41360a41998-03-26 19:42:58 +0000169 if name[:5] == "test_" and name[-3:] == ".py":
170 modname = name[:-3]
171 if modname not in stdtests and modname not in nottests:
172 tests.append(modname)
Guido van Rossum152494a1996-12-20 03:12:20 +0000173 tests.sort()
174 return stdtests + tests
175
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000176def runtest(test, generate, verbose, testdir = None):
177 """Run a single test.
178 test -- the name of the test
179 generate -- if true, generate output, instead of running the test
180 and comparing it to a previously created output file
181 verbose -- if true, print more messages
182 testdir -- test directory
183 """
Guido van Rossum152494a1996-12-20 03:12:20 +0000184 test_support.unload(test)
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000185 if not testdir: testdir = findtestdir()
Guido van Rossum152494a1996-12-20 03:12:20 +0000186 outputdir = os.path.join(testdir, "output")
187 outputfile = os.path.join(outputdir, test)
188 try:
Guido van Rossum41360a41998-03-26 19:42:58 +0000189 if generate:
190 cfp = open(outputfile, "w")
191 elif verbose:
192 cfp = sys.stdout
193 else:
194 cfp = Compare(outputfile)
Guido van Rossum152494a1996-12-20 03:12:20 +0000195 except IOError:
Guido van Rossum41360a41998-03-26 19:42:58 +0000196 cfp = None
197 print "Warning: can't open", outputfile
Guido van Rossum152494a1996-12-20 03:12:20 +0000198 try:
Guido van Rossum41360a41998-03-26 19:42:58 +0000199 save_stdout = sys.stdout
200 try:
201 if cfp:
202 sys.stdout = cfp
203 print test # Output file starts with test name
204 __import__(test, globals(), locals(), [])
205 finally:
206 sys.stdout = save_stdout
Guido van Rossum152494a1996-12-20 03:12:20 +0000207 except ImportError, msg:
Guido van Rossum41360a41998-03-26 19:42:58 +0000208 return -1
Guido van Rossum4e8ef5f1997-10-20 23:46:54 +0000209 except KeyboardInterrupt, v:
Guido van Rossum41360a41998-03-26 19:42:58 +0000210 raise KeyboardInterrupt, v, sys.exc_info()[2]
Guido van Rossum152494a1996-12-20 03:12:20 +0000211 except test_support.TestFailed, msg:
Guido van Rossum41360a41998-03-26 19:42:58 +0000212 print "test", test, "failed --", msg
213 return 0
Guido van Rossum9e48b271997-07-16 01:56:13 +0000214 except:
Guido van Rossum41360a41998-03-26 19:42:58 +0000215 type, value = sys.exc_info()[:2]
216 print "test", test, "crashed --", type, ":", value
217 if verbose:
218 traceback.print_exc(file=sys.stdout)
219 return 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000220 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000221 return 1
Guido van Rossum152494a1996-12-20 03:12:20 +0000222
223def findtestdir():
224 if __name__ == '__main__':
Guido van Rossum41360a41998-03-26 19:42:58 +0000225 file = sys.argv[0]
Guido van Rossum152494a1996-12-20 03:12:20 +0000226 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000227 file = __file__
Guido van Rossum152494a1996-12-20 03:12:20 +0000228 testdir = os.path.dirname(file) or os.curdir
229 return testdir
230
231def count(n, word):
232 if n == 1:
Guido van Rossum41360a41998-03-26 19:42:58 +0000233 return "%d %s" % (n, word)
Guido van Rossum152494a1996-12-20 03:12:20 +0000234 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000235 return "%d %ss" % (n, word)
Guido van Rossum152494a1996-12-20 03:12:20 +0000236
237class Compare:
238
239 def __init__(self, filename):
Guido van Rossum41360a41998-03-26 19:42:58 +0000240 self.fp = open(filename, 'r')
Guido van Rossum152494a1996-12-20 03:12:20 +0000241
242 def write(self, data):
Guido van Rossum41360a41998-03-26 19:42:58 +0000243 expected = self.fp.read(len(data))
244 if data <> expected:
245 raise test_support.TestFailed, \
246 'Writing: '+`data`+', expected: '+`expected`
Guido van Rossum152494a1996-12-20 03:12:20 +0000247
Guido van Rossume87ed5f1998-04-23 13:33:21 +0000248 def writelines(self, listoflines):
249 map(self.write, listoflines)
250
Guido van Rossum75fce301997-07-17 14:51:37 +0000251 def flush(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000252 pass
Guido van Rossum75fce301997-07-17 14:51:37 +0000253
Guido van Rossum152494a1996-12-20 03:12:20 +0000254 def close(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000255 leftover = self.fp.read()
256 if leftover:
257 raise test_support.TestFailed, 'Unread: '+`leftover`
258 self.fp.close()
Guido van Rossum152494a1996-12-20 03:12:20 +0000259
260 def isatty(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000261 return 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000262
263if __name__ == '__main__':
Guido van Rossume8387011997-08-14 19:40:34 +0000264 sys.exit(main())