前言
我們在實際自動化測試中,某些測試用例是無法通過一組測試資料來達到驗證效果的,所以需要通過引數化來傳遞多組資料
在unittest中,我們可以使用第三方庫parameterized來對資料進行引數化,從而實現資料驅動測試
而在pytest中,也提供了功能強大的@pytest.mark.parametrize裝飾器來實現資料引數化
Pytest引數化的方式
pytest有三種傳參方式
@pytest.mark.parametrize()
通過裝飾器方式進行引數化(最常使用)pytest.fixture()
方式進行引數化,fixture
裝飾的函式可以作為引數傳入其他函式conftest.py
檔案中存放引數化函式,可作用於模組內的所有測試用例
@pytest.mark.parametrize實現引數化
裝飾測試類
當裝飾器 @pytest.mark.parametrize 裝飾測試類時,會將資料集合傳遞給類的所有測試用例方法
舉個?
import pytest
# 定義測試資料
data1 = [
(1, 2, 3),
(4, 5, 9)
]
# 定義add方法
def add(a, b):
return a + b
# 新增parametrize裝飾器
@pytest.mark.parametrize('a, b, expect', data1)
class TestParametrize(object):
def test_parametrize_1(self, a, b, expect):
print(f'\n測試用例1資料為{a}-{b},結果為{expect}')
assert add(a, b) == expect
def test_parametrize_2(self, a, b, expect):
print(f'\n測試用例2資料為{a}-{b},結果為{expect}')
assert add(a, b) == expect
執行結果如下
裝飾測試函式
單個資料
當測試用例只需要一個引數時,我們使用列表存放測試資料,例如定義一個列表
data = [1,2]
使用@pytest.mark.parametrize裝飾器時,第一個引數使用變數a接收列表中的每個元素,第二個引數傳遞儲存資料的列表
在測試用例中使用同名的變數a接收測試資料,列表有多少個元素就會生成並執行多少個測試用例
上程式碼
import pytest
data = [1, 2 , 3]
@pytest.mark.parametrize('a', data)
def test_parametrize(a):
print(f'\n被載入測試資料為{a}')
執行結果如下
一組資料
當測試用例需要多個資料時,我們可以使用巢狀序列(巢狀元組&巢狀列表)的列表來存放測試資料
裝飾器@pytest.mark.parametrize()可以使用單個變數接收資料,也可以使用多個變數接收,同樣,測試用例函式也需要與其保持一致
當使用單個變數接收時,測試資料傳遞到測試函式內部時為列表中的每一個元素或者小列表,需要使用索引的方式取得每個資料
當使用多個變數接收資料時,那麼每個變數分別接收小列表或元組中的每個元素
列表巢狀多少個列表或元組,測生成多少條測試用例
上程式碼
import pytest
data = [
[1, 2, 3],
[4, 5, 9]
]
@pytest.mark.parametrize('a, b, expect', data)
def test_parametrize_1(a, b, expect):
# 當使用多個變數接收資料時,那麼每個變數分別接收小列表或元組中的每個元素
print(f'\n測試資料為{a},{b},{expect}')
actual = a + b
assert actual == expect
@pytest.mark.parametrize('value', data)
def test_parametrize_2(value):
當使用單個變數接收時,測試資料傳遞到測試函式內部時為列表中的每一個元素或者小列表,需要使用索引的方式取得每個資料
print(f'\n測試資料為{value}')
actual = value[0] + value[1]
assert actual == value[2]
執行結果如下
組合資料
一個測試函式還可以同時被多個引數化裝飾器裝飾,多個裝飾器中的資料會進行交叉組合的方式傳遞給測試函式,進而生成n*n個測試用例,這也為我們的測試設計時提供了方便
上程式碼
import pytest
data_1 = [1, 2]
data_2 = [3, 4, 5]
@pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):
print(f'\n測試資料為{a},{b}')
執行結果如下
標記用例
當我們不想執行某組測試資料時,我們可以標記skip或skipif
當我們預期某組資料會執行失敗時,我們可以標記為xfail
上程式碼
import pytest
data1 = [
[1, 2, 3],
pytest.param(3, 4, 8, marks=pytest.mark.xfail),
pytest.param(3, 4, 7, marks=pytest.mark.skip)
]
def add(a, b):
return a + b
@pytest.mark.parametrize("a,b,expected", data1)
def test_mark(a, b, expected):
print(f'測試資料為{a},{b},結果為{expected}')
assert add(a, b) == expected
執行結果如下
巢狀字典
資料列表中也可以使用字典型別的資料
上程式碼
import pytest
data_1 = (
{
'user': 1,
'pwd': 2
},
{
'user': 3,
'pwd': 4
}
)
@pytest.mark.parametrize('dic', data_1)
def test_parametrize_1(dic):
print(f'測試資料為{dic}')
執行結果如下
增加可讀性
使用ids引數
引數化裝飾器有一個額外的引數ids,可以標識每一個測試用例,自定義測試資料結果的顯示,用來增加測試用例的可讀性
上程式碼
import pytest
data = [1, 2, 3]
ids = [f'TestData-{a}' for a in data]
@pytest.mark.parametrize('a', data ,ids= ids)
def test_parametrize(a):
print(f'\n被載入測試資料為 {a}')
執行結果為
自定義id做標識
除了使用ids引數增加輸出可讀性外,我們還可以在引數列表的引數旁邊定義一個id值來做標識
上程式碼
import pytest
data = [
pytest.param(1, id="this is test1"),
pytest.param(2, id="this is test2")
]
@pytest.mark.parametrize('a', data)
def test_parametrize(a):
print(f'\n被載入測試資料為 {a}')
執行結果如下
pytest.fixture()方式進行引數化
待更新