Как определить, прошел или не прошел тест, изучив объект Item, переданный в pytest runtest teardown?
Pytest позволяет подключаться к фазе демонтажа для каждого теста, реализуя функцию под названием pytest_runtest_teardown
в плагине:
def pytest_runtest_teardown(item, nextitem):
pass
есть ли атрибут или метод на item
что я могу использовать, чтобы определить, прошел ли тест, который только что закончился, или не прошел? Я не смог найти никакой документации для pytest.Item
и охота через исходный код и в ipdb
не показал ничего очевидного.
2 ответов
вы также можете рассмотреть вызов.excinfo в pytest_runtest_makereport:
def pytest_runtest_makereport(item, call):
if call.when == 'setup':
print('Called after setup for test case is executed.')
if call.when == 'call':
print('Called after test case is executed.')
print('-->{}<--'.format(call.excinfo))
if call.when == 'teardown':
print('Called after teardown for test case is executed.')
объект вызова содержит целую кучу дополнительной информации (время начала тестирования, время остановки и т. д.).
см.: http://doc.pytest.org/en/latest/_modules/_pytest/runner.html
def pytest_runtest_makereport(item, call):
when = call.when
duration = call.stop-call.start
keywords = dict([(x,1) for x in item.keywords])
excinfo = call.excinfo
sections = []
if not call.excinfo:
outcome = "passed"
longrepr = None
else:
if not isinstance(excinfo, ExceptionInfo):
outcome = "failed"
longrepr = excinfo
elif excinfo.errisinstance(pytest.skip.Exception):
outcome = "skipped"
r = excinfo._getreprcrash()
longrepr = (str(r.path), r.lineno, r.message)
else:
outcome = "failed"
if call.when == "call":
longrepr = item.repr_failure(excinfo)
else: # exception in setup or teardown
longrepr = item._repr_failure_py(excinfo,
style=item.config.option.tbstyle)
for rwhen, key, content in item._report_sections:
sections.append(("Captured %s %s" %(key, rwhen), content))
return TestReport(item.nodeid, item.location,
keywords, outcome, longrepr, when,
sections, duration)
The Node
класс не имеют никакой информации о состоянии последнего теста, однако у нас есть статус общего количества неудачных тестов (в item.session.testsfailed
), и мы можем использовать это:
- мы можем добавить нового члена
item.session
объект (не так хорошо, но вы должны любить python!). Этот участник сохранит статус последнегоtestsfailed
-item.session.last_testsfailed_status
. - если
testsfailed
>last_testsfailed_status
- последний тест запуск просто неудачный.
import pytest
import logging
logging.basicConfig(
level='INFO',
handlers=(
logging.StreamHandler(),
logging.FileHandler('log.txt')
)
)
@pytest.mark.hookwrapper
def pytest_runtest_teardown(item, nextitem):
outcome = yield
if not hasattr(item.session, 'last_testsfailed_status'):
item.session.last_testsfailed_status = 0
if item.session.testsfailed and item.session.testsfailed > item.session.last_testsfailed_status:
logging.info('Last test failed')
item.session.last_testsfailed_status = item.session.testsfailed