#!/usr/bin/python """$Id: validtest.py 1014 2008-05-21 20:43:22Z joe.walton.gglcd $""" __author__ = "Sam Ruby and Mark Pilgrim " __version__ = "$Revision: 1014 $" __copyright__ = "Copyright (c) 2002 Sam Ruby and Mark Pilgrim" import feedvalidator import unittest, new, os, sys, glob, re from feedvalidator.logging import Message,SelfDoesntMatchLocation,MissingSelf from feedvalidator import compatibility from feedvalidator.formatter.application_test import Formatter class TestCase(unittest.TestCase): def failIfNoMessage(self, theList): filterFunc = compatibility.AA events = filterFunc(theList) output = Formatter(events) for e in events: if not output.format(e): raise self.failureException, 'could not contruct message for %s' % e def failUnlessContainsInstanceOf(self, theClass, params, theList, msg=None): """Fail if there are no instances of theClass in theList with given params""" self.failIfNoMessage(theList) failure=(msg or 'no %s instances in %s' % (theClass.__name__, `theList`)) for item in theList: if issubclass(item.__class__, theClass): if not params: return for k, v in params.items(): if str(item.params[k]) <> v: failure=("%s.%s value was %s, expected %s" % (theClass.__name__, k, item.params[k], v)) break else: return raise self.failureException, failure def failIfContainsInstanceOf(self, theClass, params, theList, msg=None): """Fail if there are instances of theClass in theList with given params""" self.failIfNoMessage(theList) for item in theList: if theClass==Message and isinstance(item,SelfDoesntMatchLocation): continue if theClass==Message and isinstance(item,MissingSelf): continue if issubclass(item.__class__, theClass): if not params: raise self.failureException, \ (msg or 'unexpected %s' % (theClass.__name__)) allmatch = 1 for k, v in params.items(): if item.params[k] != v: allmatch = 0 if allmatch: raise self.failureException, \ "unexpected %s.%s with a value of %s" % \ (theClass.__name__, k, v) desc_re = re.compile("") validome_re = re.compile("", re.S) def getDescription(xmlfile): """Extract description and exception from XML file The deal here is that each test case is an XML file which contains not only a possibly invalid RSS feed but also the description of the test, i.e. the exception that we would expect the RSS validator to raise (or not) when it validates the feed. The expected exception and the human-readable description are placed into an XML comment like this: """ stream = open(xmlfile) xmldoc = stream.read() stream.close() search_results = desc_re.search(xmldoc) if search_results: description, cond, excName, plist = list(search_results.groups()) else: search_results = validome_re.search(xmldoc) if search_results: plist = '' description, cond, excName = list(search_results.groups()) excName = excName.capitalize() if excName=='Valid': cond,excName = '!', 'Message' else: raise RuntimeError, "can't parse %s" % xmlfile if cond == "": method = TestCase.failUnlessContainsInstanceOf else: method = TestCase.failIfContainsInstanceOf params = {} if plist: for entry in plist.split(','): name,value = entry.lstrip().split(':',1) params[name] = value exc = getattr(feedvalidator, excName) description = xmlfile + ": " + description return method, description, params, exc def buildTestCase(xmlfile, xmlBase, description, method, exc, params): """factory to create functions which validate `xmlfile` the returned function asserts that validating `xmlfile` (an XML file) will return a list of exceptions that include an instance of `exc` (an Exception class) """ func = lambda self, xmlfile=xmlfile, exc=exc, params=params: \ method(self, exc, params, feedvalidator.validateString(open(xmlfile).read(), fallback='US-ASCII', base=xmlBase)['loggedEvents']) func.__doc__ = description return func def buildTestSuite(): curdir = os.path.dirname(os.path.abspath(__file__)) basedir = os.path.split(curdir)[0] for xmlfile in sys.argv[1:] or (glob.glob(os.path.join(basedir, 'testcases', '**', '**', '*.xml')) + glob.glob(os.path.join(basedir, 'testcases', 'opml', '**', '*.opml'))): method, description, params, exc = getDescription(xmlfile) xmlBase = os.path.abspath(xmlfile).replace(basedir,"http://www.feedvalidator.org") testName = 'test_' + xmlBase.replace(os.path.sep, "/") testFunc = buildTestCase(xmlfile, xmlBase, description, method, exc, params) instanceMethod = new.instancemethod(testFunc, None, TestCase) setattr(TestCase, testName, instanceMethod) return unittest.TestLoader().loadTestsFromTestCase(TestCase) if __name__ == '__main__': suite = buildTestSuite() unittest.main(argv=sys.argv[:1])