如果你還想從頭學起Pytest,可以看看這個系列的文章哦!
https://www.cnblogs.com/poloyy/category/1690628.html
前言
pytest允許在多個級別啟用測試參數化:
- pytest.fixture() 允許fixture有參數化功能(后面講解)
- @pytest.mark.parametrize 允許在測試函數或類中定義多組參數和fixtures
- pytest_generate_tests 允許定義自定義參數化方案或擴展(拓展)
參數化場景
只有測試數據和期望結果不一樣,但操作步驟是一樣的測試用例可以用上參數化;
可以看看下面的栗子
未參數化的代碼
def test_1(): assert 3 + 5 == 9 def test_2(): assert 2 + 4 == 6 def test_3(): assert 6 * 9 == 42
可以看到,三個用例都是加法然后斷言某個值,重復寫三個類似的用例有點冗余
利用參數化優化之后的代碼
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)]) def test_eval(test_input, expected): print(f"測試數據{test_input},期望結果{expected}") assert eval(test_input) == expected
執行結果
可以看到,只有一條用例,但是利用參數化輸入三組不同的測試數據和期望結果,最終執行的測試用例數=3,可以節省很多代碼
實際Web UI自動化中的開發場景,比如是一個登錄框
- 你肯定需要測試賬號空、密碼空、賬號密碼都為空、賬號不存在、密碼錯誤、賬號密碼正確等情況
- 這些用例的區別就在於輸入的測試數據和對應的交互結果
- 所以我們可以只寫一條登錄測試用例,然后把多組測試數據和期望結果參數化,節省很多代碼量
源碼分析
def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):
argnames
源碼解析:a comma-separated string denoting one or more argument names, or a list/tuple of argument strings.
含義:參數名字
格式:字符串"arg1,arg2,arg3"【需要用逗號分隔】
備注:源碼中寫了可以是參數字符串的list或者tuple,但博主實操過是不行的,不知道是不是寫的有問題,大家可以看看評論下
示例
@pytest.mark.parametrize(["name", "pwd"], [("yy1", "123"), ("yy2", "123")]) @pytest.mark.parametrize(("name", "pwd"), [("yy1", "123"), ("yy2", "123")]) @pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123")])
備注
有朋友提出現在上面標注錯的兩個可以正常使用了
argvalues
源碼解析:
- The list of argvalues determines how often a test is invoked with different argument values.
- If only one argname was specified argvalues is a list of values.【只有一個參數,則是值列表】
- If N argnames were specified, argvalues must be a list of N-tuples, where each tuple-element specifies a value for its respective argname.【如果有多個參數,則用元組來存每一組值】
含義:參數值列表
格式:必須是列表,如:[ val1,val2,val3 ]
如果只有一個參數,里面則是值的列表如:@pytest.mark.parametrize("username", ["yy", "yy2", "yy3"])
如果有多個參數例,則需要用元組來存放值,一個元組對應一組參數的值,如:@pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123"), ("yy3", "123")])
備注:雖然源碼說需要list包含tuple,但我試了下,tuple包含list,list包含list也是可以的........
ids
含義:用例的ID
格式:傳一個字符串列表
作用:可以標識每一個測試用例,自定義測試數據結果的顯示,為了增加可讀性
強調:ids的長度需要與測試數據列表的長度一致
indirect
作用:如果設置成True,則把傳進來的參數當函數執行,而不是一個參數(下一篇博文即講解)
講完源碼,對方法有更深入的了解了,我們就講講常用的場景
裝飾測試類
@pytest.mark.parametrize('a, b, expect', data_1) class TestParametrize: def test_parametrize_1(self, a, b, expect): print('\n測試函數11111 測試數據為\n{}-{}'.format(a, b)) assert a + b == expect def test_parametrize_2(self, a, b, expect): print('\n測試函數22222 測試數據為\n{}-{}'.format(a, b)) assert a + b == expect
執行結果
重點
當裝飾器 @pytest.mark.parametrize 裝飾測試類時,會將數據集合傳遞給類的所有測試用例方法
“笛卡爾積”,多個參數化裝飾器
# 笛卡爾積,組合數據 data_1 = [1, 2, 3] data_2 = ['a', 'b'] @pytest.mark.parametrize('a', data_1) @pytest.mark.parametrize('b', data_2) def test_parametrize_1(a, b): print(f'笛卡爾積 測試數據為 : {a},{b}')
執行結果
重點知識
- 一個函數或一個類可以裝飾多個 @pytest.mark.parametrize
- 這種方式,最終生成的用例數是n*m,比如上面的代碼就是:參數a的數據有3個,參數b的數據有2個,所以最終的用例數有3*2=6條
- 當參數化裝飾器有很多個的時候,用例數都等於n*n*n*n*....
參數化 ,傳入字典數據
# 字典 data_1 = ( { 'user': 1, 'pwd': 2 }, { 'user': 3, 'pwd': 4 } ) @pytest.mark.parametrize('dic', data_1) def test_parametrize_1(dic): print(f'測試數據為\n{dic}') print(f'user:{dic["user"]},pwd{dic["pwd"]}')
沒啥特別的,只是數據類型是常見的dict而已
執行結果
09parametrize.py::test_parametrize_1[dic0] PASSED [ 50%]測試數據為 {'user': 1, 'pwd': 2} user:1,pwd2 09parametrize.py::test_parametrize_1[dic1] PASSED [100%]測試數據為 {'user': 3, 'pwd': 4} user:3,pwd4
參數化,標記數據
# 標記參數化 @pytest.mark.parametrize("test_input,expected", [ ("3+5", 8), ("2+4", 6), pytest.param("6 * 9", 42, marks=pytest.mark.xfail), pytest.param("6*6", 42, marks=pytest.mark.skip) ]) def test_mark(test_input, expected): assert eval(test_input) == expected
執行結果
參數化,增加可讀性
# 增加可讀性 data_1 = [ (1, 2, 3), (4, 5, 9) ] # ids ids = ["a:{} + b:{} = expect:{}".format(a, b, expect) for a, b, expect in data_1] @pytest.mark.parametrize('a, b, expect', data_1, ids=ids) class TestParametrize(object): def test_parametrize_1(self, a, b, expect): print('測試函數1測試數據為{}-{}'.format(a, b)) assert a + b == expect def test_parametrize_2(self, a, b, expect): print('測試函數2數據為{}-{}'.format(a, b)) assert a + b == expect
執行結果
知識點
多少組數據,就要有多少個id,然后組成一個id的列表
作用:主要是為了更加清晰看到用例的含義