bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 1185.1.29
by Robert Collins merge merge tweaks from aaron, which includes latest .dev | 1 | # Copyright (c) 2004 Canonical Limited
 | 
| 2 | #       Author: Robert Collins <robert.collins@canonical.com>
 | |
| 3 | #
 | |
| 4 | # This program is free software; you can redistribute it and/or modify
 | |
| 5 | # it under the terms of the GNU General Public License as published by
 | |
| 6 | # the Free Software Foundation; either version 2 of the License, or
 | |
| 7 | # (at your option) any later version.
 | |
| 8 | #
 | |
| 9 | # This program is distributed in the hope that it will be useful,
 | |
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| 12 | # GNU General Public License for more details.
 | |
| 13 | #
 | |
| 14 | # You should have received a copy of the GNU General Public License
 | |
| 15 | # along with this program; if not, write to the Free Software
 | |
| 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | |
| 17 | #
 | |
| 18 | ||
| 19 | import sys | |
| 20 | import logging | |
| 21 | import unittest | |
| 22 | ||
| 23 | ||
| 24 | class LogCollector(logging.Handler): | |
| 25 | def __init__(self): | |
| 26 | logging.Handler.__init__(self) | |
| 27 | self.records=[] | |
| 28 | def emit(self, record): | |
| 29 | self.records.append(record.getMessage()) | |
| 30 | ||
| 31 | ||
| 32 | def makeCollectingLogger(): | |
| 33 | """I make a logger instance that collects its logs for programmatic analysis | |
| 34 |     -> (logger, collector)"""
 | |
| 35 | logger=logging.Logger("collector") | |
| 36 | handler=LogCollector() | |
| 37 | handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) | |
| 38 | logger.addHandler(handler) | |
| 39 | return logger, handler | |
| 40 | ||
| 41 | ||
| 42 | def visitTests(suite, visitor): | |
| 43 | """A foreign method for visiting the tests in a test suite.""" | |
| 44 | for test in suite._tests: | |
| 45 |         #Abusing types to avoid monkey patching unittest.TestCase. 
 | |
| 46 |         # Maybe that would be better?
 | |
| 47 | try: | |
| 48 | test.visit(visitor) | |
| 49 | except AttributeError: | |
| 50 | if isinstance(test, unittest.TestCase): | |
| 51 | visitor.visitCase(test) | |
| 52 | elif isinstance(test, unittest.TestSuite): | |
| 53 | visitor.visitSuite(test) | |
| 54 | visitTests(test, visitor) | |
| 55 | else: | |
| 56 | print "unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__) | |
| 57 | ||
| 58 | ||
| 59 | class TestSuite(unittest.TestSuite): | |
| 60 | """I am an extended TestSuite with a visitor interface. | |
| 61 |     This is primarily to allow filtering of tests - and suites or
 | |
| 62 |     more in the future. An iterator of just tests wouldn't scale..."""
 | |
| 63 | ||
| 64 | def visit(self, visitor): | |
| 65 | """visit the composite. Visiting is depth-first. | |
| 66 |         current callbacks are visitSuite and visitCase."""
 | |
| 67 | visitor.visitSuite(self) | |
| 68 | visitTests(self, visitor) | |
| 69 | ||
| 70 | ||
| 71 | class TestLoader(unittest.TestLoader): | |
| 1707.2.2
by Robert Collins Start on bench_add, an add benchtest. | 72 | """Custom TestLoader to address some quirks in the stock python one.""" | 
| 1185.1.29
by Robert Collins merge merge tweaks from aaron, which includes latest .dev | 73 | suiteClass = TestSuite | 
| 74 | ||
| 1707.2.2
by Robert Collins Start on bench_add, an add benchtest. | 75 | def loadTestsFromModuleNames(self, names): | 
| 76 | """use a custom means to load tests from modules. | |
| 77 | ||
| 78 |         There is an undesirable glitch in the python TestLoader where a 
 | |
| 79 |         import error is ignore. We think this can be solved by ensuring the 
 | |
| 80 |         requested name is resolvable, if its not raising the original error.
 | |
| 81 |         """
 | |
| 82 | result = self.suiteClass() | |
| 83 | for name in names: | |
| 84 | _load_module_by_name(name) | |
| 85 | result.addTests(self.loadTestsFromName(name)) | |
| 86 | return result | |
| 87 | ||
| 88 | ||
| 89 | def _load_module_by_name(mod_name): | |
| 90 | parts = mod_name.split('.') | |
| 91 | module = __import__(mod_name) | |
| 92 | del parts[0] | |
| 93 |     # for historical reasons python returns the top-level module even though
 | |
| 94 |     # it loads the submodule; we need to walk down to get the one we want.
 | |
| 95 | while parts: | |
| 96 | module = getattr(module, parts.pop(0)) | |
| 97 | return module | |
| 98 | ||
| 99 | ||
| 1185.1.29
by Robert Collins merge merge tweaks from aaron, which includes latest .dev | 100 | class TestVisitor(object): | 
| 101 | """A visitor for Tests""" | |
| 102 | def visitSuite(self, aTestSuite): | |
| 103 |         pass
 | |
| 104 | def visitCase(self, aTestCase): | |
| 105 |         pass
 |