pytest -- fixture
pytest 中的 fixture 是⼀种强⼤的机制,⽤于提供测试函数所需的资源或上下⽂。它可以⽤于设置测试环境、准备数据等。以下是 fixture 的⼀些核⼼概念和使⽤场景
测试脚本中存在的很多重复的代码、公共的数据对象时,使⽤ fixture 最为合适
访问列表⻚和详情⻚之前都需要执⾏登录操作
python
import pytest
@pytest.fixture
def login():
print("---执⾏登陆操作-----")
def test_list(login):
print("---访问列表⻚")
def test_detail(login):
print("---访问详情⻚")
通过使⽤ @pytest.fixture 装饰器来告诉 pytest ⼀个特定函数是⼀个 fixture,通过运⾏结果可⻅,在执⾏列表⻚和详情⻚之前都会先执⾏ login ⽅法。
fixture嵌套
python
# test_append.py的内容
import pytest
# 安排
@pytest.fixture
def first_entry():
return "a"
# 安排
@pytest.fixture
def order(first_entry):
return [first_entry]
def test_string(order):
# ⾏动
order.append("b")
# 断⾔
assert order == ["a", "b"]
测试不必局限于单个 fixture ,它们可以依赖于您想要的任意数量的 fixture ,并且fixture 也可以使⽤其他 fixture 。 pytest 最伟⼤的优势之⼀是其极其灵活的 fixture 系统,它允许我们将测试的复杂需求简化为更简单和有组织的函数,我们只需要每个函数描述它们所依赖的事物
请求多个fixture
python
import pytest
class Fruit:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return self.name == other.name
@pytest.fixture
def my_fruit():
return Fruit("apple")
@pytest.fixture
def fruit_basket(my_fruit):
return [Fruit("banana"), my_fruit]
def test_my_fruit_in_basket(my_fruit, fruit_basket):
assert my_fruit in fruit_basket
测试和 fixture 不仅限于⼀次请求单个 fixture ,它们可以请求任意多个。
yield fixture
当我们运⾏测试时,我们希望确保它们能够⾃我清理,以便它们不会⼲扰其他测试(同时也避免留下⼤量测试数据来膨胀系统)。pytest中的 fixture 提供了⼀个⾮常有⽤拆卸系统,它允许我们为每个 fixture 定义具体的清理步骤。
"Yield" fixture 使⽤ yield ⽽不是 return 。有了这些 fixture ,我们可以运⾏⼀些代码,并将对象返回给请求的 fixture/test ,就像其他 fixture ⼀样。唯⼀的不同是:
• return 被替换为 yield 。
• 该 fixture 的任何拆卸代码放置在 yield 之后。
⼀旦 pytest 确定了 fixture 的线性顺序,它将运⾏每个 fixture 直到它返回或 yield ,然后继续执⾏列表中的下⼀个 fixture 做同样的事情。
测试完成后, pytest 将逆向遍历 fixture 列表,对于每个 yield 的 fixture ,运⾏ yield语句之后的代码。
python
import pytest
@pytest.fixture
def open_close():
print("前置操作,初始化.....")
yield
print("后置操作,清理数据.....")
def test_01(open_close):
print("第⼀个测试⽤例")
创建⽂件句柄与关闭⽂件
python
import pytest
@pytest.fixture
def file_read():
print("打开⽂件句柄")
fo = open("test.txt", "r")
yield fo
print("关闭打开的⽂件")
fo.close()
def file_write():
print("打开⽂件句柄")
fo = open("test.txt","w",encoding="utf-8")
return fo
# yield fo
#
# print("关闭⽂件句柄")
# fo.close()
def test_file(file_write, file_read):
# 写⼊数据
w = file_write
w.write("测试数据")
w.close() # 写⼊后关闭⽂件句柄,以便读取
# 读取数据
r = file_read
str = r.read(10)
print("⽂件内容:", str)
带参数的fixture
python
pytest.fixture(scope='', params='', autouse='', ids='', name='')
参数详解:
• scope 参数⽤于控制fixture的作⽤范围,决定了fixture的⽣命周期。可选值有:
◦ function (默认):每个测试函数都会调⽤⼀次fixture。
◦ class :在同⼀个测试类中共享这个fixture。
◦ module :在同⼀个测试模块中共享这个fixture。(⼀个⽂件⾥)
◦ session :整个测试会话中共享这个fixture。
• autouse 参数默认为 False 。如果设置为 True ,则每个测试函数都会⾃动调⽤该fixture,⽆需显式传⼊
• params 参数⽤于参数化fixture,⽀持列表传⼊。每个参数值都会使fixture执⾏⼀次,类似于for循环
• ids 参数与 params 配合使⽤,为每个参数化实例指定可读的标识符(给参数取名字)
• name 参数⽤于为fixture显式设置⼀个名称。如果使⽤了 name ,则在测试函数中需要使⽤这个名称来引⽤ fixture (给fixture取名字)
• scope 默认为 function ,这⾥的 function 可以省略不写,当 scope="function" 时,每个测试函数都会调⽤⼀次 fixture 。 scope="class" 时,在同⼀个测试类中, fixture只会在类中的第⼀个测试函数开始前执⾏⼀次,并在类中的最后⼀个测试函数结束后执⾏清理。
• 当 scope="moudle" 、 scope="session" 时可⽤于实现全局的前后置应⽤,这⾥需要多个⽂件的配合conftest.py 和 @pytest.fixture 结合使⽤实现全局的前后置应⽤@pytest.fixture 与 conftest.py ⽂件结合使⽤,可以实现在多个测试模块( .py )⽂件中共享前后置操作,这种结合的⽅式使得可以在整个测试项⽬中定义和维护通⽤的前后置逻辑,使测试代码更加模块化和可维护。
规则:
• conftest.py 是⼀个单独存放的夹具配置⽂件,名称是固定的不能修改
• 你可以在项⽬中的不同⽬录下创建多个 conftest.py ⽂件,每个 conftest.py ⽂件都会对其所在⽬录及其⼦⽬录下的测试模块⽣效
• 在不同模块的测试中需要⽤到 conftest.py 的前后置功能时,不需要做任何的import导⼊操作
• 作⽤:可以在不同的 .py ⽂件中使⽤同⼀个 fixture 函数
的不同⽬录下创建多个 conftest.py ⽂件,每个 conftest.py ⽂件都会对其所在⽬录及其⼦⽬录下的测试模块⽣效
• 在不同模块的测试中需要⽤到 conftest.py 的前后置功能时,不需要做任何的import导⼊操作
• 作⽤:可以在不同的 .py ⽂件中使⽤同⼀个 fixture 函数
如果测试场景主要涉及简单的参数传递,且不需要复杂的资源管理,建议使⽤ parametrize,因为它更简单直接;如果测试需要动态加载外部数据,或者需要管理复杂的测试资源(如数据库连接、⽂件操作等),建议使⽤ fixture,在某些情况下,也可以结合使⽤ parametrize 和 fixture,以充分利⽤两者的优点。总结来说,parametrize 更适合简单场景,⽽ fixture 更适合需要动态数据和资源管理的复杂场景