You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Pytest会话级Fixture多次yield行为的疑问求助

理解Pytest会话级Fixture的yield复用机制

先看你提供的示例代码:

@pytest.fixture(scope="session")
def db():
    """CardsDB object connected to a temporary database"""
    with TemporaryDirectory() as db_dir:
        db_path = Path(db_dir)
        db_ = cards.CardsDB(db_path)
        yield db_
        db_.close()

@pytest.fixture(scope="function")
def cards_db(db):
    """CardsDB object that's empty"""
    db.delete_all()
    return db

核心机制拆解

你的困惑点在于对会话级Fixture的yield和缓存逻辑理解有误,这里直接拆解关键规则:

  • 会话级Fixture的初始化只执行一次:整个测试会话(比如你跑所有测试用例的过程)中,db Fixture里yield之前的代码(创建临时目录、初始化CardsDB)只会运行一次,生成唯一的数据库实例。
  • yield是“暂停+暴露实例”,不是“多次交权”:yield db_的作用是暂停Fixture的执行,同时把生成的db_实例交给pytest的缓存系统。之后所有依赖这个db Fixture的对象(不管是测试函数还是cards_db这种函数级Fixture),都会直接从缓存中拿同一个实例,不会重新触发db Fixture的初始化。
  • 清理代码仅在会话结束后执行:yield之后的db_.close(),只会在整个测试会话的所有测试用例都执行完毕后,才会运行一次。

结合示例的执行流程

  1. 测试会话启动,pytest先执行db Fixture的初始化代码,生成CardsDB实例,然后暂停在yield处,把实例存入缓存。
  2. 第一个测试函数执行前,调用cards_db Fixture,它依赖db,直接从缓存取出那个唯一的数据库实例,执行delete_all()清空数据后,把实例传给测试函数。
  3. 第二个测试函数执行时,重复步骤2:cards_db依然拿到缓存里的同一个数据库实例,清空后传给测试函数——全程不会重新创建数据库连接。
  4. 所有测试执行完毕,pytest回到db Fixture的yield位置,执行db_.close()完成清理。

内容的提问来源于stack exchange,提问作者naz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:45:31