常用參數(shù)分析:
一. 參數(shù)名argnames和參數(shù)值argvalues:
二. ids: 用例的ID垄提,標(biāo)識每一個測試用例陡蝇,ids的長度需與測試數(shù)據(jù)列表長度一致
三. scope:作用范圍
四. indirect:為True時析孽,傳入函數(shù)
五. 與mark一起使用
一. 參數(shù)名argnames和參數(shù)值argvalues:
單個argnames,單個argvalues
#測試用例文件test_parametrize.py
import pytest
class TestParametrize:
@pytest.mark.parametrize('testdata', [1])
def test_parametrize(self, testdata):
print("測試數(shù)據(jù)是:{}".format(testdata))
運(yùn)行結(jié)果
collected 1 item
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize[1] 測試數(shù)據(jù)是:1
PASSED
單個argnames适荣,多個argvalues
- argvalues可以傳入列表阵翎,嵌套了元組的列表,字典东囚,字符串
- 傳入多個值時跺嗽,測試用例就會被執(zhí)行多次,每次取一個值運(yùn)行
import pytest
data_1 = (
{'arg1': 1, 'arg2': 2},
{'arg1': 3, 'arg2': 4}
)
class TestParametrize:
@pytest.mark.parametrize('value', data_1)
def test_parametrize_1(self, value):
print('測試函數(shù)1页藻,測試數(shù)據(jù)為{}-{}'.format(value['arg1'], value['arg2']))
執(zhí)行結(jié)果
collected 2 items
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value0] 測試函數(shù)1桨嫁,測試數(shù)據(jù)為1-2
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value1] 測試函數(shù)1,測試數(shù)據(jù)為3-4
PASSED
多個argnames份帐,多個argvalues
argnames參數(shù)個數(shù)璃吧,必須和argvalues的每一組的個數(shù)一致,否則報錯
import pytest
class TestParametrize:
@pytest.mark.parametrize("test_input, expected", [("3 + 5", 8), ("2 + 4", 6), ("6 * 9", 54)])
def test_eval(self, test_input, expected):
print(f"測試數(shù)據(jù){test_input},期望結(jié)構(gòu){expected}")
assert eval(test_input) == expected
執(zhí)行結(jié)果如下:
parametrizetests/test_parametrize.py::TestParametrize::test_eval[3 + 5-8] 測試數(shù)據(jù)3 + 5,期望結(jié)構(gòu)8
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_eval[2 + 4-6] 測試數(shù)據(jù)2 + 4,期望結(jié)構(gòu)6
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_eval[6 * 9-54] 測試數(shù)據(jù)6 * 9,期望結(jié)構(gòu)54
PASSED
當(dāng)裝飾器裝飾類時废境,會將數(shù)據(jù)集傳遞給所有測試用例方法
import pytest
data_1 = [(1, 2, 3), (2, 4, 6)]
@pytest.mark.parametrize('a, b, expect', data_1)
class TestParametrize:
def test_parametrize_1(self, a, b, expect):
print('測試函數(shù)1畜挨,測試數(shù)據(jù)為{}-{}-{}'.format(a, b, expect))
assert a + b == expect
def test_parametrize_2(self, a, b, expect):
print('測試函數(shù)2,測試數(shù)據(jù)為{}-{}-{}'.format(a, b, expect))
assert a + b == expect
測試結(jié)果
collected 4 items
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[1-2-3] 測試函數(shù)1噩凹,測試數(shù)據(jù)為1-2-3
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[2-4-6] 測試函數(shù)1巴元,測試數(shù)據(jù)為2-4-6
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_2[1-2-3] 測試函數(shù)2,測試數(shù)據(jù)為1-2-3
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_2[2-4-6] 測試函數(shù)2驮宴,測試數(shù)據(jù)為2-4-6
PASSED
一個函數(shù)或者一個類可以裝飾多個@pytest.mark.parametrize
如下代碼逮刨,參數(shù)a數(shù)據(jù)有3個,參數(shù)b數(shù)據(jù)有2個堵泽,所以最終的用例數(shù)有3x2=6條
import pytest
data_1 = [1, 2, 3]
data_2 = ['value1', 'value2']
class TestParametrize:
@pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(self, a, b):
print('測試函數(shù)1禀忆,測試數(shù)據(jù)為{}-{}'.format(a, b))
collected 6 items
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value1-1] 測試函數(shù)1臊旭,測試數(shù)據(jù)為1-value1
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value1-2] 測試函數(shù)1,測試數(shù)據(jù)為2-value1
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value1-3] 測試函數(shù)1箩退,測試數(shù)據(jù)為3-value1
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value2-1] 測試函數(shù)1离熏,測試數(shù)據(jù)為1-value2
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value2-2] 測試函數(shù)1,測試數(shù)據(jù)為2-value2
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_parametrize_1[value2-3] 測試函數(shù)1戴涝,測試數(shù)據(jù)為3-value2
PASSED
二. ids參數(shù)化別名滋戳,增加可讀性
import pytest
data1 = [
(1, 2, 3),
(4, 5, 6)
]
ids = ["a:{} + b:{} = except:{}".format(a, b, expect) for a, b, expect in data1]
class TestParametrize:
@pytest.mark.parametrize("a, b, expected", data1, ids=ids)
def test_eval(self, a, b, expected):
print(f"測試數(shù)據(jù){a}+,期望結(jié)果{expected}")
執(zhí)行結(jié)果
collected 2 items
parametrizetests/test_parametrize.py::TestParametrize::test_eval[a:1 + b:2 = except:3] 測試數(shù)據(jù)1+2,期望結(jié)果3
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_eval[a:4 + b:5 = except:6] 測試數(shù)據(jù)4+5,期望結(jié)果6
PASSED
三. indirect
- indirect一般與Pytest的request啥刻,fixture組合使用
- 當(dāng)indirect為True時奸鸯,argnames則要傳入fixture函數(shù)名稱,不再是一個普通參數(shù)可帽,而是要被調(diào)用的fixture函數(shù)娄涩,argvalues則是要給這個函數(shù)傳的值
- 做法其實與@pytest.fixture(params)一樣,但使用了@pytest.mark.parametrize相當(dāng)于參數(shù)化了fixture映跟,而不是只有固定的一套數(shù)據(jù)傳入使用
單fixture單值
# conftest.py文件
import pytest
@pytest.fixture(scope="function", autouse=True)
def indirect_demo(request):
user = request.param
print("傳入的用戶名為:{}".format(user))
yield user
#測試用例文件test_parametrize.py
import pytest
user = ['張三', '李四']
class TestParametrize:
@pytest.mark.parametrize('indirect_demo', user, indirect=True)
def test_indirect_demo(self, indirect_demo):
print("測試數(shù)據(jù)用戶是:{}".format(indirect_demo))
運(yùn)行結(jié)果
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[\u5f20\u4e09] 傳入的用戶名為:張三
測試數(shù)據(jù)用戶是:張三
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[\u674e\u56db] 傳入的用戶名為:李四
測試數(shù)據(jù)用戶是:李四
PASSED
單fixture多值
# conftest.py文件
import pytest
@pytest.fixture(scope="function", autouse=True)
def indirect_demo2(request):
user = request.param
print("傳入的用戶名為:{}, 密碼為{}".format(user['user'], user['pwd']))
yield user
#測試用例文件test_parametrize.py
import pytest
userinfo = [
{'user': '張三', 'pwd': 123},
{'user': '李四', 'pwd': 456}
]
class TestParametrize:
@pytest.mark.parametrize('indirect_demo2', userinfo, indirect=True)
def test_indirect_demo(self, indirect_demo2):
print("測試數(shù)據(jù)用戶名是:{}蓄拣,密碼是{}".format(indirect_demo2['user'], indirect_demo2['pwd']))
運(yùn)行結(jié)果
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[indirect_demo20] 傳入的用戶名為:張三, 密碼為123
測試數(shù)據(jù)用戶名是:張三,密碼是123
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[indirect_demo21] 傳入的用戶名為:李四, 密碼為456
測試數(shù)據(jù)用戶名是:李四努隙,密碼是456
PASSED
傳入多個fixture值
# 開發(fā)時間:2023/11/1 14:23
# conftest.py文件
import pytest
@pytest.fixture(scope="function", autouse=True)
def indirect_demo3(request):
user = request.param
print("傳入的用戶名為:{}".format(user))
yield user
@pytest.fixture(scope="function", autouse=True)
def indirect_demo4(request):
pwd = request.param
print("傳入的密碼為{}".format(pwd))
yield pwd
# 開發(fā)時間:2023/11/6 11:33
#測試用例文件test_parametrize.py
import pytest
userinfo = [
('張三', 123),
('李四', 456)
]
class TestParametrize:
@pytest.mark.parametrize('indirect_demo3, indirect_demo4', userinfo, indirect=True)
def test_indirect_demo(self, indirect_demo3, indirect_demo4):
print("測試數(shù)據(jù)用戶名是:{}球恤,密碼是{}".format(indirect_demo3, indirect_demo4))
運(yùn)行結(jié)果
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[\u5f20\u4e09-123] 傳入的用戶名為:張三
傳入的密碼為123
測試數(shù)據(jù)用戶名是:張三,密碼是123
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[\u674e\u56db-456] 傳入的用戶名為:李四
傳入的密碼為456
測試數(shù)據(jù)用戶名是:李四荸镊,密碼是456
PASSED
疊加fixture
# 開發(fā)時間:2023/11/1 14:23
# conftest.py文件
import pytest
@pytest.fixture(scope="function", autouse=True)
def indirect_demo3(request):
user = request.param
print("傳入的用戶名為:{}".format(user))
yield user
@pytest.fixture(scope="function", autouse=True)
def indirect_demo4(request):
pwd = request.param
print("傳入的密碼為{}".format(pwd))
yield pwd
# 開發(fā)時間:2023/11/6 11:33
#測試用例文件test_parametrize.py
import pytest
user = ['張三', '李四']
pwd = [123, 456]
class TestParametrize:
@pytest.mark.parametrize('indirect_demo3', user, indirect=True)
@pytest.mark.parametrize('indirect_demo4', pwd, indirect=True)
def test_indirect_demo(self, indirect_demo3, indirect_demo4):
print("測試數(shù)據(jù)用戶名是:{}咽斧,密碼是{}".format(indirect_demo3, indirect_demo4))
運(yùn)行結(jié)果
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[123-\u5f20\u4e09] 傳入的用戶名為:張三
傳入的密碼為123
測試數(shù)據(jù)用戶名是:張三,密碼是123
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[123-\u674e\u56db] 傳入的用戶名為:李四
傳入的密碼為123
測試數(shù)據(jù)用戶名是:李四躬存,密碼是123
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[456-\u5f20\u4e09] 傳入的用戶名為:張三
傳入的密碼為456
測試數(shù)據(jù)用戶名是:張三张惹,密碼是456
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo[456-\u674e\u56db] 傳入的用戶名為:李四
傳入的密碼為456
測試數(shù)據(jù)用戶名是:李四,密碼是456
PASSED
四. scope參數(shù)
- scope的作用范圍取值與fixture一致岭洲,當(dāng)indirect=True才被使用
- scope的作用范圍取值會覆蓋fixture的scope范圍宛逗,如果同一個被調(diào)用的fixture有多個parametrize定義了scope,取第一條的范圍
# 開發(fā)時間:2023/11/1 14:23
# conftest.py文件
import pytest
@pytest.fixture(scope="function", autouse=True)
def indirect_demo3(request):
user = request.param
print("傳入的用戶名為:{}".format(user))
yield user
@pytest.fixture(scope="function", autouse=True)
def indirect_demo4(request):
pwd = request.param
print("傳入的密碼為{}".format(pwd))
yield pwd
# 開發(fā)時間:2023/11/6 11:33
#測試用例文件test_parametrize.py
import pytest
userinfo = [
('張三', 123)
]
ids = ["case{}".format(i) for i in range(len(userinfo))]
class TestParametrize:
@pytest.mark.parametrize('indirect_demo3, indirect_demo4', userinfo, indirect=True, ids=ids, scope='class')
def test_indirect_demo1(self, indirect_demo3, indirect_demo4):
print("測試數(shù)據(jù)用戶名是:{}钦椭,密碼是{}".format(indirect_demo3, indirect_demo4))
@pytest.mark.parametrize('indirect_demo3, indirect_demo4', userinfo, indirect=True, ids=ids, scope='function')
def test_indirect_demo2(self, indirect_demo3, indirect_demo4):
print("測試數(shù)據(jù)用戶名是:{}拧额,密碼是{}".format(indirect_demo3, indirect_demo4))
運(yùn)行結(jié)果
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo1[case0] 傳入的用戶名為:張三
傳入的密碼為123
測試數(shù)據(jù)用戶名是:張三,密碼是123
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_indirect_demo2[case0] 測試數(shù)據(jù)用戶名是:張三彪腔,密碼是123
PASSED
================= 2 passed in 0.02s =====================
五.與mark一起使用
class TestParametrize:
@pytest.mark.parametrize("test_input, expected", [
("3 + 5", 8),
("2 + 4", 6),
pytest.param("6 * 9", 54, marks=pytest.mark.xfail),
pytest.param("6 * 6", 36, marks=pytest.mark.skip)
])
def test_eval(self, test_input, expected):
print(f"測試數(shù)據(jù){test_input},期望結(jié)果{expected}")
執(zhí)行結(jié)果
collected 4 items
parametrizetests/test_parametrize.py::TestParametrize::test_eval[3 + 5-8] 測試數(shù)據(jù)3 + 5,期望結(jié)果8
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_eval[2 + 4-6] 測試數(shù)據(jù)2 + 4,期望結(jié)果6
PASSED
parametrizetests/test_parametrize.py::TestParametrize::test_eval[6 * 9-54] 測試數(shù)據(jù)6 * 9,期望結(jié)果54
XPASS
parametrizetests/test_parametrize.py::TestParametrize::test_eval[6 * 6-36] SKIPPED (unconditional skip)