遇一山,过一山,处处有风景;只要勇敢向前,一路尽是繁花盛开。 | (点击查看→)【测试干货】python/java自动化、持续集成、性能、测开、简历、笔试面试等

pytest简易教程(13):parametrize参数化

 

pytest简易教程汇总,详见https://www.cnblogs.com/uncleyong/p/17982846

关于parametrize参数化

之前我们分享了通过fixture返回值实现参数化(详见:https://www.cnblogs.com/uncleyong/p/17957896

今天我们分享parametrize参数化,也就是在测试函数/测试类进行参数化

parametrize是一个内置标记,在命令pytest --markers结果中可以看到@pytest.mark.parametrize(argnames, argvalues)

 

源码

    class _ParametrizeMarkDecorator(MarkDecorator):
        def __call__(  # type: ignore[override]
            self,
            argnames: Union[str, Sequence[str]],
            argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
            *,
            indirect: Union[bool, Sequence[str]] = ...,
            ids: Optional[
                Union[
                    Iterable[Union[None, str, float, int, bool]],
                    Callable[[Any], Optional[object]],
                ]
            ] = ...,
            scope: Optional[_ScopeName] = ...,
        ) -> MarkDecorator:
            ...

   


方法:parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)

 

常用参数:

  • argnames:参数名,格式为:"arg1,arg2,arg3,...",通过逗号分隔多个参数
多参数写法汇总:参数名可以是字符串、元组、列表、字符串放元组中

@pytest.mark.parametrize("input,expected", [("1+1", 2), ("2-4", -2), ("2*3", 6)])

@pytest.mark.parametrize(("input","expected"), [("1+1", 2), ("2-4", -2), ("2*3", 6)])

@pytest.mark.parametrize(["input","expected"], [("1+1", 2), ("2-4", -2), ("2*3", 6)])

@pytest.mark.parametrize(("input,expected"), [("1+1", 2), ("2-4", -2), ("2*3", 6)])

 

  • argvalues:参数对应值,类型必须为list

    当参数为一个时格式:[v1]
    当参数个数大于一个时,格式为:[(v1_1, v2_1, ...), (v1_2, v2_2, ...)],一组参数值放元组或者列表中,也就是说,最外层列表可以嵌套元组或者列表

@pytest.mark.parametrize("name,technology",[['韧','测试开发'],['全栈测试笔记','性能测试']])  # 列表嵌列表

@pytest.mark.parametrize("name,technology",[('韧','测试开发'),('全栈测试笔记','性能测试')])  # 列表嵌套元组

 

  • indirect:默认是False,如果设置成True,表示把被parametrize修饰器修饰的方法形参当函数执行(parametrize中参数名和这个形参同名),同时,必须有这个函数,且被@pytest.fixture()修饰,否则报错:fixture 'xxx' not found,xxx表示形参名
  • ids:用例id,用于标识用例,增加可读性(测试结果中会展示id),是字符串列表,ids的长度要与测试数据列表长度一致

  
使用方法:
  1、@pytest.mark.parametrize(argnames, argvalues)可以修饰函数、方法、测试类

  2、修饰测试类时,会将测试数据传给此类下所有测试方法

  3、函数、方法、测试类上可以加多个参数化修饰器

  4、如果只有一个修饰器,参数值为N个(也就是列表长度),测试方法就会运行N次

  5、如果多个修饰器,参数个数分别是X、Y、Z,会运行X*Y*Z次  

 

单个参数的参数化

测试方法形参名要和parametrize里面的参数一样

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest

@pytest.mark.parametrize("data",['韧','全栈测试笔记','性能测试','自动化测试','测试开发'])
class TestQzcsbj:
    def test_case(self, data):
        print(f"data={data}")

 

结果:

 

多个参数的参数化

参数放列表中,且列表嵌套元组或者列表

示例一:修饰器放函数上,参数值是基本类型

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest
@pytest.mark.parametrize("input,expected", [("1+1", 2), ("2-4", -2), ("2*3", 6)])
def test_eval(input, expected):
    assert eval(input) == expected

  

结果:

 

示例二:修饰器放函数上,参数值是字典

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest

data = [
    {
        "input": "1+1",
        "expected": 2
    },
    {
        "input": "2-4",
        "expected": -2
    },
    {
        "input": "2*3",
        "expected": 6
    }
]
@pytest.mark.parametrize("par", data)
def test_eval(par):
    print(f"本次入参是:input={par['input']}, expected={par['expected']}")
    assert eval(par['input']) == par['expected']

  

结果:

 

示例三:修饰器放测试类上

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest


# @pytest.mark.parametrize("name,technology",[['韧','测试开发'],['全栈测试笔记','性能测试']])  # 列表嵌列表
@pytest.mark.parametrize("name,technology",[('韧','测试开发'),('全栈测试笔记','性能测试')])  # 列表嵌套元组
class TestQzcsbj:
    def test_case(self, name, technology):
        print(f"name={name}, technology={technology}")

 

结果:  

 

示例四:测试类下多个方法,会将测试数据传给此类下所有测试方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest


# @pytest.mark.parametrize("name,technology",[['韧','测试开发'],['全栈测试笔记','性能测试']])  # 列表嵌列表
@pytest.mark.parametrize("name,technology",[('韧','测试开发'),('全栈测试笔记','性能测试')])  # 列表嵌套元组
class TestQzcsbj:
    def test_case(self, name, technology):
        print(f"test_case: name={name}, technology={technology}")

    def test_case2(self, name, technology):
        print(f"test_case2: name={name}, technology={technology}")

  

结果:

 

参数放变量中

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest

data = [('韧','测试开发'),('全栈测试笔记','性能测试')]
@pytest.mark.parametrize("name,technology",data)
class TestQzcsbj:
    def test_case(self, name, technology):
        print(f"name={name}, technology={technology}")

  

结果:

 

调用函数获取参数数据

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest


def get_data():
    return [('韧','测试开发'),('全栈测试笔记','性能测试')]

@pytest.mark.parametrize("name,technology",get_data())
class TestQzcsbj:
    def test_case(self, name, technology):
        print(f"name={name}, technology={technology}")

  

结果:

 

mark标记参数

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest


@pytest.mark.parametrize(
    "input,expected",
    [
        ("1+1", 2),
        pytest.param("2-4", -2, marks=[pytest.mark.minus, pytest.mark.xfail], id="input:2-4"),
        pytest.param("2*3", 6, marks=[pytest.mark.multiplication, pytest.mark.skip], id="input:2*3"),
        pytest.param("4/2", 2, marks=pytest.mark.division, id="input:4/2")
    ]
)
def test_eval(input, expected):
    assert eval(input) == expected

  

添加配置

[pytest]
addopts = -s --strict-markers
markers =
    minus
    multiplication
    division

  

结果:

 

只执行某个标记的参数:pytest case\test_qzcsbj.py -vs -m division

 

笛卡尔积:多个parametrize参数化修饰器

应用场景:比如注册接口,考虑不同入参的组合

示例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest
@pytest.mark.parametrize("username",["qzcsbj","ren","jack"])
@pytest.mark.parametrize("password",["a123","abc123","ABC123"])
class TestQzcsbj:
    def test_case(self, username, password):
        print(f"name={username}, technology={password}")

  

结果:运行9次

 

笛卡尔积:parametrize与fixture混合

注意:此时fixture修饰器中有params参数

示例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/

import pytest

@pytest.fixture(params=["qzcsbj","ren","jack"])
def fun(request):
    return request.param
@pytest.mark.parametrize("password", ["a123","abc123","ABC123"])
def test_case(fun, password):
    print(f"name={fun}, password={password}")

  

结果:

 

posted @ 2024-02-23 21:36  全栈测试笔记  阅读(235)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end