Pytest Fixture 相较于全局变量的核心优势疑问(除整洁性外)
除了代码整洁,fixture 在测试场景下比全局变量实用得多,核心优势体现在这几点:
灵活的作用域控制
全局变量从测试会话启动到结束一直存在,不管测试用不用都会占用资源。而 fixture 可以通过scope参数精准控制生命周期:比如scope="function"会给每个测试函数单独初始化实例,scope="module"只在当前模块初始化一次,scope="session"则贯穿整个测试会话。你可以根据资源的复用需求选择合适的作用域,避免不必要的资源浪费。自动的资源清理
用全局变量时,资源清理(比如关闭数据库连接、删除临时文件)得自己手动写钩子或者在测试末尾处理,很容易遗漏导致资源泄漏。fixture 可以通过yield语法实现初始化+清理的闭环:@pytest.fixture(scope="session") def db_connection(): conn = create_db_connection() yield conn # 测试用例执行时拿到这个连接 conn.close() # 测试结束后自动关闭连接不管测试成功还是失败,清理逻辑都会执行,完全不用额外操心。
可组合的依赖关系
fixture 可以依赖其他 fixture,把复杂的初始化逻辑拆成多个小模块。比如你可以先写一个读取配置的db_configfixture,再让db_connection依赖它:@pytest.fixture def db_config(): return {"host": "localhost", "port": 5432} @pytest.fixture def db_connection(db_config): return create_db_connection(**db_config)这种层级依赖能让代码逻辑更清晰,复用性更强。全局变量做不到这种模块化的依赖,只能硬编码初始化顺序,逻辑复杂后很容易出错。
更好的测试隔离性
全局变量的问题在于,某个测试用例如果不小心修改了它的值,会直接影响后续所有测试,排查问题时很难定位到是哪个测试搞的鬼。而 fixture 会根据作用域提供隔离的实例:比如function级别的 fixture,每个测试拿到的都是全新的实例,就算被修改也不会影响其他测试,从根源上避免了这类污染问题。原生支持参数化
你可以给 fixture 加上参数化,让它生成多组不同的测试数据,配合测试用例实现多场景覆盖。比如:@pytest.fixture(params=["mysql", "postgresql"]) def db_connection(request): if request.param == "mysql": conn = create_mysql_conn() else: conn = create_pg_conn() yield conn conn.close()这样所有依赖这个 fixture 的测试都会自动跑两遍,分别测试两种数据库。全局变量要实现类似功能,得手动写循环或者分支,代码会变得臃肿且不易维护。
明确的依赖可见性
在测试函数中声明需要的 fixture,比如def test_query(db_connection):,任何人看代码都能立刻知道这个测试依赖数据库连接。而全局变量的依赖是隐式的,新人接手时得翻遍代码才能理清测试到底用到了哪些全局资源,排查问题的效率极低。
内容的提问来源于stack exchange,提问作者scott_m

