关于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的初始化只执行一次:整个测试会话(比如你跑所有测试用例的过程)中,
dbFixture里yield之前的代码(创建临时目录、初始化CardsDB)只会运行一次,生成唯一的数据库实例。 - yield是“暂停+暴露实例”,不是“多次交权”:
yield db_的作用是暂停Fixture的执行,同时把生成的db_实例交给pytest的缓存系统。之后所有依赖这个dbFixture的对象(不管是测试函数还是cards_db这种函数级Fixture),都会直接从缓存中拿同一个实例,不会重新触发dbFixture的初始化。 - 清理代码仅在会话结束后执行:
yield之后的db_.close(),只会在整个测试会话的所有测试用例都执行完毕后,才会运行一次。
结合示例的执行流程
- 测试会话启动,pytest先执行
dbFixture的初始化代码,生成CardsDB实例,然后暂停在yield处,把实例存入缓存。 - 第一个测试函数执行前,调用
cards_dbFixture,它依赖db,直接从缓存取出那个唯一的数据库实例,执行delete_all()清空数据后,把实例传给测试函数。 - 第二个测试函数执行时,重复步骤2:
cards_db依然拿到缓存里的同一个数据库实例,清空后传给测试函数——全程不会重新创建数据库连接。 - 所有测试执行完毕,pytest回到
dbFixture的yield位置,执行db_.close()完成清理。
内容的提问来源于stack exchange,提问作者naz
相关产品推荐
相关产品推荐

