一、参数化简介

pytest允许在多个级别启用测试参数化:

  • @pytest.mark.parametrize 允许在测试函数或类中定义多组参数和fixtures
  • @pytest.fixture() 允许fixture有参数化功能
  • pytest_generate_tests 允许定义自定义参数化方案或扩展(拓展)

二、@pytest.mark.parametrize

有这样一个场景,登录的测试用例,共同的特点是,它们测试步骤是一模一样的,只是输入的数据(用户名、密码)不同,要检查的输出数据(错误提示)不同。这批测试用例,就是典型的 可以用 数据驱动相同的测试步骤测试参数数据不同分离 开来,以后增加新的测试用例,只需要修改数据。这就是数据驱动。

这种情况可以使用 pytest 用例 的 数据驱动格式,只需如下定义即可:

import pytest

def login(username,password):
    if username == "zhangwuj" and password == "123456":
        return "登录成功"
    else:
        return "用户名或者密码错误"

class Test_pass03:
    @pytest.mark.parametrize('username, password, expectedalert', [
        ('lisi', '88888888', '请输入用户名'),
        ('zhangsan', None, '请输入密码')
    ])
    def test_UI_0005(self, username, password, expectedalert):
        alertText = login(username, password)
        assert alertText == expectedalert

这样,我们就不需要定义那么多的测试用例方法了, 而且测试数据也可以集中存放。参考pytest官方文档,之后结果如下:

测试用例参数化_测试用例

三、fixture 传参数 request

为了提高复用性,在编写测试用例的时候,会用到不同的fixture,比如:项目中的登录操作,大部分的用例的前置条件都是登录,假设不同的用例想登录不同的测试账号,那么登录fixture就不能把账号写死,需要通过传参的方式来完成登录操作

3.1.传单个参数

准备test_case16.py,代码如下:

import pytest

@pytest.fixture()
def login(request):
    """
    将函数 login 标记为一个 Pytest fixture。Pytest fixture 是一个用于提供测试数据或测试环境的函数或方法。在此处,login 是一个 fixture,将在每次测试调用之前运行。
    :param request: 是一个特殊的 fixture 参数,它代表当前测试用例的请求对象。可以通过该对象获取测试用例参数和其他信息。
    :return:
    """
    # 获取参数:获取测试用例参数的值。在 @pytest.mark.parametrize 注解中,通过 data 列表传递的每个值都会依次赋给 request.param
    name = request.param
    print(f"*************本次登录用户名{name}*************")
    # 测试用例参数 name 作为 fixture 的返回值
    return name


data = ["张三", "李四"]
ids = [f"login name is:{name}" for name in data]

# "login":这是测试用例的参数名。
# data:这是一个包含测试用例参数的列表,用于参数化测试。每个测试用例都会按顺序取值。
# ids=ids:这是一个包含参数标识的列表,用于在测试报告中显示可读性更高的标识。
# indirect=True:这个参数的值为 True,表明 login 参数是一个 fixture。
@pytest.mark.parametrize("login", data, ids=ids, indirect=True)
# login 参数将会从 login fixture 中获取值
def test_order(login):
    print(f"本次登录的账户是:{login}")
    assert login == "李四"

执行结果如下:

测试用例参数化_用例_02

注意:

  • 添加 indirect=True 参数是为了把 login 当成一个函数去执行,而不是一个参数,并且将data当做参数传入函数
  • def test_name(login) ,这里的login是获取fixture返回的值

3.2.多个参数

传入多个参数,准备代码如下:

import pytest

@pytest.fixture()
def logins(request):
    params = request.param
    # 多个参数传入的是字典,也要通过键获取值
    print(f"账户是:{params['username']},密码是:{params['password']}")
    return params

# 准备参数化的数据,多个参数需要以字典的形式传入
data = [{"username": "Augus", "password": "123321"}, {"username": "ls", "password": "123456"}]

@pytest.mark.parametrize("logins", data, indirect=True)
def test_user_login(logins):
    print(f"账户是:{logins['username']},密码是:{logins['password']}")

执行结果如下:

测试用例参数化_参数化_03

 注意:如果需要传多个参数,需要通过字典去传

3.3.多个fixture(只加一个装饰器)推荐使用

可以使用多个fixtrue处理多个参数,只用一个装饰器给用例设置,代码如下:

import pytest

# 处理账户
@pytest.fixture()
def logins_username(request):
    username = request.param
    # 多个参数传入的是字典,也要通过键获取值
    print(f"账户是:{username}")
    return username

# 处理密码
@pytest.fixture()
def logins_password(request):
    password = request.param
    # 多个参数传入的是字典,也要通过键获取值
    print(f"密码是:{password}")
    return password

# 准备参数化的数据
data = [("Augus", "123321"), ("ls", "123456")]


@pytest.mark.parametrize("logins_username, logins_password", data, indirect=True)
def test_user_login(logins_username, logins_password):
    print(f"账户是:{logins_username},密码是:{logins_password}")

代码执行如下:

测试用例参数化_用例_04

3.4.多个fixture(叠加装饰器)

可以使用多个fixtrue处理多个参数,用多个装饰器给用例设置,代码如下:

import pytest

# 处理账户
@pytest.fixture()
def logins_username(request):
    username = request.param
    # 多个参数传入的是字典,也要通过键获取值
    print(f"账户是:{username}")
    return username

# 处理密码
@pytest.fixture()
def logins_password(request):
    password = request.param
    # 多个参数传入的是字典,也要通过键获取值
    print(f"密码是:{password}")
    return password

# 准备参数化的数据,多个参数需要以字典的形式传入
name = ["Augus", "ls"]
pwd = ["123321", "123456"]

@pytest.mark.parametrize("logins_username", name, indirect=True)
@pytest.mark.parametrize("logins_password", pwd, indirect=True)
def test_user_login(logins_username, logins_password):
    print(f"账户是:{logins_username},密码是:{logins_password}")

执行结果如下:

测试用例参数化_参数化_05

 注意:

  测试用例数=2*2,共有4条,根据数据算