參數(shù)化,就是把測試過程中的數(shù)據(jù)提取出來,通過參數(shù)傳遞不同的數(shù)據(jù)來驅(qū)動(dòng)用例運(yùn)行。其實(shí)也就是數(shù)據(jù)驅(qū)動(dòng)的概念。
在 Unittest 中,我們講過使用 ddt 庫配合 unittest 實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)。在 Pytest 中并不需要額外的庫,通過 pytest.mark.parametrize()即可實(shí)現(xiàn)參數(shù)化。
方法:
parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
常用參數(shù):
argnames:參數(shù)名
argvalues:參數(shù)對應(yīng)值,類型必須為list或元組
當(dāng)參數(shù)為一個(gè)時(shí)格式:[value]
當(dāng)參數(shù)個(gè)數(shù)大于一個(gè)時(shí),格式為:[(param_value1,param_value2.....),(param_value1,param_value2.....)]
ids:使用的數(shù)據(jù)組別名,類型必須為list或元組,與argvalues一一對應(yīng),用于使用的數(shù)據(jù)組的展示
使用方法:
@pytest.mark.parametrize(argnames,argvalues)
? 參數(shù)值為N個(gè),測試方法就會(huì)運(yùn)行N次
單個(gè)參數(shù)
在使用pytest.mark.parametrize()傳遞參數(shù)化數(shù)據(jù)時(shí),測試用例本身必須有參數(shù)。
測試用例的參數(shù)名必須要跟parametrize傳遞的參數(shù)名保持一致
import pytest
def add(a, b):
return a + b
# 單個(gè)參數(shù)的情況
@pytest.mark.parametrize('a', (1,2,3,4))
def test_add(a): # => 作為用例參數(shù),接收裝飾器傳入的數(shù)據(jù)
print('\na的值:', a)
assert add(a, 1) == a+1
if __name__ == '__main__':
pytest.main(["-s", "demo.py"])
輸出結(jié)果:
collected 4 items
demo.py
a的值: 1
.
a的值: 2
.
a的值: 3
.
a的值: 4
.
============================== 4 passed in 0.06s ==============================
注意用法,@pytest.mark.parametrize() 裝飾器接收兩個(gè)參數(shù),一個(gè)參數(shù)是以字符串的形式標(biāo)識用例函數(shù)的參數(shù),第二個(gè)參數(shù)以列表或元組的形式傳遞測試數(shù)據(jù)。

多個(gè)參數(shù)
多個(gè)參數(shù),@pytest.mark.parametrize()第一個(gè)參數(shù)依然是字符串, 對應(yīng)用例的多個(gè)參數(shù)用逗號分隔。第二個(gè)參數(shù)為一個(gè)二維的列表或者元組
import pytest
# 待測函數(shù)
def add(a, b):
return a + b
# 多個(gè)參數(shù)的情況
@pytest.mark.parametrize('a,b,c', ([1,2,3],[4,5,9],[7,8,15]))
def test_add(a,b,c): # => 作為用例參數(shù),接收裝飾器傳入的數(shù)據(jù)
print('\na,b,c的值分別為:', f"{a},,{c}")
assert add(a, b) == c
if __name__ == '__main__':
pytest.main(["-s", "demo.py","-v"])
執(zhí)行后輸出:
collecting ... collected 3 items
demo.py::test_add[1-2-3]
a,b,c的值分別為: 1,2,3
PASSED
demo.py::test_add[4-5-9]
a,b,c的值分別為: 4,5,9
PASSED
demo.py::test_add[7-8-15]
a,b,c的值分別為: 7,8,15
PASSED
============================== 3 passed in 0.05s ==============================
對測試類參數(shù)化
以上例子我們是對單個(gè)的測試用例進(jìn)行了數(shù)據(jù)驅(qū)動(dòng),如果要對整個(gè)測試類操作,其實(shí)際上也是對類中的測試方法進(jìn)行參數(shù)化。類中的測試方法的參數(shù)必須與@pytest.mark.parametrize()中的標(biāo)識的參數(shù)個(gè)數(shù)一致且參數(shù)名相同。
每個(gè)測試用例都會(huì)循環(huán)執(zhí)行傳入?yún)?shù)的組數(shù)的次數(shù)
import pytest
def add(a, b):
return a + b
@pytest.mark.parametrize('a, b, c', ([1,2,3],[4,13,9],[7,8,15]))
class TestAbc():
def test_add1(self,a,b,c): # => 作為用例參數(shù),接收裝飾器傳入的數(shù)據(jù)
assert add(a, b) == c
def test_add2(self,a,b,c): # => 作為用例參數(shù),接收裝飾器傳入的數(shù)據(jù)
assert add(a, c) == b
def test_other(self,a,b,c):
print("\na,b的值分別為:",f"{a},")
if __name__ == '__main__':
pytest.main(["-s", "demo.py","-v"])
修改結(jié)果顯示名稱
通過上面的運(yùn)行結(jié)果,我們可以看到,為了區(qū)分參數(shù)化的運(yùn)行結(jié)果,在結(jié)果中都會(huì)顯示數(shù)據(jù)組合而成的名稱。
數(shù)據(jù)短小還好說,如果數(shù)據(jù)比較長而復(fù)雜的話,那么就會(huì)很難看。
@pytest.mark.parametrize() 還提供了第三個(gè) ids 參數(shù)來自定義顯示結(jié)果,數(shù)據(jù)格式為元組或者列表,與傳入的第二個(gè)參數(shù)一一對應(yīng),僅作展示所用。
test_add[1-2-3]這是結(jié)果中顯示的名稱,ids 的修改會(huì)作用于[]中的顯示。
我們下面的示例簡單的為數(shù)據(jù)編了一個(gè)號:
import pytest
def add(a, b):
return a + b
# ids 的作用
data = ([1,2,3],[4,13,9],[7,8,15])
ids = [f'datau0z1t8os' for d in range(len(data))] # => 生成與數(shù)據(jù)數(shù)量相同的名稱列表
# ids = ('data0','data1','data2')
@pytest.mark.parametrize('a, b, c', data, ids=ids)
def test_add1(a,b,c):
assert add(a, b) == c
if __name__ == '__main__':
pytest.main(["-s", "demo.py","-v"])
輸出結(jié)果:
demo.py::test_add1[data0] PASSED
demo.py::test_add1[data1] FAILED
demo.py::test_add1[data2] PASSED
================================== FAILURES ===================================
常用的測試用例管理方式
在進(jìn)行自動(dòng)化測試的時(shí)候,一般需要對數(shù)據(jù)進(jìn)行一個(gè)統(tǒng)籌規(guī)劃實(shí)現(xiàn)以用例數(shù)據(jù)驅(qū)動(dòng)框架進(jìn)行測試。
常見的有
excel存放
優(yōu)點(diǎn): 便于維護(hù),框架成型之后維護(hù)用例的人員沒有學(xué)習(xí)成本。
缺點(diǎn): 執(zhí)行效率低,且用例量級大的時(shí)候易卡頓。
yaml存放
優(yōu)點(diǎn): 便于維護(hù),輕便
缺點(diǎn): 學(xué)習(xí)成本,用例編寫設(shè)置不夠直觀
json存放
優(yōu)點(diǎn): 便于維護(hù),輕便
缺點(diǎn): 學(xué)習(xí)成本,用例編寫設(shè)置不夠直觀
類屬性存放
優(yōu)點(diǎn): 調(diào)用便利
缺點(diǎn): 學(xué)習(xí)成本