pytest框架---fixture固件

📅 2026/6/26 16:27:29
pytest框架---fixture固件
在 Pytest 框架中Fixture固件 绝对是最核心、最强大的功能没有之一。如果说 parametrize 是 Pytest 的“心脏”负责驱动数据那么 Fixture 就是 Pytest 的“神经系统”负责提供测试所需的全部外部资源和环境。Fixture 允许你设置一些特定的测试环境或准备测试数据这些环境和数据可以在多个测试用例中重复使用。通过使用fixture你可以避免在每个测试函数中编写重复的设置和清理代码使得测试更加干净、简洁并提高代码的可维护性。pytest.fixturedeflogin_token():print(① 去数据库查用户生成 token)# 前置yieldabc123# 把 token 交给用例print(③ 用例跑完了删除这个 token 缓存)# 后置无论用例成功还是失败都会执行deftest_order(login_token):print(② 拿着 token 下单)assertabc123inlogin_token上面这段代码的打印顺序是① → ② → ③把 yield 换成 return 的执行顺序① → ②③ 永远不会执行Pytest 的执行指针Instruction Pointer跳转顺序第 0 步准备Pytest 扫描发现 test_order 需要 login_token 参数决定先去 login_token 拿值。指针跳转到第 ② 行Pytest 调用 login_token() 函数。指针进入第 ③ 行执行 print(“① …”)此时控制台输出 ①。指针到达第 ④ 行遇到 yield “abc123”函数在此处暂停冻结把 “abc123” 扔出来。指针跳出 login_tokenPytest 拿到了返回值。指针跳转到第 ⑥ 行Pytest 拿着 “abc123”现在才开始调用 test_order()指针进入第 ⑦ 行执行 print(“② …”)控制台输出 ②。指针进入第 ⑧ 行执行断言。test_order 执行完毕Pytest 发现调用结束了。指针再次跳回第 ④ 行yield 的下一行Pytest 恢复之前暂停的 login_token 函数执行第 ⑤ 行 print(“③ …”)控制台输出 ③。上面代码中assert “abc123” in login_token 这句代码 还会再调用一遍login_token函数吗绝对不会 这句断言 不会再调用一遍 login_token 函数执行时的真相变量与函数的区别在 def test_order(login_token): 这一行中login_token 是函数的形参参数名。当 Pytest 要运行这个测试时它做的事情是提前执行 Fixture它先跑去执行 login_token 这个函数拿到返回值 “abc123”如果在 yield 情况下执行到 yield 暂停。参数注入赋值Pytest 把拿到的结果 “abc123” 直接赋值给 test_order 的参数 login_token。执行用例此时在函数体内login_token 已经不再是一个函数而是一个实实在在的字符串变量它的值就是 “abc123”。所以你在断言里写 assert “abc123” in login_token在 Python 看来这行代码实际上等价于assert “abc123” in “abc123”pytest.fixture 上面代码中这一段代码是什么作用如果你把 pytest.fixture 这行删掉 会报错。 Python 会认为 test_order 是一个普通函数需要调用者手动传参。但你在调用时没传所以报错。加上 pytest.fixture 后Pytest 在启动时会扫描所有被这个装饰器标记的函数把它们记录在一个“内部字典注册表”里。当它看到 test_order 需要一个名为 login_token 的参数时就会去注册表里找找到后自动执行该函数把返回值注入进来。这就实现了“依赖注入DI”——你不需要手动调用框架帮你把“原料”送到手上。pytest.fixture 是 Pytest 依赖注入的核心实现。它在框架启动时将被装饰函数注册为资源提供者通过参数名匹配的方式在测试函数执行前自动调用该函数获取资源如 session、数据库连接并支持通过 yield 实现资源的前置分配与后置回收从而解决了测试环境的初始化和清理问题。被 pytest.fixture 装饰的是 login_token 函数而不是 test_order 函数。test_order 被称为“测试用例Test Case”或“测试函数Test Function”。核心原理Pytest 在启动时收集阶段做了一件极其重要的事它遍历所有以 test_ 开头的函数把它们从“普通函数”注册进自己的“待执行队列”中并打上“测试用例”的标签。当 Pytest 准备执行 test_order 时它会检查这个函数需要哪些参数这里需要 login_token。Pytest 去自己的“注册表”里找发现 login_token 是一个被 pytest.fixture 标记的“供应商”。装饰器是什么装饰器Decorator pytest.fixture被装饰的函数 def login_token():消费者 def test_order(login_token):fixture的强大作用在接口测试中我们经常需要一些共享的资源或设置比如一个预登录获取的token供多个测试用例使用。一个数据库连接用于测试前后清理数据。一个固定的请求头如Content-Type。一个复杂的测试数据对象。如果每个测试函数都去重复写这些代码会非常冗余且难以维护。Fixture就是用来解决这个问题的。它就像一个“夹具”你定义好一个“准备”函数pytest会在运行测试前自动调用它并将返回值“注入”到需要它的测试函数中。比如上面的例子更强大的Fixture作用域scope与清理teardown Fixture可以定义不同的作用域控制其创建和销毁的频率。在pytest中fixture的作用域决定了测试夹具的生命周期以及它们能被哪些测试用例或测试类访问。以下是pytest中fixture的几种作用域及其用途1 function这是fixture的默认作用域。当不指定scope参数时fixture会在每个测试函数执行前被调用并在测试函数结束后清理。它适用于需要为每个测试准备和清理资源的场合。例如打开和关闭数据库连接、初始化和释放内存空间等。2 class当设置scopeclass’时fixture会在一个测试类开始前被调用一次然后在整个类的所有测试方法运行完毕后被清理。这适用于整个测试类共享的准备工作如创建共享的测试环境或对象。3 module如果设置scope‘module’则fixture会在整个模块的第一个测试开始前被调用并在模块中的所有测试完成后被清理。这通常用于模块级别的资源管理比如建立和断开与外部服务的连接。4 package/package.module当设置为scopepackage’或scopepackage.module’时fixture将在整个包或指定的包的模块中运行一次。这适用于跨模块或跨包共享的测试资源例如配置全局服务或执行一次性的环境设置。5 session通过scopesession’设置fixture将在整个测试会话中只运行一次。这适用于开销较大且所有测试用例都可以共享的准备步骤如复杂的系统级设置或一次性的资源分配。6 instance如果设置了scope‘instance’则可以为每个测试实例创建一个fixture实例。这允许在不同的测试用例之间共享状态而不需要在每个测试用例中重新准备。7 classinstance通过scope‘classinstance’可以为每个测试类创建一个fixture实例。与instance类似但适用于在类的不同方法间共享状态。8once使用scopeonce’时fixture只会被调用一次无论被多少个测试用例或测试类引用。这对于单例资源管理或确保某些操作只执行一次非常有用。Fixture用途fixture的主要用途包括设置测试环境例如配置数据库连接、初始化外部服务等。准备测试数据提供测试所需的数据如用户信息、产品列表等。模拟外部依赖当测试难以直接访问外部系统时可以使用fixture来模拟这些系统的行为。执行特定操作在测试前后执行某些特定操作如临时修改配置、记录日志等。共享资源在不同的测试用例之间共享资源减少资源的创建和销毁开销。