Pytest Fixture 参数化
同学们大家好,这个章节我们来学习 pytest 中使用 fixture 实现参数化的用法。
简介
pytest 还支持参数化 fixture,即可以为一个 fixture 提供多个不同的值,让多个测试用例使用不同的测试数据。
这样可以有效减少重复代码,尤其适合测试多组输入输出的情况。
其实我们前面已经学习过通过 pytest 提供的 parametrize 实现参数化的方法。不过 fixture 也是支持参数化的用法的,这意味着我们可以为一个 fixture 提供多个不同的值,来让多个测试用例使用不同的测试数据。这种方式的好处是能有效减少重复代码,特别适合在需要多组输入输出的情况下使用。例如,如果你有一个测试需要不同的数据库配置、不同的用户角色,或者其他多种不同的数据输入,通过参数化 fixture,你就可以一次性解决多个场景的测试,而不需要为每种情况编写多个类似的测试代码。下面来看看具体用法吧。
基本语法
params
:传入一个列表,包含 Fixture 的不同参数。request.param
:可以在 Fixture 函数中通过request.param
获取当前参数。
import pytest
@pytest.fixture(params=[param1, param2, param3, ...])
def fixture_name(request):
return request.param
要实现 fixture 的参数化,我们需要使用 params 这个参数。你可以传入一个包含不同测试数据的列表,pytest 会依次使用这些数据运行测试。在 fixture 函数中,我们可以通过 request点param 来获取当前正在使用的参数。这种方式让我们能够动态地获取不同的输入值并进行测试。比如在这个例子里,在 fixture 装饰器中使用 params 传入一个包含多个值的列表。这样,fixture 就会在每次测试时使用不同的参数。下面我们用几个例子分别介绍一下具体的用法。
单参数
import pytest
@pytest.fixture(params=[1, 2, 3])
def number(request):
return request.param
def test_number(number):
assert number > 0
首先来看看如果要把单个参数实现参数化需要怎么操作。来看一个简单的例子,假设我们想要测试一个数字是否大于 0,我们可以将数字作为 fixture 参数传递进去。这里,我们通过 params 参数给 number fixture 传入了 1、2 和 3。每次执行测试用例时,pytest 都会把其中一个数字传给 number,然后执行测试,验证它是否大于 0。
运行结果:
当运行测试时,pytest 会依次传入不同的参数,执行所有的测试。你会看到类似截图这样的结果。
多参数
import pytest
@pytest.fixture(params=[
["selenium", 123],
["appium", 123456]
])
def login(request):
print(f"用户名:{request.param}")
yield request.param
def test_demo(login):
print(f"demo case: 数据为: {login}")
除了单个参数外,pytest 还支持将多个参数一起传递给 fixture。如果你需要给一个测试用例传入更复杂的数据结构,比如一个包含多个值的列表,也可以轻松实现。在这个例子中,login fixture 会依次使用 selenium, 123 和 appium, 123456 这两组数据。测试函数 test demo 会使用这些数据来执行测试,确保每次测试都使用不同的输入。
运行结果:
执行测试用例,可以看到,测试的输出类似于这样。
fixture 与 parametrize 结合实现参数化
- 通过
parametrize
中设置indirect=True
可以将参数传递到指定的 Fixture 中
import pytest
@pytest.fixture
def database(request):
# database fixture 接收 request.param,返回数据库连接字符串。
db_name = request.param
return f"连接数据库: {db_name}"
# @pytest.mark.parametrize 使用 indirect=True 将参数传递给 database fixture
@pytest.mark.parametrize(
"database",
["test_db1", "test_db2"],
indirect=True
)
def test_database_connection(database):
print(f"database = {database}")
assert "连接数据库" in database
有时候,我们希望将测试参数传递给 fixture,这时就可以使用 pytest点mark点parametrize。通过 indirect等于True 参数,pytest 会把测试数据传递给对应的 fixture,而不是直接传给测试函数。例如,我们可以这样实现数据库连接的测试。在这个例子中,database fixture 接收了不同的数据库名称参数,并生成相应的数据库连接字符串。通过 indirect等于True,我们将测试数据传递给了 database fixture,而不是直接传递给 test database connection。
运行结果:
执行一下会看到类似这样的输出。通过这种方式,你可以将数据传递给 fixture,进一步实现更加灵活的测试。
下面给大家演示一下具体操作吧。进入项目之后,我们先来创建一个测试文件,比如说就叫做 test fixture params。然后我们先来定义一个测试方法,比如说需要 test number,那么在这个里面的话,我们需要去断言一下有一个叫做 number 的参数,它的值是大于 0 的,然后我们就需要把这个 number 参数给它传递进来,那在这里我们就来定义一个,比如说就叫 number 这样的一个 fixture。那这个 fixture 的话,我们先来把它的值传进来,我们就可以用 fixture 里面的 params,然后通过一个列表把数值给它组织进来。那然后的话在 fixture 方法当中,我们在这需要用到一个叫做 request,然后我们就可以在这个方法里面去把 request 里面的 param 返回来。那这样的话,当我们把这个 fixture 函数传入到这个测试方法里面去之后,实现一下看看。诶,这块儿的这个参数就会被自动的生成三条测试用例。
./assets/PytestFixture参数化.mp4
下面我们再来看一下多参数的一个场景,那比如说这边有个叫做 test demo,那这个 test demo 里面的话,比如说我们想要去获取一些数据,比如说我们的这个获取到的数据为,比如说我们这个到时候会打印一下它的这个数据,那它的这个数据从哪儿来呢?比如说我们在这边定义一个叫做 logging 的这样的一个 fixture 方法,方法上方用 @pytest点fixture 来指定这是个 fixture 方法。在这个f ixture 里面我们用 params 来指定一下需要传入的数据,然后如果是多个数据的话,在里面还需要再嵌套,比如说第一个我们知道它叫做 selenium,然后后面的这个数据,比如说是 1123。然后下面的这个的话,比如说我们给他指定一个 appium。然后再写几个数字,这样的话我们就有两组数据了,对不对?那然后同样的话,在方法参数列表中我们要把 request 给它传进去,那么传进去了之后的话,方法内部就可以访问到了。可以来打印一下,比如说打印这个用户名为传入的数据request点param。好,那然后的话在这儿我们也可以用 yield 的直接把我们这个 request点param 给它返回来。然后我们就把这个函数 fixture 函数传入到这个测试方法里面,那然后同样去打印一下我们的这个 fixture,来看看能拿到哪些数据。那然后的话我们就可以看到这边的这个命名,就是用我们这个 fixture 来命名的,那么第一个用户名是不是跟获取到的这个数字是一致的,对吧?那然后第二个我们的用户名是这个,对吧?获取到的数据也是这个,这样的话就完成了一个多参数的一个传递。
./assets/PytestFixture参数化.mp4
然后的话我们再来看一下这个 fixture 和 params 的结合。那比如说现在我先来定义一个测试函数叫 test database connection。然后在这个方法里面可能我们要去这个打印一下我们的这个数据库的一个信息,那数据库的信息的话就是待会我们要传入的那个 fixture。然后的话,嗯,我们比如说我们要去断言一下某一个数据,在我们拿到的这样的一个数据里。好,那这个数据在哪里呢?我们就需要通过一个 fixture 来给它进行一个指定啊。那比如说我们来定义一个就叫做 database 这样的一个fixture 方法,那然后的话我们在这边就可以通过 @pytest点fixture() 把它定义为成是一个 fixture 函数。然后同样要把我们的这个 request 给它传进来。那么这样的话,其实我们就比如说我们的这个数据库的名称,那我们就可以用 request点param 来指定,对吧?然后用 return 把我们的这个,比如说我们指定为连接数据库,对吧?然后的话把我们的这个 db name 给它返回去啊。好,那这样的话我们就定义好了一个 fixture 的这样的一个方法。那然后的话我们在这个里面就可以直接的把我们这个 database 给它传入进来。那么传入进来之后,那我们在这边的话就打印一下 database 的这个值。这样就可以去看一下我们的这个连接数据库的这个内容,在没在我们拿到的这个数据里。那具体的数据我们从哪拿呢?就可以用我们的这个 @pytest点mark点parametrize,那这个数据的话其实就是我们要传到 fixture 中的,对吧?我们先把 parametrize 中需要的参数传入进来,比如说数据库名称叫做 test db1,那么传完两个数据之后,最主要的是把这个 indirect 把它设置为 true,那这样的话我们就可以去结合我们的这个 fixture,然后具体的数据用 params 来给它传递。下面我们来执行一下看看。哎,执行完了之后,大家可以看到我们连接数据库这块儿,是不是哎?是可以看到对应的这个数据的,对吧?
./assets/PytestFixture参数化.mp4
总结
- Pytest Fixture 参数化的使用。
好了,关于使用 fixture 实现参数化的用法就先介绍到这里。