Fix tests incorrectly identified if worker crashes during teardown stage

Fix #124
This commit is contained in:
Bruno Oliveira
2017-08-10 10:43:40 -03:00
parent 79f1b6dab2
commit f8e138b986
5 changed files with 46 additions and 19 deletions

1
changelog/124.bugfix Normal file
View File

@@ -0,0 +1 @@
Fix issue where tests were being incorrectly identified if a worker crashed during the ``teardown`` stage of the test.

View File

@@ -471,18 +471,34 @@ def test_funcarg_teardown_failure(testdir):
assert result.ret
def test_crashing_item(testdir):
@pytest.mark.parametrize('when', ['setup', 'call', 'teardown'])
def test_crashing_item(testdir, when):
"""Ensure crashing item is correctly reported during all testing stages"""
code = dict(setup='', call='', teardown='')
code[when] = 'py.process.kill(os.getpid())'
p = testdir.makepyfile("""
import py
import os
def test_crash():
py.process.kill(os.getpid())
def test_noncrash():
import py
import pytest
@pytest.fixture
def fix():
{setup}
yield
{teardown}
def test_crash(fix):
{call}
pass
""")
def test_ok():
pass
""".format(**code))
passes = 2 if when == 'teardown' else 1
result = testdir.runpytest("-n2", p)
result.stdout.fnmatch_lines([
"*crashed*test_crash*", "*1 failed*1 passed*"
"*crashed*test_crash*",
"*1 failed*%d passed*" % passes,
])

View File

@@ -230,18 +230,19 @@ class DSession:
nodeid=nodeid, location=location)
def slave_testreport(self, node, rep):
"""Emitted when a node calls the pytest_runtest_logreport hook.
If the node indicates it is finished with a test item, remove
the item from the pending list in the scheduler.
"""
if rep.when == "call" or (rep.when == "setup" and not rep.passed):
self.sched.mark_test_complete(node, rep.item_index, rep.duration)
# self.report_line("testreport %s: %s" %(rep.id, rep.status))
"""Emitted when a node calls the pytest_runtest_logreport hook."""
rep.node = node
self.config.hook.pytest_runtest_logreport(report=rep)
self._handlefailures(rep)
def slave_runtest_protocol_complete(self, node, item_index, duration):
"""
Emitted when a node fires the 'runtest_protocol_complete' event,
signalling that a test has completed the runtestprotocol and should be
removed from the pending list in the scheduler.
"""
self.sched.mark_test_complete(node, item_index, duration)
def slave_collectreport(self, node, rep):
"""Emitted when a node calls the pytest_collectreport hook."""
if rep.failed:

View File

@@ -8,6 +8,7 @@
import sys
import os
import time
import pytest
@@ -59,23 +60,29 @@ class SlaveInteractor:
self.log("items to run:", torun)
# only run if we have an item and a next item
while len(torun) >= 2:
self.run_tests(torun)
self.run_one_test(torun)
if name == "shutdown":
if torun:
self.run_tests(torun)
self.run_one_test(torun)
break
return True
def run_tests(self, torun):
def run_one_test(self, torun):
items = self.session.items
self.item_index = torun.pop(0)
item = items[self.item_index]
if torun:
nextitem = items[torun[0]]
else:
nextitem = None
start = time.time()
self.config.hook.pytest_runtest_protocol(
item=items[self.item_index],
item=item,
nextitem=nextitem)
duration = time.time() - start
self.sendevent("runtest_protocol_complete", item_index=self.item_index,
duration=duration)
def pytest_collection_finish(self, session):
self.sendevent(

View File

@@ -315,6 +315,8 @@ class SlaveController(object):
self.notify_inproc(eventname, node=self, rep=rep)
elif eventname == "collectionfinish":
self.notify_inproc(eventname, node=self, ids=kwargs['ids'])
elif eventname == "runtest_protocol_complete":
self.notify_inproc(eventname, node=self, **kwargs)
elif eventname == "logwarning":
self.notify_inproc(eventname, message=kwargs['message'],
code=kwargs['code'], nodeid=kwargs['nodeid'],