/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/TestUtil.py

  • Committer: John Ferlito
  • Date: 2009-09-02 04:31:45 UTC
  • mto: (4665.7.1 serve-init)
  • mto: This revision was merged to the branch mainline in revision 4913.
  • Revision ID: johnf@inodes.org-20090902043145-gxdsfw03ilcwbyn5
Add a debian init script for bzr --serve

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
16
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
#
18
18
 
 
19
import sys
19
20
import logging
20
21
import unittest
21
 
import weakref
22
 
 
23
 
from .. import pyutils
24
22
 
25
23
# Mark this python module as being part of the implementation
26
24
# of unittest: this gives us better tracebacks where the last
29
27
 
30
28
 
31
29
class LogCollector(logging.Handler):
32
 
 
33
30
    def __init__(self):
34
31
        logging.Handler.__init__(self)
35
 
        self.records = []
36
 
 
 
32
        self.records=[]
37
33
    def emit(self, record):
38
34
        self.records.append(record.getMessage())
39
35
 
41
37
def makeCollectingLogger():
42
38
    """I make a logger instance that collects its logs for programmatic analysis
43
39
    -> (logger, collector)"""
44
 
    logger = logging.Logger("collector")
45
 
    handler = LogCollector()
 
40
    logger=logging.Logger("collector")
 
41
    handler=LogCollector()
46
42
    handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
47
43
    logger.addHandler(handler)
48
44
    return logger, handler
51
47
def visitTests(suite, visitor):
52
48
    """A foreign method for visiting the tests in a test suite."""
53
49
    for test in suite._tests:
54
 
        # Abusing types to avoid monkey patching unittest.TestCase.
 
50
        #Abusing types to avoid monkey patching unittest.TestCase.
55
51
        # Maybe that would be better?
56
52
        try:
57
53
            test.visit(visitor)
62
58
                visitor.visitSuite(test)
63
59
                visitTests(test, visitor)
64
60
            else:
65
 
                print("unvisitable non-unittest.TestCase element %r (%r)" % (
66
 
                    test, test.__class__))
67
 
 
68
 
 
69
 
class FailedCollectionCase(unittest.TestCase):
70
 
    """Pseudo-test to run and report failure if given case was uncollected"""
71
 
 
72
 
    def __init__(self, case):
73
 
        super(FailedCollectionCase, self).__init__("fail_uncollected")
74
 
        # GZ 2011-09-16: Maybe catch errors from id() method as cases may be
75
 
        #                in a bit of a funny state by now.
76
 
        self._problem_case_id = case.id()
77
 
 
78
 
    def id(self):
79
 
        if self._problem_case_id[-1:] == ")":
80
 
            return self._problem_case_id[:-1] + ",uncollected)"
81
 
        return self._problem_case_id + "(uncollected)"
82
 
 
83
 
    def fail_uncollected(self):
84
 
        self.fail("Uncollected test case: " + self._problem_case_id)
 
61
                print "unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__)
85
62
 
86
63
 
87
64
class TestSuite(unittest.TestSuite):
95
72
        visitor.visitSuite(self)
96
73
        visitTests(self, visitor)
97
74
 
98
 
    def run(self, result):
99
 
        """Run the tests in the suite, discarding references after running."""
100
 
        tests = list(self)
101
 
        tests.reverse()
102
 
        self._tests = []
103
 
        stored_count = 0
104
 
        count_stored_tests = getattr(result, "_count_stored_tests", int)
105
 
        from breezy.tests import selftest_debug_flags
106
 
        notify = "uncollected_cases" in selftest_debug_flags
107
 
        while tests:
108
 
            if result.shouldStop:
109
 
                self._tests = reversed(tests)
110
 
                break
111
 
            case = _run_and_collect_case(tests.pop(), result)()
112
 
            new_stored_count = count_stored_tests()
113
 
            if case is not None and isinstance(case, unittest.TestCase):
114
 
                if stored_count == new_stored_count and notify:
115
 
                    # Testcase didn't fail, but somehow is still alive
116
 
                    FailedCollectionCase(case).run(result)
117
 
                    # Adding a new failure so need to reupdate the count
118
 
                    new_stored_count = count_stored_tests()
119
 
                # GZ 2011-09-16: Previously zombied the case at this point by
120
 
                #                clearing the dict as fallback, skip for now.
121
 
            stored_count = new_stored_count
122
 
        return result
123
 
 
124
 
 
125
 
def _run_and_collect_case(case, res):
126
 
    """Run test case against result and use weakref to drop the refcount"""
127
 
    case.run(res)
128
 
    return weakref.ref(case)
129
 
 
130
75
 
131
76
class TestLoader(unittest.TestLoader):
132
77
    """Custom TestLoader to extend the stock python one."""
149
94
 
150
95
    def loadTestsFromModuleName(self, name):
151
96
        result = self.suiteClass()
152
 
        module = pyutils.get_named_object(name)
 
97
        module = _load_module_by_name(name)
153
98
 
154
99
        result.addTests(self.loadTestsFromModule(module))
155
100
        return result
156
101
 
 
102
    def loadTestsFromModule(self, module):
 
103
        """Load tests from a module object.
 
104
 
 
105
        This extension of the python test loader looks for an attribute
 
106
        load_tests in the module object, and if not found falls back to the
 
107
        regular python loadTestsFromModule.
 
108
 
 
109
        If a load_tests attribute is found, it is called and the result is
 
110
        returned.
 
111
 
 
112
        load_tests should be defined like so:
 
113
        >>> def load_tests(standard_tests, module, loader):
 
114
        >>>    pass
 
115
 
 
116
        standard_tests is the tests found by the stock TestLoader in the
 
117
        module, module and loader are the module and loader instances.
 
118
 
 
119
        For instance, to run every test twice, you might do:
 
120
        >>> def load_tests(standard_tests, module, loader):
 
121
        >>>     result = loader.suiteClass()
 
122
        >>>     for test in iter_suite_tests(standard_tests):
 
123
        >>>         result.addTests([test, test])
 
124
        >>>     return result
 
125
        """
 
126
        basic_tests = super(TestLoader, self).loadTestsFromModule(module)
 
127
        load_tests = getattr(module, "load_tests", None)
 
128
        if load_tests is not None:
 
129
            return load_tests(basic_tests, module, self)
 
130
        else:
 
131
            return basic_tests
 
132
 
157
133
    def getTestCaseNames(self, test_case_class):
158
134
        test_fn_names = self.test_func_names.get(test_case_class, None)
159
135
        if test_fn_names is not None:
185
161
            return self.suiteClass()
186
162
 
187
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
 
188
175
class TestVisitor(object):
189
176
    """A visitor for Tests"""
190
 
 
191
177
    def visitSuite(self, aTestSuite):
192
178
        pass
193
 
 
194
179
    def visitCase(self, aTestCase):
195
180
        pass