Update version number and release date.
[python/dscho.git] / Lib / test / test_support.py
blobc61e194f57a22d29b72d911df06a79c0af60a017
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 class ResourceDenied(TestSkipped):
25 """Test skipped because it requested a disallowed resource.
27 This is raised when a test calls requires() for a resource that
28 has not be enabled. It is used to distinguish between expected
29 and unexpected skips.
30 """
32 verbose = 1 # Flag set to 0 by regrtest.py
33 use_resources = None # Flag set to [] by regrtest.py
35 # _original_stdout is meant to hold stdout at the time regrtest began.
36 # This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
37 # The point is to have some flavor of stdout the user can actually see.
38 _original_stdout = None
39 def record_original_stdout(stdout):
40 global _original_stdout
41 _original_stdout = stdout
43 def get_original_stdout():
44 return _original_stdout or sys.stdout
46 def unload(name):
47 try:
48 del sys.modules[name]
49 except KeyError:
50 pass
52 def forget(modname):
53 unload(modname)
54 import os
55 for dirname in sys.path:
56 try:
57 os.unlink(os.path.join(dirname, modname + '.pyc'))
58 except os.error:
59 pass
61 def is_resource_enabled(resource):
62 return use_resources is not None and resource in use_resources
64 def requires(resource, msg=None):
65 # see if the caller's module is __main__ - if so, treat as if
66 # the resource was set
67 if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
68 return
69 if not is_resource_enabled(resource):
70 if msg is None:
71 msg = "Use of the `%s' resource not enabled" % resource
72 raise ResourceDenied(msg)
74 FUZZ = 1e-6
76 def fcmp(x, y): # fuzzy comparison function
77 if type(x) == type(0.0) or type(y) == type(0.0):
78 try:
79 x, y = coerce(x, y)
80 fuzz = (abs(x) + abs(y)) * FUZZ
81 if abs(x-y) <= fuzz:
82 return 0
83 except:
84 pass
85 elif type(x) == type(y) and type(x) in (type(()), type([])):
86 for i in range(min(len(x), len(y))):
87 outcome = fcmp(x[i], y[i])
88 if outcome != 0:
89 return outcome
90 return cmp(len(x), len(y))
91 return cmp(x, y)
93 try:
94 unicode
95 have_unicode = 1
96 except NameError:
97 have_unicode = 0
99 is_jython = sys.platform.startswith('java')
101 import os
102 # Filename used for testing
103 if os.name == 'java':
104 # Jython disallows @ in module names
105 TESTFN = '$test'
106 elif os.name != 'riscos':
107 TESTFN = '@test'
108 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
109 if have_unicode:
110 if isinstance('', unicode):
111 # python -U
112 # XXX perhaps unicode() should accept Unicode strings?
113 TESTFN_UNICODE="@test-\xe0\xf2"
114 else:
115 TESTFN_UNICODE=unicode("@test-\xe0\xf2", "latin-1") # 2 latin characters.
116 TESTFN_ENCODING=sys.getfilesystemencoding()
117 else:
118 TESTFN = 'test'
120 # Make sure we can write to TESTFN, try in /tmp if we can't
121 fp = None
122 try:
123 fp = open(TESTFN, 'w+')
124 except IOError:
125 TMP_TESTFN = os.path.join('/tmp', TESTFN)
126 try:
127 fp = open(TMP_TESTFN, 'w+')
128 TESTFN = TMP_TESTFN
129 del TMP_TESTFN
130 except IOError:
131 print ('WARNING: tests will fail, unable to write to: %s or %s' %
132 (TESTFN, TMP_TESTFN))
133 if fp is not None:
134 fp.close()
135 try:
136 os.unlink(TESTFN)
137 except:
138 pass
139 del os, fp
141 from os import unlink
143 def findfile(file, here=__file__):
144 import os
145 if os.path.isabs(file):
146 return file
147 path = sys.path
148 path = [os.path.dirname(here)] + path
149 for dn in path:
150 fn = os.path.join(dn, file)
151 if os.path.exists(fn): return fn
152 return file
154 def verify(condition, reason='test failed'):
155 """Verify that condition is true. If not, raise TestFailed.
157 The optional argument reason can be given to provide
158 a better error text.
161 if not condition:
162 raise TestFailed(reason)
164 def vereq(a, b):
165 """Raise TestFailed if a == b is false.
167 This is better than verify(a == b) because, in case of failure, the
168 error message incorporates repr(a) and repr(b) so you can see the
169 inputs.
171 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
172 former is tested.
175 if not (a == b):
176 raise TestFailed, "%r == %r" % (a, b)
178 def sortdict(dict):
179 "Like repr(dict), but in sorted order."
180 items = dict.items()
181 items.sort()
182 reprpairs = ["%r: %r" % pair for pair in items]
183 withcommas = ", ".join(reprpairs)
184 return "{%s}" % withcommas
186 def check_syntax(statement):
187 try:
188 compile(statement, '<string>', 'exec')
189 except SyntaxError:
190 pass
191 else:
192 print 'Missing SyntaxError: "%s"' % statement
196 #=======================================================================
197 # Preliminary PyUNIT integration.
199 import unittest
202 class BasicTestRunner:
203 def run(self, test):
204 result = unittest.TestResult()
205 test(result)
206 return result
209 def run_suite(suite, testclass=None):
210 """Run tests from a unittest.TestSuite-derived class."""
211 if verbose:
212 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
213 else:
214 runner = BasicTestRunner()
216 result = runner.run(suite)
217 if not result.wasSuccessful():
218 if len(result.errors) == 1 and not result.failures:
219 err = result.errors[0][1]
220 elif len(result.failures) == 1 and not result.errors:
221 err = result.failures[0][1]
222 else:
223 if testclass is None:
224 msg = "errors occurred; run in verbose mode for details"
225 else:
226 msg = "errors occurred in %s.%s" \
227 % (testclass.__module__, testclass.__name__)
228 raise TestFailed(msg)
229 raise TestFailed(err)
232 def run_unittest(testclass):
233 """Run tests from a unittest.TestCase-derived class."""
234 run_suite(unittest.makeSuite(testclass), testclass)
237 #=======================================================================
238 # doctest driver.
240 def run_doctest(module, verbosity=None):
241 """Run doctest on the given module. Return (#failures, #tests).
243 If optional argument verbosity is not specified (or is None), pass
244 test_support's belief about verbosity on to doctest. Else doctest's
245 usual behavior is used (it searches sys.argv for -v).
248 import doctest
250 if verbosity is None:
251 verbosity = verbose
252 else:
253 verbosity = None
255 # Direct doctest output (normally just errors) to real stdout; doctest
256 # output shouldn't be compared by regrtest.
257 save_stdout = sys.stdout
258 sys.stdout = get_original_stdout()
259 try:
260 f, t = doctest.testmod(module, verbose=verbosity)
261 if f:
262 raise TestFailed("%d of %d doctests failed" % (f, t))
263 return f, t
264 finally:
265 sys.stdout = save_stdout