Viewing file: testcase.py (5.18 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
import inspect, types, warnings
from twisted.trial import runner, unittest
from nevow import athena, loaders, tags, page
class TestCase(athena.LiveFragment, unittest.TestCase): """ Server-side component of a B{N}evow B{I}nteractive B{T}est.
TestCases are L{athena.LiveFragment}s which correspond to one or more test methods which will be invoked on the client. They are responsible for specifying a JavaScript widget class which defines the client portion of this set of tests, specifying a document which will be rendered for that JavaScript widget, and defining any methods which the client may need to invoke during the test. """ docFactory = loaders.stan(tags.div(render=tags.directive('testWidget')))
def render_liveTest(self, ctx, data): warnings.warn( "liveTest renderer is deprecated, use the default " "docFactory and override getWidgetTag, getTestContainer, " "and/or getWidgetDocument instead", category=DeprecationWarning) return self.render_liveFragment(ctx, data)
def render_testWidget(self, ctx, data): container = self.getTestContainer() widget = self.getWidgetTag()(render=tags.directive('liveFragment')) container.fillSlots('widget', widget[self.getWidgetDocument()]) return ctx.tag[container]
def getWidgetTag(self): """ Return a Nevow tag object which will be used as the top-level widget node for this test case.
Subclasses may want to override this. """ return tags.div
def getTestContainer(self): """ Return a Nevow DOM object (generally a tag) with a C{widget} slot in it. This will be used as the top-level DOM for this test case, and the actual widget will be used to fill the C{widget} slot.
Subclasses may want to override this. """ return tags.invisible[tags.slot('widget')]
def getWidgetDocument(self): """ Retrieve a Nevow DOM object (generally a tag) which will be placed inside this TestCase's widget node.
Subclasses may want to override this. """ return u''
def head(self): """ Return objects that should be rendered inside the <head> tag of the document for the test suite that this test case belongs to. Typically instances of tags from L{nevow.tags}.
Subclasses may want to override this """
def __repr__(self): return object.__repr__(self)
class TestError(athena.LiveElement): """ An element rendering an error that occurred during test collection. """ docFactory = loaders.stan(tags.div(render=tags.directive('error')))
def __init__(self, holder): holder.run(self)
def addError(self, holder, error): self._error = error
def head(self): """ We have nothing to render in <head>. """
def error(self, req, tag): return tag(_class='test-suite')[ tags.pre[self._error.getTraceback()]] page.renderer(error)
class TestSuite(object): """ A collection of test cases. """
holderType = runner.ErrorHolder
def __init__(self, name="Live Tests"): self.tests = [] self.name = name
def addTest(self, test): self.tests.append(test)
def gatherInstances(self): l = [] for test in self.tests: if isinstance(test, TestSuite): l.extend(test.gatherInstances()) elif isinstance(test, self.holderType): l.append(TestError(test)) else: test.name = '%s.%s' % (self.name, test.__name__) l.append(test()) return l
class TestLoader(runner.TestLoader): """ An object which discovers test cases and collects them into a suite. """ modulePrefix = 'livetest_'
def __init__(self): runner.TestLoader.__init__(self) self.suiteFactory = TestSuite
def loadByName(self, name, recurse=False): thing = self.findByName(name) return self.loadAnything(thing, recurse)
def loadMethod(self, method): raise NotImplementedError, 'livetests must be classes'
def loadClass(self, klass): if not (isinstance(klass, type) or isinstance(klass, types.ClassType)): raise TypeError("%r is not a class" % (klass,)) if not self.isTestCase(klass): raise ValueError("%r is not a test case" % (klass,)) return klass
def loadModule(self, module): if not isinstance(module, types.ModuleType): raise TypeError("%r is not a module" % (module,)) suite = self.suiteFactory(module.__name__) for testClass in self._findTestClasses(module): suite.addTest(self.loadClass(testClass)) return suite
def isTestCase(self, obj): return isinstance(obj, (type, types.ClassType)) and issubclass(obj, TestCase) and obj is not TestCase
def _findTestClasses(self, module): classes = [] for name, val in inspect.getmembers(module): if self.isTestCase(val): classes.append(val) return self.sort(classes)
|