pytest.mark.parametrize參數(shù)詳解

常用參數(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

  1. argvalues可以傳入列表阵翎,嵌套了元組的列表,字典东囚,字符串
  2. 傳入多個值時跺嗽,測試用例就會被執(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

  1. indirect一般與Pytest的request啥刻,fixture組合使用
  2. 當(dāng)indirect為True時奸鸯,argnames則要傳入fixture函數(shù)名稱,不再是一個普通參數(shù)可帽,而是要被調(diào)用的fixture函數(shù)娄涩,argvalues則是要給這個函數(shù)傳的值
  3. 做法其實與@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ù)

  1. scope的作用范圍取值與fixture一致岭洲,當(dāng)indirect=True才被使用
  2. 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)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侥锦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子德挣,更是在濱河造成了極大的恐慌恭垦,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異番挺,居然都是意外死亡唠帝,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門玄柏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來襟衰,“玉大人,你說我怎么就攤上這事粪摘∑偕梗” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵徘意,是天一觀的道長苔悦。 經(jīng)常有香客問我,道長椎咧,這世上最難降的妖魔是什么玖详? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮勤讽,結(jié)果婚禮上蟋座,老公的妹妹穿的比我還像新娘。我一直安慰自己地技,他們只是感情好蜈七,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布秒拔。 她就那樣靜靜地躺著莫矗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪砂缩。 梳的紋絲不亂的頭發(fā)上作谚,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機(jī)與錄音庵芭,去河邊找鬼妹懒。 笑死,一個胖子當(dāng)著我的面吹牛双吆,可吹牛的內(nèi)容都是我干的眨唬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼好乐,長吁一口氣:“原來是場噩夢啊……” “哼匾竿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔚万,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤岭妖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昵慌,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡假夺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了斋攀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片已卷。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖淳蔼,靈堂內(nèi)的尸體忽然破棺而出悼尾,到底是詐尸還是另有隱情,我是刑警寧澤肖方,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布闺魏,位于F島的核電站,受9級特大地震影響俯画,放射性物質(zhì)發(fā)生泄漏析桥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一艰垂、第九天 我趴在偏房一處隱蔽的房頂上張望泡仗。 院中可真熱鬧,春花似錦猜憎、人聲如沸娩怎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽截亦。三九已至,卻和暖如春柬讨,著一層夾襖步出監(jiān)牢的瞬間崩瓤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工踩官, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留却桶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓蔗牡,卻偏偏與公主長得像颖系,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辩越,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容