[svn r58095] (pedronis, arigo)
KeyboardInterrupt handling: * in --verbose mode, print a detailed traceback at the end of the report. * in non-verbose mode, only print the file name and line number where the KeyboardInterrupt occurred. That's the minimal amount of information that is of any help at all to locate an infinite loop somewhere. --HG-- branch : trunk
This commit is contained in:
parent
f12b795147
commit
7afc30d130
|
@ -45,8 +45,12 @@ class TestrunStart(BaseEvent):
|
|||
self.timestart = time.time()
|
||||
|
||||
class TestrunFinish(BaseEvent):
|
||||
def __init__(self, exitstatus=0):
|
||||
def __init__(self, exitstatus=0, excinfo=None):
|
||||
self.exitstatus = exitstatus
|
||||
if excinfo is None:
|
||||
self.excrepr = None
|
||||
else:
|
||||
self.excrepr = excinfo.getrepr()
|
||||
self.timeend = time.time()
|
||||
|
||||
class InternalException(BaseEvent):
|
||||
|
|
|
@ -132,6 +132,8 @@ class TerminalReporter(BaseReporter):
|
|||
if ev.exitstatus in (0, 1, 2):
|
||||
self.summary_failures()
|
||||
self.summary_skips()
|
||||
if ev.excrepr is not None:
|
||||
self.summary_final_exc(ev.excrepr)
|
||||
if ev.exitstatus == 2:
|
||||
self.write_sep("!", "KEYBOARD INTERRUPT")
|
||||
self.summary_deselected()
|
||||
|
@ -201,6 +203,13 @@ class TerminalReporter(BaseReporter):
|
|||
for num, fspath, lineno, reason in folded_skips:
|
||||
self._tw.line("%s:%d: [%d] %s" %(fspath, lineno, num, reason))
|
||||
|
||||
def summary_final_exc(self, excrepr):
|
||||
self.write_sep("!")
|
||||
if self.config.option.verbose:
|
||||
excrepr.toterminal(self._tw)
|
||||
else:
|
||||
excrepr.reprcrash.toterminal(self._tw)
|
||||
|
||||
def out_hostinfo(self):
|
||||
self._tw.line("host 0: %s %s - Python %s" %
|
||||
(py.std.sys.platform,
|
||||
|
|
|
@ -207,25 +207,41 @@ class TestTerminal(InlineCollection):
|
|||
print s
|
||||
assert s.find("test_show_path_before_running_test.py") != -1
|
||||
|
||||
def test_keyboard_interrupt(self):
|
||||
def test_keyboard_interrupt(self, verbose=False):
|
||||
modcol = self.getmodulecol("""
|
||||
def test_foobar():
|
||||
assert 0
|
||||
def test_spamegg():
|
||||
import py; py.test.skip('skip me please!')
|
||||
""", configargs=("--showskipsummary",), withsession=True)
|
||||
def test_interrupt_me():
|
||||
raise KeyboardInterrupt # simulating the user
|
||||
""", configargs=("--showskipsummary",) + ("-v",)*verbose,
|
||||
withsession=True)
|
||||
stringio = py.std.cStringIO.StringIO()
|
||||
rep = TerminalReporter(modcol._config, bus=self.session.bus, file=stringio)
|
||||
rep.processevent(event.TestrunStart())
|
||||
for item in self.session.genitems([modcol]):
|
||||
ev = basic_run_report(item)
|
||||
rep.processevent(ev)
|
||||
try:
|
||||
for item in self.session.genitems([modcol]):
|
||||
ev = basic_run_report(item)
|
||||
rep.processevent(ev)
|
||||
except KeyboardInterrupt:
|
||||
excinfo = py.code.ExceptionInfo()
|
||||
else:
|
||||
py.test.fail("no KeyboardInterrupt??")
|
||||
s = popvalue(stringio)
|
||||
assert s.find("test_keyboard_interrupt.py Fs") != -1
|
||||
rep.processevent(event.TestrunFinish(exitstatus=2))
|
||||
if not verbose:
|
||||
assert s.find("_keyboard_interrupt.py Fs") != -1
|
||||
rep.processevent(event.TestrunFinish(exitstatus=2, excinfo=excinfo))
|
||||
assert_stringio_contains_lines(stringio, [
|
||||
" def test_foobar():",
|
||||
"> assert 0",
|
||||
"E assert 0",
|
||||
])
|
||||
assert "Skipped: 'skip me please!'" in stringio.getvalue()
|
||||
text = stringio.getvalue()
|
||||
assert "Skipped: 'skip me please!'" in text
|
||||
assert "_keyboard_interrupt.py:6: KeyboardInterrupt" in text
|
||||
see_details = "raise KeyboardInterrupt # simulating the user" in text
|
||||
assert see_details == verbose
|
||||
|
||||
def test_verbose_keyboard_interrupt(self):
|
||||
self.test_keyboard_interrupt(verbose=True)
|
||||
|
|
|
@ -103,9 +103,10 @@ class Session(object):
|
|||
if self.config.option.exitfirst:
|
||||
self.shouldstop = True
|
||||
|
||||
def sessionfinishes(self, exitstatus=0):
|
||||
def sessionfinishes(self, exitstatus=0, excinfo=None):
|
||||
""" teardown any resources after a test run. """
|
||||
self.bus.notify(event.TestrunFinish(exitstatus=exitstatus))
|
||||
self.bus.notify(event.TestrunFinish(exitstatus=exitstatus,
|
||||
excinfo=excinfo))
|
||||
self.bus.unsubscribe(self._processfailures)
|
||||
#self.reporter.deactivate()
|
||||
return self._failurelist
|
||||
|
@ -123,6 +124,7 @@ class Session(object):
|
|||
self.sessionstarts()
|
||||
self.bus.notify(makehostup())
|
||||
exitstatus = outcome.EXIT_OK
|
||||
captured_excinfo = None
|
||||
try:
|
||||
for item in self.collect(colitems):
|
||||
if self.shouldstop:
|
||||
|
@ -131,13 +133,14 @@ class Session(object):
|
|||
self.runtest(item)
|
||||
py.test.collect.Item._setupstate.teardown_all()
|
||||
except KeyboardInterrupt:
|
||||
captured_excinfo = py.code.ExceptionInfo()
|
||||
exitstatus = outcome.EXIT_INTERRUPTED
|
||||
except:
|
||||
self.bus.notify(event.InternalException())
|
||||
exitstatus = outcome.EXIT_INTERNALERROR
|
||||
if self._failurelist and exitstatus == 0:
|
||||
exitstatus = outcome.EXIT_TESTSFAILED
|
||||
self.sessionfinishes(exitstatus=exitstatus)
|
||||
self.sessionfinishes(exitstatus=exitstatus, excinfo=captured_excinfo)
|
||||
return exitstatus
|
||||
|
||||
def runpdb(self, excinfo):
|
||||
|
|
Loading…
Reference in New Issue