• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Pytest.参数化

武飞扬头像
译远
帮助3

参数化在自动化测试里算是一个耳熟能详的概念了,那么pytest框架是怎么应用它的呢?之前在pytest.fixture脚手架一文中有说过fixture的构造有params,这个也可以起到参数化的作用。本文讲的是ParametrizeMarkDecorator装饰器。
举个最简单的例子,格式如下:

参数化的一个好处是,每条用例都是独立的,单独运行的,第一条报错,不会影响第二条的运行。

import pytest


@pytest.mark.parametrize("test_input", ["1 2", "2-1"])
def test_eval(test_input):
    assert eval(test_input) == 3

学新通

参数化的另外一个好处是,可以一个参数,也可以多个参数。

import pytest


@pytest.mark.parametrize("test_input,expected", [
    ["1 2", 3],
    ["2-1", 2],
])
def test_eval(test_input, expected):
    assert eval(test_input) == expected

学新通
如果入参很多,是一个多参数的json,dict等等,会导致测试代码不整洁。比如:

import pytest


@pytest.mark.parametrize("test_input, expected", [
    [{"username": "test1", "password": "123"}, {"resCode": 200, "message": "login success"}],
    [{"username": "test1", "password": ""}, {"resCode": 200, "message": "用户名或密码错误!"}],
    [{"username": "", "password": "123"}, {"resCode": 200, "message": "用户名或密码错误!"}],
    [{"username": "", "password": ""}, {"resCode": 200, "message": "用户名或密码错误!"}],
    [{"username": "test1", "password": "321"}, {"resCode": 200, "message": "用户名或密码错误!"}],
])
def test_login(test_input, expected):
    ...  # 断言

如果这个py文件的用例很多,想去修改其中某个场景的入参或预期结果,这么找下去会很麻烦,如果改错用例还得去找。
那么我们是不是可以把这些输入输出隔离出来?
有人说只要在外部定一个变量即可。

import pytest


data = [
    [{"username": "test1", "password": "123"}, {"resCode": 200, "message": "login success"}],
    [{"username": "test1", "password": ""}, {"resCode": 200, "message": "用户名或密码错误!"}],
    [{"username": "", "password": "123"}, {"resCode": 200, "message": "用户名或密码错误!"}],
    [{"username": "", "password": ""}, {"resCode": 200, "message": "用户名或密码错误!"}],
    [{"username": "test1", "password": "321"}, {"resCode": 200, "message": "用户名或密码错误!"}],
]


@pytest.mark.parametrize("test_input, expected", data)
def test_login(test_input, expected):
    ...  # 断言

这么写也没问题,但还是在一个py文件里,并没有达到数据隔离的真正目的。
这里我们可以重写一个文件,看数据是什么格式的,我们可以在用例同级目录下新建一个json文件,把data按list格式直接复制过去就好。但是json文件规范,比如必须是双引号,如果你的测试data里是单引号,还需要转换一下。

json文件写好后,我们需要写一个方法取驱动用例来读取测试数据。这个公共方法就是读取所在路径下的把json类型转换成适配用例的dict或者list等等。
新建一个py文件,写一个公共方法:

import json


def read_json_data(file_path="data.json"):
    with open(file_path, "rb") as f:
        r = json.load(f)
    return r


if __name__ == '__main__':
    obj = read_json_data("data.json")
    print(obj)

测试用例里再引用这个公共方法即可读取json文件作为测试data了

import pytest
from apitest_dev.read_data import read_json_data

data = read_json_data("data.json")
# print(data)
# print(type(data))


@pytest.mark.parametrize("input_test, expected", data)
def test_login(input_test, expected):
    ...

这么看是不是更简洁明了,层次清晰?

如果测试数据格式用yaml,那么可以在这个公共方法py文件里再增加上读取yaml文件的方法即可。
代码如下:

def read_yaml_data(file_path="test_data.yml"):
    if not os.path.isfile(file_path):
        raise FileNotFoundError(f"文件{file_path}不存在,请检查文件名或路径是否正确")
    with open(file_path, "rb") as f:
        r = yaml.safe_load(f)
    return r

再说下mark标签的,如何选择性的执行case,发一串伪代码:

@pytest.mark.login
def test_login_1():
    ...


def test_login_2():
    ...


@pytest.mark.register
def test_register_1():
    ...


@pytest.mark.register
def test_register_2():
    ...
学新通

这里给每条用例做了标签,register的用例我都想执行,而login的用例只想执行login_1,mark标签按上面这么写。同时需要配置pytest.ini,不配ini会有warning提示:
学新通
pytest.ini配置这么写:

[pytest]


markers =
    login: login case
    register: register case

[pytest]表示这里都是pytest的配置,冒号后面的可以不写,相当于注释。但是login和register必须是换行的,否则无效。
最后执行用例py文件pytest -m “login"或者文件内部main执行pytest.main([”-s", “-m login”, “xx.py”]),也支持多个mark,这里不再赘述了。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhiebbhf
系列文章
更多 icon
同类精品
更多 icon
继续加载