Bump version number to 2.4.2 to pick up the latest minor bug fixes.
[python/dscho.git] / Lib / test / test_support.py
blob948c64561f890a907c0026b645ecfc2760ef77ab
1 """Supporting definitions for the Python regression test."""
3 if __name__ != 'test.test_support':
4 raise ImportError, 'test_support must be imported from the test package'
6 import sys
8 class Error(Exception):
9 """Base class for regression test exceptions."""
11 class TestFailed(Error):
12 """Test failed."""
14 class TestSkipped(Error):
15 """Test skipped.
17 This can be raised to indicate that a test was deliberatly
18 skipped, but not because a feature wasn't available. For
19 example, if some resource can't be used, such as the network
20 appears to be unavailable, this should be raised instead of
21 TestFailed.
22 """
24 verbose = 1 # Flag set to 0 by regrtest.py
25 use_resources = None # Flag set to [] by regrtest.py
27 # _original_stdout is meant to hold stdout at the time regrtest began.
28 # This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
29 # The point is to have some flavor of stdout the user can actually see.
30 _original_stdout = None
31 def record_original_stdout(stdout):
32 global _original_stdout
33 _original_stdout = stdout
35 def get_original_stdout():
36 return _original_stdout or sys.stdout
38 def unload(name):
39 try:
40 del sys.modules[name]
41 except KeyError:
42 pass
44 def forget(modname):
45 unload(modname)
46 import os
47 for dirname in sys.path:
48 try:
49 os.unlink(os.path.join(dirname, modname + '.pyc'))
50 except os.error:
51 pass
53 def requires(resource, msg=None):
54 if use_resources is not None and resource not in use_resources:
55 if msg is None:
56 msg = "Use of the `%s' resource not enabled" % resource
57 raise TestSkipped(msg)
59 FUZZ = 1e-6
61 def fcmp(x, y): # fuzzy comparison function
62 if type(x) == type(0.0) or type(y) == type(0.0):
63 try:
64 x, y = coerce(x, y)
65 fuzz = (abs(x) + abs(y)) * FUZZ
66 if abs(x-y) <= fuzz:
67 return 0
68 except:
69 pass
70 elif type(x) == type(y) and type(x) in (type(()), type([])):
71 for i in range(min(len(x), len(y))):
72 outcome = fcmp(x[i], y[i])
73 if outcome != 0:
74 return outcome
75 return cmp(len(x), len(y))
76 return cmp(x, y)
78 try:
79 unicode
80 have_unicode = 1
81 except NameError:
82 have_unicode = 0
84 import os
85 # Filename used for testing
86 if os.name == 'java':
87 # Jython disallows @ in module names
88 TESTFN = '$test'
89 elif os.name != 'riscos':
90 TESTFN = '@test'
91 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
92 if have_unicode:
93 TESTFN_UNICODE=unicode("@test-\xe0\xf2", "latin-1") # 2 latin characters.
94 if os.name=="nt":
95 TESTFN_ENCODING="mbcs"
96 else:
97 TESTFN = 'test'
98 del os
100 from os import unlink
102 def findfile(file, here=__file__):
103 import os
104 if os.path.isabs(file):
105 return file
106 path = sys.path
107 path = [os.path.dirname(here)] + path
108 for dn in path:
109 fn = os.path.join(dn, file)
110 if os.path.exists(fn): return fn
111 return file
113 def verify(condition, reason='test failed'):
114 """Verify that condition is true. If not, raise TestFailed.
116 The optional argument reason can be given to provide
117 a better error text.
120 if not condition:
121 raise TestFailed(reason)
123 def vereq(a, b):
124 """Raise TestFailed if a == b is false.
126 This is better than verify(a == b) because, in case of failure, the
127 error message incorporates repr(a) and repr(b) so you can see the
128 inputs.
130 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
131 former is tested.
134 if not (a == b):
135 raise TestFailed, "%r == %r" % (a, b)
137 def sortdict(dict):
138 "Like repr(dict), but in sorted order."
139 items = dict.items()
140 items.sort()
141 reprpairs = ["%r: %r" % pair for pair in items]
142 withcommas = ", ".join(reprpairs)
143 return "{%s}" % withcommas
145 def check_syntax(statement):
146 try:
147 compile(statement, '<string>', 'exec')
148 except SyntaxError:
149 pass
150 else:
151 print 'Missing SyntaxError: "%s"' % statement
155 #=======================================================================
156 # Preliminary PyUNIT integration.
158 import unittest
161 class BasicTestRunner:
162 def run(self, test):
163 result = unittest.TestResult()
164 test(result)
165 return result
168 def run_suite(suite, testclass=None):
169 """Run tests from a unittest.TestSuite-derived class."""
170 if verbose:
171 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
172 else:
173 runner = BasicTestRunner()
175 result = runner.run(suite)
176 if not result.wasSuccessful():
177 if len(result.errors) == 1 and not result.failures:
178 err = result.errors[0][1]
179 elif len(result.failures) == 1 and not result.errors:
180 err = result.failures[0][1]
181 else:
182 if testclass is None:
183 msg = "errors occurred; run in verbose mode for details"
184 else:
185 msg = "errors occurred in %s.%s" \
186 % (testclass.__module__, testclass.__name__)
187 raise TestFailed(msg)
188 raise TestFailed(err)
191 def run_unittest(testclass):
192 """Run tests from a unittest.TestCase-derived class."""
193 run_suite(unittest.makeSuite(testclass), testclass)
196 #=======================================================================
197 # doctest driver.
199 def run_doctest(module, verbosity=None):
200 """Run doctest on the given module. Return (#failures, #tests).
202 If optional argument verbosity is not specified (or is None), pass
203 test_support's belief about verbosity on to doctest. Else doctest's
204 usual behavior is used (it searches sys.argv for -v).
207 import doctest
209 if verbosity is None:
210 verbosity = verbose
211 else:
212 verbosity = None
214 # Direct doctest output (normally just errors) to real stdout; doctest
215 # output shouldn't be compared by regrtest.
216 save_stdout = sys.stdout
217 sys.stdout = get_original_stdout()
218 try:
219 f, t = doctest.testmod(module, verbose=verbosity)
220 if f:
221 raise TestFailed("%d of %d doctests failed" % (f, t))
222 return f, t
223 finally:
224 sys.stdout = save_stdout