~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/TestUtil.py

NEWS section template into a separate file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006 Canonical Ltd
2
2
#       Author: Robert Collins <robert.collins@canonical.com>
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
19
19
import sys
20
20
import logging
21
21
import unittest
22
 
import weakref
23
 
 
24
 
from bzrlib import pyutils
25
22
 
26
23
# Mark this python module as being part of the implementation
27
24
# of unittest: this gives us better tracebacks where the last
30
27
 
31
28
 
32
29
class LogCollector(logging.Handler):
33
 
 
34
30
    def __init__(self):
35
31
        logging.Handler.__init__(self)
36
32
        self.records=[]
37
 
 
38
33
    def emit(self, record):
39
34
        self.records.append(record.getMessage())
40
35
 
63
58
                visitor.visitSuite(test)
64
59
                visitTests(test, visitor)
65
60
            else:
66
 
                print "unvisitable non-unittest.TestCase element %r (%r)" % (
67
 
                    test, test.__class__)
68
 
 
69
 
 
70
 
class FailedCollectionCase(unittest.TestCase):
71
 
    """Pseudo-test to run and report failure if given case was uncollected"""
72
 
 
73
 
    def __init__(self, case):
74
 
        super(FailedCollectionCase, self).__init__("fail_uncollected")
75
 
        # GZ 2011-09-16: Maybe catch errors from id() method as cases may be
76
 
        #                in a bit of a funny state by now.
77
 
        self._problem_case_id = case.id()
78
 
 
79
 
    def id(self):
80
 
        if self._problem_case_id[-1:] == ")":
81
 
            return self._problem_case_id[:-1] + ",uncollected)"
82
 
        return self._problem_case_id + "(uncollected)"
83
 
 
84
 
    def fail_uncollected(self):
85
 
        self.fail("Uncollected test case: " + self._problem_case_id)
 
61
                print "unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__)
86
62
 
87
63
 
88
64
class TestSuite(unittest.TestSuite):
96
72
        visitor.visitSuite(self)
97
73
        visitTests(self, visitor)
98
74
 
99
 
    def run(self, result):
100
 
        """Run the tests in the suite, discarding references after running."""
101
 
        tests = list(self)
102
 
        tests.reverse()
103
 
        self._tests = []
104
 
        stored_count = 0
105
 
        count_stored_tests = getattr(result, "_count_stored_tests", int)
106
 
        from bzrlib.tests import selftest_debug_flags
107
 
        notify = "uncollected_cases" in selftest_debug_flags
108
 
        while tests:
109
 
            if result.shouldStop:
110
 
                self._tests = reversed(tests)
111
 
                break
112
 
            case = _run_and_collect_case(tests.pop(), result)()
113
 
            new_stored_count = count_stored_tests()
114
 
            if case is not None and isinstance(case, unittest.TestCase):
115
 
                if stored_count == new_stored_count and notify:
116
 
                    # Testcase didn't fail, but somehow is still alive
117
 
                    FailedCollectionCase(case).run(result)
118
 
                    # Adding a new failure so need to reupdate the count
119
 
                    new_stored_count = count_stored_tests()
120
 
                # GZ 2011-09-16: Previously zombied the case at this point by
121
 
                #                clearing the dict as fallback, skip for now.
122
 
            stored_count = new_stored_count
123
 
        return result
124
 
 
125
 
 
126
 
def _run_and_collect_case(case, res):
127
 
    """Run test case against result and use weakref to drop the refcount"""
128
 
    case.run(res)
129
 
    return weakref.ref(case)
130
 
 
131
75
 
132
76
class TestLoader(unittest.TestLoader):
133
77
    """Custom TestLoader to extend the stock python one."""
150
94
 
151
95
    def loadTestsFromModuleName(self, name):
152
96
        result = self.suiteClass()
153
 
        module = pyutils.get_named_object(name)
 
97
        module = _load_module_by_name(name)
154
98
 
155
99
        result.addTests(self.loadTestsFromModule(module))
156
100
        return result
179
123
        >>>         result.addTests([test, test])
180
124
        >>>     return result
181
125
        """
182
 
        if sys.version_info < (2, 7):
183
 
            basic_tests = super(TestLoader, self).loadTestsFromModule(module)
184
 
        else:
185
 
            # GZ 2010-07-19: Python 2.7 unittest also uses load_tests but with
186
 
            #                a different and incompatible signature
187
 
            basic_tests = super(TestLoader, self).loadTestsFromModule(module,
188
 
                use_load_tests=False)
 
126
        basic_tests = super(TestLoader, self).loadTestsFromModule(module)
189
127
        load_tests = getattr(module, "load_tests", None)
190
128
        if load_tests is not None:
191
129
            return load_tests(basic_tests, module, self)
223
161
            return self.suiteClass()
224
162
 
225
163
 
 
164
def _load_module_by_name(mod_name):
 
165
    parts = mod_name.split('.')
 
166
    module = __import__(mod_name)
 
167
    del parts[0]
 
168
    # for historical reasons python returns the top-level module even though
 
169
    # it loads the submodule; we need to walk down to get the one we want.
 
170
    while parts:
 
171
        module = getattr(module, parts.pop(0))
 
172
    return module
 
173
 
 
174
 
226
175
class TestVisitor(object):
227
176
    """A visitor for Tests"""
228
 
 
229
177
    def visitSuite(self, aTestSuite):
230
178
        pass
231
 
 
232
179
    def visitCase(self, aTestCase):
233
180
        pass