test_support.py revision ef8b654bbea15dc55767a7095e01dff7a3ca86cb
1"""Supporting definitions for the Python regression test."""
2
3import sys
4
5
6class Error(Exception):
7    """Base class for regression test exceptions."""
8
9class TestFailed(Error):
10    """Test failed."""
11
12class TestSkipped(Error):
13    """Test skipped.
14
15    This can be raised to indicate that a test was deliberatly
16    skipped, but not because a feature wasn't available.  For
17    example, if some resource can't be used, such as the network
18    appears to be unavailable, this should be raised instead of
19    TestFailed.
20    """
21
22verbose = 1                             # Flag set to 0 by regrtest.py
23use_large_resources = 1 # Flag set to 0 by regrtest.py
24
25def unload(name):
26    try:
27        del sys.modules[name]
28    except KeyError:
29        pass
30
31def forget(modname):
32    unload(modname)
33    import os
34    for dirname in sys.path:
35        try:
36            os.unlink(os.path.join(dirname, modname + '.pyc'))
37        except os.error:
38            pass
39
40FUZZ = 1e-6
41
42def fcmp(x, y): # fuzzy comparison function
43    if type(x) == type(0.0) or type(y) == type(0.0):
44        try:
45            x, y = coerce(x, y)
46            fuzz = (abs(x) + abs(y)) * FUZZ
47            if abs(x-y) <= fuzz:
48                return 0
49        except:
50            pass
51    elif type(x) == type(y) and type(x) in (type(()), type([])):
52        for i in range(min(len(x), len(y))):
53            outcome = fcmp(x[i], y[i])
54            if outcome != 0:
55                return outcome
56        return cmp(len(x), len(y))
57    return cmp(x, y)
58
59import os
60# Filename used for testing
61if os.name == 'java':
62    # Jython disallows @ in module names
63    TESTFN = '$test'
64elif os.name != 'riscos':
65    TESTFN = '@test'
66    # Unicode name only used if TEST_FN_ENCODING exists for the platform.
67    TESTFN_UNICODE=u"@test-\xe0\xf2" # 2 latin characters.
68    if os.name=="nt":
69        TESTFN_ENCODING="mbcs"
70else:
71    TESTFN = 'test'
72del os
73
74from os import unlink
75
76def findfile(file, here=__file__):
77    import os
78    if os.path.isabs(file):
79        return file
80    path = sys.path
81    path = [os.path.dirname(here)] + path
82    for dn in path:
83        fn = os.path.join(dn, file)
84        if os.path.exists(fn): return fn
85    return file
86
87def verify(condition, reason='test failed'):
88    """Verify that condition is true. If not, raise TestFailed.
89
90       The optional argument reason can be given to provide
91       a better error text.
92    """
93
94    if not condition:
95        raise TestFailed(reason)
96
97def sortdict(dict):
98    "Like repr(dict), but in sorted order."
99    items = dict.items()
100    items.sort()
101    reprpairs = ["%r: %r" % pair for pair in items]
102    withcommas = ", ".join(reprpairs)
103    return "{%s}" % withcommas
104
105def check_syntax(statement):
106    try:
107        compile(statement, '<string>', 'exec')
108    except SyntaxError:
109        pass
110    else:
111        print 'Missing SyntaxError: "%s"' % statement
112
113
114
115#=======================================================================
116# Preliminary PyUNIT integration.
117
118import unittest
119
120
121class BasicTestRunner:
122    def run(self, test):
123        result = unittest.TestResult()
124        test(result)
125        return result
126
127
128def run_unittest(testclass):
129    """Run tests from a unittest.TestCase-derived class."""
130    if verbose:
131        runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
132    else:
133        runner = BasicTestRunner()
134
135    suite = unittest.makeSuite(testclass)
136    result = runner.run(suite)
137    if not result.wasSuccessful():
138        raise TestFailed("errors occurred in %s.%s"
139                         % (testclass.__module__, testclass.__name__))
140