This commit was manufactured by cvs2svn to create tag 'r221'.
[python/dscho.git] / Lib / test / test_support.py
blob83bde3ee9f91c8caf9de87311f1cd69bf1366cd1
1 """Supporting definitions for the Python regression test."""
3 import sys
5 class Error(Exception):
6 """Base class for regression test exceptions."""
8 class TestFailed(Error):
9 """Test failed."""
11 class TestSkipped(Error):
12 """Test skipped.
14 This can be raised to indicate that a test was deliberatly
15 skipped, but not because a feature wasn't available. For
16 example, if some resource can't be used, such as the network
17 appears to be unavailable, this should be raised instead of
18 TestFailed.
19 """
21 verbose = 1 # Flag set to 0 by regrtest.py
22 use_resources = None # Flag set to [] by regrtest.py
24 # _original_stdout is meant to hold stdout at the time regrtest began.
25 # This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
26 # The point is to have some flavor of stdout the user can actually see.
27 _original_stdout = None
28 def record_original_stdout(stdout):
29 global _original_stdout
30 _original_stdout = stdout
32 def get_original_stdout():
33 return _original_stdout or sys.stdout
35 def unload(name):
36 try:
37 del sys.modules[name]
38 except KeyError:
39 pass
41 def forget(modname):
42 unload(modname)
43 import os
44 for dirname in sys.path:
45 try:
46 os.unlink(os.path.join(dirname, modname + '.pyc'))
47 except os.error:
48 pass
50 def requires(resource, msg=None):
51 if use_resources is not None and resource not in use_resources:
52 if msg is None:
53 msg = "Use of the `%s' resource not enabled" % resource
54 raise TestSkipped(msg)
56 FUZZ = 1e-6
58 def fcmp(x, y): # fuzzy comparison function
59 if type(x) == type(0.0) or type(y) == type(0.0):
60 try:
61 x, y = coerce(x, y)
62 fuzz = (abs(x) + abs(y)) * FUZZ
63 if abs(x-y) <= fuzz:
64 return 0
65 except:
66 pass
67 elif type(x) == type(y) and type(x) in (type(()), type([])):
68 for i in range(min(len(x), len(y))):
69 outcome = fcmp(x[i], y[i])
70 if outcome != 0:
71 return outcome
72 return cmp(len(x), len(y))
73 return cmp(x, y)
75 try:
76 unicode
77 have_unicode = 1
78 except NameError:
79 have_unicode = 0
81 import os
82 # Filename used for testing
83 if os.name == 'java':
84 # Jython disallows @ in module names
85 TESTFN = '$test'
86 elif os.name != 'riscos':
87 TESTFN = '@test'
88 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
89 if have_unicode:
90 TESTFN_UNICODE=unicode("@test-\xe0\xf2", "latin-1") # 2 latin characters.
91 if os.name=="nt":
92 TESTFN_ENCODING="mbcs"
93 else:
94 TESTFN = 'test'
95 del os
97 from os import unlink
99 def findfile(file, here=__file__):
100 import os
101 if os.path.isabs(file):
102 return file
103 path = sys.path
104 path = [os.path.dirname(here)] + path
105 for dn in path:
106 fn = os.path.join(dn, file)
107 if os.path.exists(fn): return fn
108 return file
110 def verify(condition, reason='test failed'):
111 """Verify that condition is true. If not, raise TestFailed.
113 The optional argument reason can be given to provide
114 a better error text.
117 if not condition:
118 raise TestFailed(reason)
120 def vereq(a, b):
121 if not (a == b):
122 raise TestFailed, "%r == %r" % (a, b)
124 def sortdict(dict):
125 "Like repr(dict), but in sorted order."
126 items = dict.items()
127 items.sort()
128 reprpairs = ["%r: %r" % pair for pair in items]
129 withcommas = ", ".join(reprpairs)
130 return "{%s}" % withcommas
132 def check_syntax(statement):
133 try:
134 compile(statement, '<string>', 'exec')
135 except SyntaxError:
136 pass
137 else:
138 print 'Missing SyntaxError: "%s"' % statement
142 #=======================================================================
143 # Preliminary PyUNIT integration.
145 import unittest
148 class BasicTestRunner:
149 def run(self, test):
150 result = unittest.TestResult()
151 test(result)
152 return result
155 def run_suite(suite, testclass=None):
156 """Run tests from a unittest.TestSuite-derived class."""
157 if verbose:
158 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
159 else:
160 runner = BasicTestRunner()
162 result = runner.run(suite)
163 if not result.wasSuccessful():
164 if len(result.errors) == 1 and not result.failures:
165 err = result.errors[0][1]
166 elif len(result.failures) == 1 and not result.errors:
167 err = result.failures[0][1]
168 else:
169 if testclass is None:
170 msg = "errors occurred; run in verbose mode for details"
171 else:
172 msg = "errors occurred in %s.%s" \
173 % (testclass.__module__, testclass.__name__)
174 raise TestFailed(msg)
175 raise TestFailed(err)
178 def run_unittest(testclass):
179 """Run tests from a unittest.TestCase-derived class."""
180 run_suite(unittest.makeSuite(testclass), testclass)
183 #=======================================================================
184 # doctest driver.
186 def run_doctest(module, verbosity=None):
187 """Run doctest on the given module. Return (#failures, #tests).
189 If optional argument verbosity is not specified (or is None), pass
190 test_support's belief about verbosity on to doctest. Else doctest's
191 usual behavior is used (it searches sys.argv for -v).
194 import doctest
196 if verbosity is None:
197 verbosity = verbose
198 else:
199 verbosity = None
201 # Direct doctest output (normally just errors) to real stdout; doctest
202 # output shouldn't be compared by regrtest.
203 save_stdout = sys.stdout
204 sys.stdout = get_original_stdout()
205 try:
206 f, t = doctest.testmod(module, verbose=verbosity)
207 if f:
208 raise TestFailed("%d of %d doctests failed" % (f, t))
209 return f, t
210 finally:
211 sys.stdout = save_stdout