5 This will find all modules whose name is "test_*" in the test
6 directory, and run them. Various command line options provide
11 -v: verbose -- run tests in verbose mode with output to stdout
12 -q: quiet -- don't print anything except if a test fails
13 -g: generate -- write the output file for a test instead of comparing it
14 -x: exclude -- arguments are tests to *exclude*
15 -s: single -- run only a single test (see below)
16 -r: random -- randomize test execution order
17 -l: findleaks -- if GC is available detect and print cyclic garbage
18 --have-resources -- run tests that require large resources (time/space)
20 If non-option arguments are present, they are names for tests to run,
21 unless -x is given, in which case they are names for tests not to run.
22 If no test names are given, all tests are run.
24 -v is incompatible with -g and does not compare test output files.
26 -s means to run only a single test and exit. This is useful when Purifying
27 the Python interpreter. The file /tmp/pynexttest is read to find the next
28 test to run. If this file is missing, the first test_*.py file in testdir or
29 on the command line is used. (actually tempfile.gettempdir() is used instead
43 def main(tests
=None, testdir
=None, verbose
=0, quiet
=0, generate
=0,
44 exclude
=0, single
=0, randomize
=0, findleaks
=0,
45 use_large_resources
=0):
46 """Execute a test suite.
48 This also parses command-line options and modifies its behavior
51 tests -- a list of strings containing test names (optional)
52 testdir -- the directory in which to look for tests (optional)
54 Users other than the Python test suite will certainly want to
55 specify testdir; if it's omitted, the directory containing the
56 Python test suite is searched for.
58 If the tests argument is omitted, the tests listed on the
59 command-line will be used. If that's empty, too, then all *.py
60 files beginning with test_ will be used.
62 The other seven default arguments (verbose, quiet, generate, exclude,
63 single, randomize, and findleaks) allow programmers calling main()
64 directly to set the values that would normally be set by flags on the
70 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'vgqxsrl', ['have-resources'])
71 except getopt
.error
, msg
:
76 if o
== '-v': verbose
= verbose
+1
77 if o
== '-q': quiet
= 1; verbose
= 0
78 if o
== '-g': generate
= 1
79 if o
== '-x': exclude
= 1
80 if o
== '-s': single
= 1
81 if o
== '-r': randomize
= 1
82 if o
== '-l': findleaks
= 1
83 if o
== '--have-resources': use_large_resources
= 1
84 if generate
and verbose
:
85 print "-g and -v don't go together!"
95 print 'cycle garbage collection not available'
98 gc
.set_debug(gc
.DEBUG_SAVEALL
)
102 from tempfile
import gettempdir
103 filename
= os
.path
.join(gettempdir(), 'pynexttest')
105 fp
= open(filename
, 'r')
106 next
= string
.strip(fp
.read())
111 for i
in range(len(args
)):
112 # Strip trailing ".py" from arguments
113 if args
[i
][-3:] == '.py':
114 args
[i
] = args
[i
][:-3]
115 stdtests
= STDTESTS
[:]
116 nottests
= NOTTESTS
[:]
123 tests
= tests
or args
or findtests(testdir
, stdtests
, nottests
)
127 random
.shuffle(tests
)
128 test_support
.verbose
= verbose
# Tell tests to be moderately quiet
129 test_support
.use_large_resources
= use_large_resources
130 save_modules
= sys
.modules
.keys()
134 ok
= runtest(test
, generate
, verbose
, quiet
, testdir
)
144 print "garbage:", repr(gc
.garbage
)
145 found_garbage
.extend(gc
.garbage
)
147 # Unload the newly imported modules (best effort finalization)
148 for module
in sys
.modules
.keys():
149 if module
not in save_modules
and module
.startswith("test."):
150 test_support
.unload(module
)
151 if good
and not quiet
:
152 if not bad
and not skipped
and len(good
) > 1:
154 print count(len(good
), "test"), "OK."
156 print count(len(bad
), "test"), "failed:",
157 print string
.join(bad
)
158 if skipped
and not quiet
:
159 print count(len(skipped
), "test"), "skipped:",
160 print string
.join(skipped
)
163 alltests
= findtests(testdir
, stdtests
, nottests
)
164 for i
in range(len(alltests
)):
165 if tests
[0] == alltests
[i
]:
166 if i
== len(alltests
) - 1:
169 fp
= open(filename
, 'w')
170 fp
.write(alltests
[i
+1] + '\n')
193 def findtests(testdir
=None, stdtests
=STDTESTS
, nottests
=NOTTESTS
):
194 """Return a list of all applicable test modules."""
195 if not testdir
: testdir
= findtestdir()
196 names
= os
.listdir(testdir
)
199 if name
[:5] == "test_" and name
[-3:] == ".py":
201 if modname
not in stdtests
and modname
not in nottests
:
202 tests
.append(modname
)
204 return stdtests
+ tests
206 def runtest(test
, generate
, verbose
, quiet
, testdir
= None):
207 """Run a single test.
208 test -- the name of the test
209 generate -- if true, generate output, instead of running the test
210 and comparing it to a previously created output file
211 verbose -- if true, print more messages
212 quiet -- if true, don't print 'skipped' messages (probably redundant)
213 testdir -- test directory
215 test_support
.unload(test
)
216 if not testdir
: testdir
= findtestdir()
217 outputdir
= os
.path
.join(testdir
, "output")
218 outputfile
= os
.path
.join(outputdir
, test
)
221 cfp
= open(outputfile
, "w")
225 cfp
= Compare(outputfile
)
228 print "Warning: can't open", outputfile
230 save_stdout
= sys
.stdout
234 print test
# Output file starts with test name
235 __import__(test
, globals(), locals(), [])
236 if cfp
and not (generate
or verbose
):
239 sys
.stdout
= save_stdout
240 except (ImportError, test_support
.TestSkipped
), msg
:
243 print "skipped -- ", msg
245 except KeyboardInterrupt:
247 except test_support
.TestFailed
, msg
:
248 print "test", test
, "failed --", msg
251 type, value
= sys
.exc_info()[:2]
252 print "test", test
, "crashed --", str(type) + ":", value
254 traceback
.print_exc(file=sys
.stdout
)
260 if __name__
== '__main__':
264 testdir
= os
.path
.dirname(file) or os
.curdir
269 return "%d %s" % (n
, word
)
271 return "%d %ss" % (n
, word
)
275 def __init__(self
, filename
):
276 self
.fp
= open(filename
, 'r')
278 def write(self
, data
):
279 expected
= self
.fp
.read(len(data
))
281 raise test_support
.TestFailed
, \
282 'Writing: '+`data`
+', expected: '+`expected`
284 def writelines(self
, listoflines
):
285 map(self
.write
, listoflines
)
291 leftover
= self
.fp
.read()
293 raise test_support
.TestFailed
, 'Unread: '+`leftover`
299 if __name__
== '__main__':