如何仅 运行 pytest fixture 在测试错误或失败时清理
How to only run a pytest fixture cleanup on test error or failure
我只想在测试不成功时保存 pytest
测试运行的日志文件,这可能是由于测试装置设置错误或测试本身失败。
我的方法是创建一个测试装置来复制 yield
之后的日志,但我不知道如何让它以测试结果为条件。
@pytest.fixture
def setup():
do_setup()
yield
do_teardown()
@pytest.fixture
def get_logs():
yield
if not test_success: # how to know this condition?
copy_log_files()
def test_run(get_logs, setup):
do_test_stuff()
使用 pytest_runtest_makereport,如文档所述:
Called to create a _pytest.reports.TestReport for each of the setup, call and teardown runtest phases of a test item.
并与_Result.get_result() to add the result in the Node/Item一起使用。
我们实际上可以按照 Making test result information available in fixtures
中记录的相同步骤进行操作
conftest.py
import pytest
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
# execute all other hooks to obtain the report object
outcome = yield
rep = outcome.get_result()
# set a report attribute for each phase of a call, which can
# be "setup", "call", "teardown"
setattr(item, "rep_" + rep.when, rep)
test_module.py
import pytest
@pytest.fixture
def get_logs(request):
yield
if request.node.rep_call.failed:
# Add code here to cleanup failure scenario
print("executing test failed")
elif request.node.rep_call.passed:
# Add code here to cleanup success scenario
print("executing test success")
def test_run1(get_logs):
print("Test 1")
assert 1
def test_run2(get_logs):
print("Test 2")
assert 0
def test_run3(get_logs):
print("Test 3")
assert 1
def test_run4(get_logs):
print("Test 4")
assert 0
输出
$ pytest -rP test_module.py
test_module.py .F.F [100%]
============================================= FAILURES ==============================================
_____________________________________________ test_run2 _____________________________________________
get_logs = None
def test_run2(get_logs):
print("Test 2")
> assert 0
E assert 0
test_module.py:21: AssertionError
--------------------------------------- Captured stdout call ----------------------------------------
Test 2
------------------------------------- Captured stdout teardown --------------------------------------
executing test failed
_____________________________________________ test_run4 _____________________________________________
get_logs = None
def test_run4(get_logs):
print("Test 4")
> assert 0
E assert 0
test_module.py:31: AssertionError
--------------------------------------- Captured stdout call ----------------------------------------
Test 4
------------------------------------- Captured stdout teardown --------------------------------------
executing test failed
============================================== PASSES ===============================================
_____________________________________________ test_run1 _____________________________________________
--------------------------------------- Captured stdout call ----------------------------------------
Test 1
------------------------------------- Captured stdout teardown --------------------------------------
executing test success
_____________________________________________ test_run3 _____________________________________________
--------------------------------------- Captured stdout call ----------------------------------------
Test 3
------------------------------------- Captured stdout teardown --------------------------------------
executing test success
==================================== 2 failed, 2 passed in 0.11s ====================================
我只想在测试不成功时保存 pytest
测试运行的日志文件,这可能是由于测试装置设置错误或测试本身失败。
我的方法是创建一个测试装置来复制 yield
之后的日志,但我不知道如何让它以测试结果为条件。
@pytest.fixture
def setup():
do_setup()
yield
do_teardown()
@pytest.fixture
def get_logs():
yield
if not test_success: # how to know this condition?
copy_log_files()
def test_run(get_logs, setup):
do_test_stuff()
使用 pytest_runtest_makereport,如文档所述:
Called to create a _pytest.reports.TestReport for each of the setup, call and teardown runtest phases of a test item.
并与_Result.get_result() to add the result in the Node/Item一起使用。
我们实际上可以按照 Making test result information available in fixtures
中记录的相同步骤进行操作conftest.py
import pytest
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
# execute all other hooks to obtain the report object
outcome = yield
rep = outcome.get_result()
# set a report attribute for each phase of a call, which can
# be "setup", "call", "teardown"
setattr(item, "rep_" + rep.when, rep)
test_module.py
import pytest
@pytest.fixture
def get_logs(request):
yield
if request.node.rep_call.failed:
# Add code here to cleanup failure scenario
print("executing test failed")
elif request.node.rep_call.passed:
# Add code here to cleanup success scenario
print("executing test success")
def test_run1(get_logs):
print("Test 1")
assert 1
def test_run2(get_logs):
print("Test 2")
assert 0
def test_run3(get_logs):
print("Test 3")
assert 1
def test_run4(get_logs):
print("Test 4")
assert 0
输出
$ pytest -rP test_module.py
test_module.py .F.F [100%]
============================================= FAILURES ==============================================
_____________________________________________ test_run2 _____________________________________________
get_logs = None
def test_run2(get_logs):
print("Test 2")
> assert 0
E assert 0
test_module.py:21: AssertionError
--------------------------------------- Captured stdout call ----------------------------------------
Test 2
------------------------------------- Captured stdout teardown --------------------------------------
executing test failed
_____________________________________________ test_run4 _____________________________________________
get_logs = None
def test_run4(get_logs):
print("Test 4")
> assert 0
E assert 0
test_module.py:31: AssertionError
--------------------------------------- Captured stdout call ----------------------------------------
Test 4
------------------------------------- Captured stdout teardown --------------------------------------
executing test failed
============================================== PASSES ===============================================
_____________________________________________ test_run1 _____________________________________________
--------------------------------------- Captured stdout call ----------------------------------------
Test 1
------------------------------------- Captured stdout teardown --------------------------------------
executing test success
_____________________________________________ test_run3 _____________________________________________
--------------------------------------- Captured stdout call ----------------------------------------
Test 3
------------------------------------- Captured stdout teardown --------------------------------------
executing test success
==================================== 2 failed, 2 passed in 0.11s ====================================