231 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
"""
 | 
						|
    test support code
 | 
						|
 
 | 
						|
    makeuniquepyfile(source) generates a per-test-run-unique directory and test_*.py file 
 | 
						|
 | 
						|
    for analyzing events an EventSorter instance is returned for both of: 
 | 
						|
    * events_from_cmdline(args): inprocess-run of cmdline invocation
 | 
						|
    * events_from_session(session): inprocess-run of given session
 | 
						|
    * events_run_example(examplename, *args):in-process-run of
 | 
						|
      given example test file 
 | 
						|
    
 | 
						|
    eventappender(config): for getting all events in a list: 
 | 
						|
"""
 | 
						|
import py
 | 
						|
from py.__.test import event
 | 
						|
from fnmatch import fnmatch
 | 
						|
 | 
						|
def eventappender(session):
 | 
						|
    l = []
 | 
						|
    def app(ev):
 | 
						|
        print ev
 | 
						|
        l.append(ev)
 | 
						|
    session.bus.subscribe(app)
 | 
						|
    return l 
 | 
						|
 | 
						|
def initsorter_from_cmdline(args=None):
 | 
						|
    if args is None: 
 | 
						|
        args = []
 | 
						|
    config = py.test.config._reparse(args)
 | 
						|
    session = config.initsession()
 | 
						|
    sorter = EventSorter(config, session)
 | 
						|
    return sorter 
 | 
						|
 | 
						|
def getcolitems(config):
 | 
						|
    return [config.getfsnode(arg) for arg in config.args]
 | 
						|
 | 
						|
def events_from_cmdline(args=None):
 | 
						|
    sorter = initsorter_from_cmdline(args)
 | 
						|
    sorter.session.main(getcolitems(sorter.session.config))
 | 
						|
    return sorter 
 | 
						|
 | 
						|
def events_from_runsource(source):
 | 
						|
    source = py.code.Source(source)
 | 
						|
    tfile = makeuniquepyfile(source) 
 | 
						|
    return events_from_cmdline([tfile])
 | 
						|
 | 
						|
def events_from_session(session):
 | 
						|
    sorter = EventSorter(session.config, session)
 | 
						|
    session.main(getcolitems(session.config))
 | 
						|
    return sorter 
 | 
						|
 | 
						|
def events_run_example(examplename, *args):
 | 
						|
    from setupdata import getexamplefile
 | 
						|
    p = getexamplefile(examplename) 
 | 
						|
    return events_from_cmdline([p] + list(args))
 | 
						|
 | 
						|
class EventSorter(object):
 | 
						|
    def __init__(self, config, session=None):
 | 
						|
        self.config = config
 | 
						|
        self.session = session
 | 
						|
        self.cls2events = d = {}
 | 
						|
        def app(event):
 | 
						|
            print "[event]", event
 | 
						|
            for cls in py.std.inspect.getmro(event.__class__):
 | 
						|
                if cls is not object: 
 | 
						|
                    d.setdefault(cls, []).append(event) 
 | 
						|
        session.bus.subscribe(app)
 | 
						|
 | 
						|
    def get(self, cls):
 | 
						|
        return self.cls2events.get(cls, [])
 | 
						|
 | 
						|
    def listoutcomes(self):
 | 
						|
        passed = []
 | 
						|
        skipped = []
 | 
						|
        failed = []
 | 
						|
        for ev in self.get(event.ItemTestReport):
 | 
						|
            if ev.passed: 
 | 
						|
                passed.append(ev) 
 | 
						|
            elif ev.skipped: 
 | 
						|
                skipped.append(ev) 
 | 
						|
            elif ev.failed:
 | 
						|
                failed.append(ev) 
 | 
						|
        return passed, skipped, failed 
 | 
						|
 | 
						|
    def countoutcomes(self):
 | 
						|
        return map(len, self.listoutcomes())
 | 
						|
 | 
						|
    def assertoutcome(self, passed=0, skipped=0, failed=0):
 | 
						|
        realpassed, realskipped, realfailed = self.listoutcomes()
 | 
						|
        assert passed == len(realpassed)
 | 
						|
        assert skipped == len(realskipped)
 | 
						|
        assert failed == len(realfailed)
 | 
						|
 | 
						|
    def getfailedcollections(self):
 | 
						|
        l = []
 | 
						|
        for ev in self.get(event.CollectionReport):
 | 
						|
            if ev.failed:
 | 
						|
               l.append(ev) 
 | 
						|
        return l
 | 
						|
 | 
						|
    def getreport(self, inamepart): 
 | 
						|
        """ return a testreport whose dotted import path matches """
 | 
						|
        l = []
 | 
						|
        for rep in self.get(event.ItemTestReport):
 | 
						|
            if inamepart in rep.colitem.listnames():
 | 
						|
                l.append(rep)
 | 
						|
        if len(l) != 1:
 | 
						|
            raise ValueError("did not find exactly one testreport"
 | 
						|
                             "found" + str(l))
 | 
						|
        return l[0]
 | 
						|
            
 | 
						|
 | 
						|
counter = py.std.itertools.count().next
 | 
						|
def makeuniquepyfile(source):
 | 
						|
    dirname = "test_%d" %(counter(),)
 | 
						|
    tmpdir = py.test.ensuretemp(dirname) 
 | 
						|
    p = tmpdir.join(dirname + ".py")
 | 
						|
    assert not p.check()
 | 
						|
    p.write(py.code.Source(source))
 | 
						|
    print "created test file", p
 | 
						|
    p.dirpath("__init__.py").ensure() 
 | 
						|
    return p
 | 
						|
 | 
						|
def getItemTestReport(source, tb="long"):
 | 
						|
    tfile = makeuniquepyfile(source)
 | 
						|
    sorter = events_from_cmdline([tfile, "--tb=%s" %tb])
 | 
						|
    # get failure base info 
 | 
						|
    failevents = sorter.get(event.ItemTestReport)
 | 
						|
    assert len(failevents) == 1
 | 
						|
    return failevents[0],tfile
 | 
						|
 | 
						|
def assert_lines_contain_lines(lines1, lines2):
 | 
						|
    """ assert that lines2 are contained (linearly) in lines1. 
 | 
						|
        return a list of extralines found.
 | 
						|
    """
 | 
						|
    __tracebackhide__ = True
 | 
						|
    if isinstance(lines2, str):
 | 
						|
        lines2 = py.code.Source(lines2)
 | 
						|
    if isinstance(lines2, py.code.Source):
 | 
						|
        lines2 = lines2.strip().lines
 | 
						|
 | 
						|
    extralines = []
 | 
						|
    lines1 = lines1[:]
 | 
						|
    nextline = None
 | 
						|
    for line in lines2:
 | 
						|
        nomatchprinted = False
 | 
						|
        while lines1:
 | 
						|
            nextline = lines1.pop(0)
 | 
						|
            if line == nextline:
 | 
						|
                print "exact match:", repr(line)
 | 
						|
                break 
 | 
						|
            elif fnmatch(nextline, line):
 | 
						|
                print "fnmatch:", repr(line)
 | 
						|
                print "   with:", repr(nextline)
 | 
						|
                break
 | 
						|
            else:
 | 
						|
                if not nomatchprinted:
 | 
						|
                    print "nomatch:", repr(line)
 | 
						|
                    nomatchprinted = True
 | 
						|
                print "    and:", repr(nextline)
 | 
						|
            extralines.append(nextline)
 | 
						|
        else:
 | 
						|
            if line != nextline:
 | 
						|
                #__tracebackhide__ = True
 | 
						|
                raise AssertionError("expected line not found: %r" % line)
 | 
						|
    extralines.extend(lines1)
 | 
						|
    return extralines 
 | 
						|
 | 
						|
# XXX below some code to help with inlining examples 
 | 
						|
#     as source code.  
 | 
						|
#
 | 
						|
class FileCreation(object):
 | 
						|
    def setup_method(self, method):
 | 
						|
        self.tmpdir = py.test.ensuretemp("%s_%s" % 
 | 
						|
            (self.__class__.__name__, method.__name__))
 | 
						|
    def makepyfile(self, **kwargs):
 | 
						|
        return self._makefile('.py', **kwargs)
 | 
						|
    def maketxtfile(self, **kwargs):
 | 
						|
        return self._makefile('.txt', **kwargs)
 | 
						|
    def _makefile(self, ext, **kwargs):
 | 
						|
        ret = None
 | 
						|
        for name, value in kwargs.iteritems():
 | 
						|
            p = self.tmpdir.join(name).new(ext=ext)
 | 
						|
            source = py.code.Source(value)
 | 
						|
            p.write(str(py.code.Source(value)).lstrip())
 | 
						|
            if ret is None:
 | 
						|
                ret = p
 | 
						|
        return ret 
 | 
						|
 
 | 
						|
class InlineCollection(FileCreation):
 | 
						|
    """ helps to collect and run test functions inlining other test functions. """
 | 
						|
 | 
						|
    def getmodulecol(self, source, configargs=(), withsession=False):
 | 
						|
        self.tmpdir.ensure("__init__.py")
 | 
						|
        kw = {self.tmpdir.basename: py.code.Source(source).strip()}
 | 
						|
        path = self.makepyfile(**kw)
 | 
						|
        self.config = self.parseconfig(path, *configargs)
 | 
						|
        if withsession:
 | 
						|
            self.session = self.config.initsession()
 | 
						|
        return self.config.getfsnode(path)
 | 
						|
 | 
						|
    def parseconfig(self, *args):
 | 
						|
        return py.test.config._reparse(list(args))
 | 
						|
 | 
						|
    def getitems(self, source):
 | 
						|
        modulecol = self.getmodulecol(source)
 | 
						|
        return [modulecol.join(x) for x in modulecol.listdir()]
 | 
						|
 | 
						|
    def getitem(self, source, funcname="test_func"):
 | 
						|
        modulecol = self.getmodulecol(source)
 | 
						|
        item = modulecol.join(funcname) 
 | 
						|
        assert item is not None, "%r item not found in module:\n%s" %(funcname, source)
 | 
						|
        return item 
 | 
						|
 | 
						|
    def runitem(self, func, funcname="test_func", **runnerargs):
 | 
						|
        item = self.getitem(func, funcname=funcname)
 | 
						|
        runner = self.getrunner()
 | 
						|
        return runner(item, **runnerargs)
 | 
						|
 | 
						|
 | 
						|
def popvalue(stringio):
 | 
						|
    value = stringio.getvalue().rstrip()
 | 
						|
    stringio.truncate(0)
 | 
						|
    return value
 | 
						|
 | 
						|
def assert_stringio_contains_lines(stringio, tomatchlines):
 | 
						|
    stringio.seek(0)
 | 
						|
    l = stringio.readlines()
 | 
						|
    l = map(str.rstrip, l)
 | 
						|
    assert_lines_contain_lines(l, tomatchlines)
 |