一、前言
上节课我们讲解了如何用parametrize装饰器进行参数化,它有5个参数,argnames, argvalues, indirect, ids, scope,本节课针对这五个参数做详细讲解。
二、学习目标
1.argnames、argvalues参数实例讲解
2.indirect参数实例讲解
3.ids参数实例讲解
4.scope参数实例讲解
5.与其它mark一起使用
三、知识点
1.【argnames、argvalues参数实例讲解】
-
单参数单值
代码示例:
#测试用例文件test_XXX.py import pytest class TestCase(): @pytest.mark.parametrize('arg', [1]) #单参数单值,值必须是列表 def test_one_params(self,arg): print("传入的值:{}".format(arg))
运行效果:
test-demo7.py::TestCase::test_one_params[1] PASSED [100%]传入的值:1 ============================== 1 passed in 0.01s ==============================
-
单参数多值
1.单参数多值,argvalues可以传入多样的python数据类型:列表,嵌套了元组的列表,字典,字符串
2.传入多个值时,测试用例会被执行多次,每次取一个值去运行代码示例:
#测试用例文件test_XXX.py import pytest class TestCase(): @pytest.mark.parametrize('arg', ['abc',1,{'a':1,'b':3},(4,5)]) #值列表中传入了四组数据 def test_one_params(self,arg): print("传入的值:{}".format(arg))
运行效果:
test-demo7.py::TestCase::test_one_params[abc] PASSED [ 25%]传入的值:abc test-demo7.py::TestCase::test_one_params[1] PASSED [ 50%]传入的值:1 test-demo7.py::TestCase::test_one_params[arg2] PASSED [ 75%]传入的值:{'a': 1, 'b': 3} test-demo7.py::TestCase::test_one_params[arg3] PASSED [100%]传入的值:(4, 5) ============================== 4 passed in 0.02s ============================== #同一个测试用例分别用四组值执行了四遍
-
多参数多值
argnames参数的个数,必须要和argvalues的每一组的个数一致,否则报错。
代码示例:
#测试用例文件test_XXX.py import pytest @pytest.mark.parametrize("test_input,expected",[("3+5",8),("5-2",3),("5*2",10)])#test_input,expected分别对应每个元组中的两个值 def test_params(test_input,expected): print("原值:{} 期望值{}".format(test_input,expected)) assert eval(test_input) == expected
运行效果:
test-demo7.py::test_params[3+5-8] PASSED [ 33%]原值:3+5 期望值8 test-demo7.py::test_params[5-2-3] PASSED [ 66%]原值:5-2 期望值3 test-demo7.py::test_params[5*2-10] PASSED [100%]原值:5*2 期望值10 ============================== 3 passed in 0.02s ==============================
-
parametrize叠加使用:
代码示例:
#测试用例文件test_XXX.py import pytest @pytest.mark.parametrize("arg2",["a","b","c"]) @pytest.mark.parametrize("arg1",["1","2","3"]) def test_params(arg1,arg2): all = arg1 + arg2 print("叠加组合的值:{}".format(all))
运行效果:
test-demo7.py::test_params[1-a] PASSED [ 11%]叠加组合的值:1a test-demo7.py::test_params[1-b] PASSED [ 22%]叠加组合的值:1b test-demo7.py::test_params[1-c] PASSED [ 33%]叠加组合的值:1c test-demo7.py::test_params[2-a] PASSED [ 44%]叠加组合的值:2a test-demo7.py::test_params[2-b] PASSED [ 55%]叠加组合的值:2b test-demo7.py::test_params[2-c] PASSED [ 66%]叠加组合的值:2c test-demo7.py::test_params[3-a] PASSED [ 77%]叠加组合的值:3a test-demo7.py::test_params[3-b] PASSED [ 88%]叠加组合的值:3b test-demo7.py::test_params[3-c] PASSED [100%]叠加组合的值:3c ============================== 9 passed in 0.04s ==============================
2.【indirect参数实例讲解】
说明:
(一)indirect一般与Pytest的request、fixture组合使用。
(二)当indrect 为True时,argnames则要传入fixture函数名称,不再是一个普通参数,而是要被调用的fixture函数,argvalues则是要给这个函数传的值。
(三)作法其实与@pytest.fixture(params)一样,但使用了@pytest.mark.parametrize相当于参数化了fixture,而不是只有固定的一套数据传入使用。
-
单fixture单值(通过列表)
代码示例:
#conftest.py前置定义文件 import pytest @pytest.fixture() def indirect_demo(request): user = request.param print("传入的用户名为:{}".format(user)) yield user
#测试用例文件test_XXX.py import pytest user = ['张三','李四'] @pytest.mark.parametrize('indirect_demo',user,indirect=True) def test_one_param(indirect_demo): print("测试类的读到的用户是:{}".format(indirect_demo))
运行结果:
test-demo7.py::test_one_param[\u5f20\u4e09] 传入的用户名为:张三 PASSED [ 50%]测试类的读到的用户是:张三 test-demo7.py::test_one_param[\u674e\u56db] 传入的用户名为:李四 PASSED [100%]测试类的读到的用户是:李四 ============================== 2 passed in 0.02s ==============================
-
单fixture多值(通过字典)
代码示例:
#conftest.py前置定义文件 import pytest @pytest.fixture() def indirect_demo2(request): user = request.param print("传入的用户名为:{},密码为:{}".format(user['user'],user['pwd'])) yield user
#测试用例文件test_XXX.py import pytest userinfo = [ {'user':'张三','pwd':123}, {'user':'李四','pwd':456} ] @pytest.mark.parametrize('indirect_demo2',userinfo,indirect=True) def test_one_param(indirect_demo2): print("测试类的读到的用户是:{} 密码是:{}".format(indirect_demo2['user'],indirect_demo2['pwd']))
运行结果:
test-demo7.py::test_one_param[indirect_demo20] 传入的用户名为:张三,密码为:123 PASSED [ 50%]测试类的读到的用户是:张三 密码是:123 test-demo7.py::test_one_param[indirect_demo21] 传入的用户名为:李四,密码为:456 PASSED [100%]测试类的读到的用户是:李四 密码是:456 ============================== 2 passed in 0.01s ==============================
-
传多fixture多值(通过嵌套元组的列表)
代码示例:
#conftest.py前置定义文件 import pytest @pytest.fixture() def indirect_demo3(request): user = request.param print("传入的用户名为:{}".format(user)) return user @pytest.fixture() def indirect_demo4(request): pwd = request.param print("传入的密码为:{}".format(pwd)) return pwd
#测试用例文件test_XXX.py import pytest userinfo = [ ('张三',123), ('李四','pwd') ] @pytest.mark.parametrize('indirect_demo3,indirect_demo4',userinfo,indirect=True) def test_one_param(indirect_demo3,indirect_demo4): print("测试类的读到的用户是:{} 密码是:{}".format(indirect_demo3,indirect_demo4))
运行结果:
test-demo7.py::test_one_param[\u5f20\u4e09-123] 传入的用户名为:张三 传入的密码为:123 PASSED [ 50%]测试类的读到的用户是:张三 密码是:123 test-demo7.py::test_one_param[\u674e\u56db-pwd] 传入的用户名为:李四 传入的密码为:pwd PASSED [100%]测试类的读到的用户是:李四 密码是:pwd ============================== 2 passed in 0.02s ==============================
-
叠加fixture(单值列表)
代码示例:
#conftest.py前置定义文件 import pytest @pytest.fixture() def indirect_demo3(request): user = request.param print("传入的用户名为:{}".format(user)) return user @pytest.fixture() def indirect_demo4(request): pwd = request.param print("传入的密码为:{}".format(pwd)) return pwd
#测试用例文件test_XXX.py import pytest user = ['张三','李四'] pwd = [124,345] @pytest.mark.parametrize('indirect_demo3',pwd,indirect=True) @pytest.mark.parametrize('indirect_demo4',user,indirect=True) def test_one_param(indirect_demo3,indirect_demo4): print("测试类的读到的用户是:{} 密码是:{}".format(indirect_demo3,indirect_demo4))
运行结果:
test-demo7.py::test_one_param[\u5f20\u4e09-124] 传入的用户名为:124 传入的密码为:张三 PASSED [ 25%]测试类的读到的用户是:124 密码是:张三 test-demo7.py::test_one_param[\u5f20\u4e09-345] 传入的用户名为:345 传入的密码为:张三 PASSED [ 50%]测试类的读到的用户是:345 密码是:张三 test-demo7.py::test_one_param[\u674e\u56db-124] 传入的用户名为:124 传入的密码为:李四 PASSED [ 75%]测试类的读到的用户是:124 密码是:李四 test-demo7.py::test_one_param[\u674e\u56db-345] 传入的用户名为:345 传入的密码为:李四 PASSED [100%]测试类的读到的用户是:345 密码是:李四 ============================== 4 passed in 0.03s ==============================
3.【ids参数实例讲解】
作用:标记子用例执行名称,增加可读性,中文需要转码
代码示例:
#测试用例文件test_XXX.py
import pytest
userinfo = [
('张三',123),
('李四','pwd')
]
ids = ["case{}".format(i) for i in range(len(userinfo))]
@pytest.mark.parametrize('indirect_demo3,indirect_demo4',userinfo,indirect=True,ids=ids)
def test_one_param(indirect_demo3,indirect_demo4):
print("测试类的读到的用户是:{} 密码是:{}".format(indirect_demo3,indirect_demo4))
运行效果:
test-demo7.py::test_one_param[case0] 传入的用户名为:张三 #【】内显示自定义的ids
传入的密码为:123
PASSED [ 50%]测试类的读到的用户是:张三 密码是:123
test-demo7.py::test_one_param[case1] 传入的用户名为:李四
传入的密码为:pwd
PASSED [100%]测试类的读到的用户是:李四 密码是:pwd
============================== 2 passed in 0.02s ==============================
4.【scope参数实例讲解】
- scope的作用范围取值与fixture scope一致,当indirect=True才会被使用。
- scope的作用范围会覆盖fixture的scope范围,如果同一个被调用的fixture有多个parametrize定义了scope,取第一条的范围。
代码示例:
#conftest.py前置定义文件
import pytest
@pytest.fixture(scope="function")
def indirect_demo3(request):
user = request.param
print("传入的用户名为:{}".format(user))
return user
@pytest.fixture(scope="function")
def indirect_demo4(request):
pwd = request.param
print("传入的密码为:{}".format(pwd))
return pwd
#测试用例文件test_XXX.py
import pytest
userinfo = [
('张三',123)
]
ids = ["case{}".format(i) for i in range(len(userinfo))]
class TestCase():
@pytest.mark.parametrize('indirect_demo3,indirect_demo4',userinfo,indirect=True,ids=ids,scope="class")
def test_one_param1(self,indirect_demo3,indirect_demo4):
print("测试类的读到的用户是:{} 密码是:{}".format(indirect_demo3,indirect_demo4))
@pytest.mark.parametrize('indirect_demo3,indirect_demo4',userinfo,indirect=True,ids=ids,scope="function")
def test_one_param2(self,indirect_demo3,indirect_demo4):
print("测试类的读到的用户是:{} 密码是:{}".format(indirect_demo3,indirect_demo4))
运行效果:
test-demo7.py::TestCase::test_one_param1[case0] 传入的用户名为:张三
传入的密码为:123
PASSED [ 50%]测试类的读到的用户是:张三 密码是:123
test-demo7.py::TestCase::test_one_param2[case0] PASSED [100%]测试类的读到的用户是:张三 密码是:123
============================== 2 passed in 0.02s ==============================
#前置函数的作用范围被重新定义,原来是function,用例是class。但是第二个测试用例还是class。因为两个测试用例都修改了同一个前置,以第一个为准。
5.【 与其它mark一起使用】
代码示例:
#测试用例文件test_XXX.py
import pytest
a = '跳过'
@pytest.mark.parametrize("x,y",
[('test1',123456),
pytest.param("test1",123456,marks=pytest.mark.xfail),
pytest.param("test1",123456,marks=pytest.mark.xfail),
pytest.param("test2",123456,marks=pytest.mark.skip("跳过这条用例")),
pytest.param("test3",123456,marks=pytest.mark.skipif(a =='跳过',reason="有条件的跳过"))
]
)
def test_one(x,y):
assert x== 'test1'
assert y == 123456
运行效果:
test-demo7.py::test_one[test1-1234560] PASSED [ 20%]
test-demo7.py::test_one[test1-1234561] XPASS [ 40%]
test-demo7.py::test_one[test1-1234562] XPASS [ 60%]
test-demo7.py::test_one[test2-123456] SKIPPED [ 80%]
Skipped: 跳过这条用例
test-demo7.py::test_one[test3-123456] SKIPPED [100%]
Skipped: 有条件的跳过
=================== 1 passed, 2 skipped, 2 xpassed in 0.02s ===================
标签:parametrize,py,pytest,Pytest,参数,demo7,PASSED,test,indirect
From: https://www.cnblogs.com/ckxingchen/p/17057169.html