test_ok1/py/test/terminal/terminal.py

295 lines
11 KiB
Python

import py
from time import time as now
from py.__.test.terminal.out import getout
from py.__.test.representation import Presenter
from py.__.test.outcome import Skipped, Passed, Failed
def getrelpath(source, dest):
base = source.common(dest)
if not base:
return None
# with posix local paths '/' is always a common base
relsource = source.relto(base)
reldest = dest.relto(base)
n = relsource.count(source.sep)
target = dest.sep.join(('..', )*n + (reldest, ))
return target
from py.__.test.session import Session
class TerminalSession(Session):
def __init__(self, config, file=None):
super(TerminalSession, self).__init__(config)
if file is None:
file = py.std.sys.stdout
self._file = file
self.out = getout(file)
self._opencollectors = []
self.presenter = Presenter(self.out, config)
# ---------------------
# PROGRESS information
# ---------------------
def start(self, colitem):
super(TerminalSession, self).start(colitem)
if self.config.option.collectonly:
cols = self._opencollectors
self.out.line(' ' * len(cols) + repr(colitem))
cols.append(colitem)
else:
cls = getattr(colitem, '__class__', None)
if cls is None:
return
if issubclass(cls, py.test.collect.Module):
self.start_Module(colitem)
elif issubclass(cls, py.test.collect.Item):
self.start_Item(colitem)
#for typ in py.std.inspect.getmro(cls):
# meth = getattr(self, 'start_%s' % typ.__name__, None)
# if meth:
# meth(colitem)
# break
colitem.start = py.std.time.time()
def start_Module(self, colitem):
if self.config.option.verbose == 0:
abbrev_fn = getrelpath(py.path.local('.xxx.'), colitem.fspath)
self.out.write('%s' % (abbrev_fn, ))
else:
self.out.line()
self.out.line("+ testmodule: %s" % colitem.fspath)
def startiteration(self, colitem, subitems):
if (isinstance(colitem, py.test.collect.Module)
and self.config.option.verbose == 0
and not self.config.option.collectonly):
try:
sum = 0
for sub in subitems:
sum += len(list(colitem.join(sub)._tryiter()))
except (SystemExit, KeyboardInterrupt):
raise
except:
self.out.write('[?]')
else:
self.out.write('[%d] ' % sum)
return self.out.line
def start_Item(self, colitem):
if self.config.option.verbose >= 1:
if isinstance(colitem, py.test.collect.Item):
realpath, lineno = colitem._getpathlineno()
location = "%s:%d" % (realpath.basename, lineno+1)
self.out.write("%-20s %s " % (location, colitem._getmodpath()))
def finish(self, colitem, outcome):
end = now()
super(TerminalSession, self).finish(colitem, outcome)
if self.config.option.collectonly:
cols = self._opencollectors
last = cols.pop()
#assert last == colitem, "expected %r, got %r" %(last, colitem)
return
colitem.elapsedtime = end - colitem.start
if self.config.option.usepdb:
if isinstance(outcome, Failed):
print "dispatching to ppdb", colitem
self.repr_failure(colitem, outcome)
import pdb
self.out.write('\n%s\n' % (outcome.excinfo.exconly(),))
pdb.post_mortem(outcome.excinfo._excinfo[2])
if isinstance(colitem, py.test.collect.Module):
resultstring = self.repr_progress_module_result(colitem, outcome)
if resultstring:
self.out.line(" - " + resultstring)
if isinstance(colitem, py.test.collect.Item):
if self.config.option.verbose >= 1:
resultstring = self.repr_progress_long_result(colitem, outcome)
resultstring += " (%.2f)" % (colitem.elapsedtime,)
self.out.line(resultstring)
else:
c = self.repr_progress_short_result(colitem, outcome)
self.out.write(c)
# -------------------
# HEADER information
# -------------------
def header(self, colitems):
super(TerminalSession, self).header(colitems)
self.out.sep("=", "test process starts")
option = self.config.option
modes = []
for name in 'looponfailing', 'exitfirst', 'nomagic':
if getattr(option, name):
modes.append(name)
#if self._isremoteoption._fromremote:
# modes.insert(0, 'child process')
#else:
# modes.insert(0, 'inprocess')
#mode = "/".join(modes)
#self.out.line("testing-mode: %s" % mode)
self.out.line("executable: %s (%s)" %
(py.std.sys.executable, repr_pythonversion()))
rev = py.__package__.getrev()
self.out.line("using py lib: %s <rev %s>" % (
py.path.local(py.__file__).dirpath(), rev))
if self.config.option.traceconfig or self.config.option.verbose:
for x in colitems:
self.out.line("test target: %s" %(x.fspath,))
conftestmodules = self.config._conftest.getconftestmodules(None)
for i,x in py.builtin.enumerate(conftestmodules):
self.out.line("initial conf %d: %s" %(i, x.__file__))
#for i, x in py.builtin.enumerate(py.test.config.configpaths):
# self.out.line("initial testconfig %d: %s" %(i, x))
#additional = py.test.config.getfirst('additionalinfo')
#if additional:
# for key, descr in additional():
# self.out.line("%s: %s" %(key, descr))
self.out.line()
self.starttime = now()
# -------------------
# FOOTER information
# -------------------
def footer(self, colitems):
super(TerminalSession, self).footer(colitems)
self.endtime = now()
self.out.line()
self.skippedreasons()
self.failures()
self.summaryline()
# --------------------
# progress information
# --------------------
typemap = {
Passed: '.',
Skipped: 's',
Failed: 'F',
}
namemap = {
Passed: 'ok',
Skipped: 'SKIP',
Failed: 'FAIL',
}
def repr_progress_short_result(self, item, outcome):
for outcometype, char in self.typemap.items():
if isinstance(outcome, outcometype):
return char
else:
#raise TypeError, "not an Outomce instance: %r" % (outcome,)
return '?'
def repr_progress_long_result(self, item, outcome):
for outcometype, char in self.namemap.items():
if isinstance(outcome, outcometype):
return char
else:
#raise TypeError, "not an Outcome instance: %r" % (outcome,)
return 'UNKNOWN'
def repr_progress_module_result(self, item, outcome):
if isinstance(outcome, Failed):
return "FAILED TO LOAD MODULE"
elif isinstance(outcome, Skipped):
return "skipped"
elif not isinstance(outcome, (list, Passed)):
return "?"
# --------------------
# summary information
# --------------------
def summaryline(self):
outlist = []
sum = 0
for typ in Passed, Failed, Skipped:
l = self.getitemoutcomepairs(typ)
if l:
outlist.append('%d %s' % (len(l), typ.__name__.lower()))
sum += len(l)
elapsed = self.endtime-self.starttime
status = "%s" % ", ".join(outlist)
self.out.sep('=', 'tests finished: %s in %4.2f seconds' %
(status, elapsed))
def getlastvisible(self, sourcetraceback):
traceback = sourcetraceback[:]
while traceback:
entry = traceback.pop()
try:
x = entry.frame.eval("__tracebackhide__")
except:
x = False
if not x:
return entry
else:
return sourcetraceback[-1]
def skippedreasons(self):
texts = {}
for colitem, outcome in self.getitemoutcomepairs(Skipped):
raisingtb = self.getlastvisible(outcome.excinfo.traceback)
fn = raisingtb.frame.code.path
lineno = raisingtb.lineno
d = texts.setdefault(outcome.excinfo.exconly(), {})
d[(fn,lineno)] = outcome
if texts:
self.out.line()
self.out.sep('_', 'reasons for skipped tests')
for text, dict in texts.items():
for (fn, lineno), outcome in dict.items():
self.out.line('Skipped in %s:%d' %(fn, lineno+1))
self.out.line("reason: %s" % text)
self.out.line()
def failures(self):
if self.config.option.tbstyle == 'no':
return # skip the detailed failure reports altogether
l = self.getitemoutcomepairs(Failed)
if l:
self.out.sep('_')
for colitem, outcome in l:
self.repr_failure(colitem, outcome)
def repr_failure(self, item, outcome):
excinfo = outcome.excinfo
traceback = excinfo.traceback
#print "repr_failures sees item", item
#print "repr_failures sees traceback"
#py.std.pprint.pprint(traceback)
if item and not self.config.option.fulltrace:
path, firstlineno = item._getpathlineno()
ntraceback = traceback.cut(path=path, firstlineno=firstlineno)
if ntraceback == traceback:
ntraceback = ntraceback.cut(path=path)
traceback = ntraceback.filter()
if not traceback:
self.out.line("empty traceback from item %r" % (item,))
return
handler = getattr(self.presenter, 'repr_failure_tb%s' % self.config.option.tbstyle)
handler(item, excinfo, traceback, lambda : self.repr_out_err(item))
def repr_out_err(self, colitem):
for parent in colitem.listchain():
for name, obj in zip(['out', 'err'], parent._getouterr()):
if obj:
self.out.sep("- ", "%s: recorded std%s" % (parent.name, name))
self.out.line(obj)
def repr_pythonversion():
v = py.std.sys.version_info
try:
return "%s.%s.%s-%s-%s" % v
except ValueError:
return str(v)