[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:
arigo 2008-09-12 22:35:18 +02:00
parent f12b795147
commit 7afc30d130
4 changed files with 44 additions and 12 deletions

View File

@ -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):

View File

@ -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,

View File

@ -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)

View File

@ -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):