pytest_sessionfinish无法调用session级fixture如何解决?
问题根因
- pytest的fixture有独立的生命周期管理,只有被测试用例/其他fixture显式依赖时才会被自动调度执行,无法像普通函数一样直接在钩子中调用
- 你代码里的
myfunction仅引用了fixture的函数对象,没有触发执行逻辑,因此不会产生对应输出
可行解决方案
方案1:抽离公共逻辑(最推荐,改动最小)
把fixture中的核心业务逻辑抽成独立普通函数,fixture和钩子都直接调用该函数,绕开fixture生命周期限制:
# 抽离核心逻辑为普通函数 def run_my_logic(ser: Serial, logger: Logger) -> bool: print("In my function") # 原有fixture的业务逻辑写在这里 ... # 原fixture保留,供其他用例/依赖使用 @pytest.fixture(scope="session") def myfunction(ser: Serial, logger: Logger) -> bool: return run_my_logic(ser, logger) @pytest.hookimpl(trylast=True) def pytest_sessionfinish(session, exitstatus): print("Prepare to call myfunction") # 仅测试全部执行成功时运行 if exitstatus != 0: return # 从session配置中获取已经初始化的ser、logger实例(提前在其他地方存入stash即可) ser = session.config.stash["serial_instance"] logger = session.config.stash["logger_instance"] # 直接调用核心逻辑 run_my_logic(ser, logger)
方案2:通过fixture的yield语法实现后置执行
利用session级fixture的yield特性,后置逻辑会在所有测试用例执行完成后、session销毁前运行,配合全局标记判断测试结果即可:
# 存储测试执行结果的标记 TEST_PASSED = False # 统计测试结果 @pytest.hookimpl(tryfirst=True) def pytest_sessionfinish(session, exitstatus): global TEST_PASSED TEST_PASSED = (exitstatus == 0) @pytest.fixture(scope="session", autouse=True) # autouse保证fixture会自动加载 def myfunction(ser: Serial, logger: Logger) -> bool: # 如果fixture有初始化逻辑,写在yield前 yield # 所有测试跑完后执行,仅测试全部成功时运行逻辑 if TEST_PASSED: print("In my function") # 原有fixture的业务逻辑写在这里 ...
方案3:在钩子中主动触发fixture执行
如果一定要直接在pytest_sessionfinish中调用fixture,可以通过pytest内置的fixture管理器主动调度执行:
@pytest.hookimpl(trylast=True) def pytest_sessionfinish(session, exitstatus): print("Prepare to call myfunction") if exitstatus != 0: return # 获取fixture定义 fixture_defs = session._fixturemanager.getfixturedefs("myfunction", session.config.rootpath) if not fixture_defs: return # 执行fixture获取返回值 my_func_result = fixture_defs[0].cached_call(session) # 后续可使用返回值处理业务逻辑
内容的提问来源于stack exchange,提问作者yyuankm
相关产品推荐
相关产品推荐

