《pytest測試實戰》筆記:二

1. 使用assert聲明

pytest與unittest對比:

pytest unittest
assert something assertTrue(something)
assert a == b assertEqual(a,b)
assert a <= b assertLessEqual(a,b)

pytest有一個重要的功能,它可以重寫assert關鍵字。pytest會截斷對原生assert的調用,替換爲pytest定義的assert,從而提供更多的失敗信息和細節。
增加一個運行失敗的測試用例:

def test_failure():
    """使用assert"""

    t1 = 'a'
    t2 = 'b'
    assert t1 == t2

運行結果如下:
在這裏插入圖片描述
失敗的測試用例在行首都用一個>號來表示。以E開頭的行是pytest提供的額外判定信息,用於幫助我們瞭解異常的具體情況。

2. 預期異常

定義一個Task類型數據,並增加一個會引起TypeError異常的測試用例:

Task = namedtuple('Task', ['summary', 'owner', 'dine', 'id'])
Task.__new__.__delattr__ = (None, None, False, None)

def test_task():
	task = Task();

運行結果如下:
在這裏插入圖片描述
在原本基礎上,增加with pytest.raises(TypeError):

def test_task():
    with pytest.raises(TypeError):
        task = Task();

再次運行,運行結果如下:
在這裏插入圖片描述
測試用例test_task()中有with pytest.raises(TypeError)聲明,意味着無論with中的內容是什麼,都至少會發生TypeError異常。如果測試通過,說明確實發生來我們預期的TypeError異常;如果測試失敗,說明拋出的是與我們所預期不一致的異常。
另外,可以通過as excinfo語句來獲取異常消息的值。

 with pytest.raises(TypeError) as excinfo:

3. 測試函數的標記

pytest提供了標記機制,允許你使用marker對測試函數做標記。一個測試函數可以有多個marker,一個marker也可以用勒標記多個測試函數。
例如,爲了吧選定的測試用例加入冒煙測試,可以對它們添加統一的標識,如:@pytest.mark.smoke。
運行時,通過參數-m來指定:

pytest -m smoke

ps:-m具體用法可查看:《pytest測試實戰》筆記:一
另外,帶有相同標記的測試用例即使存放在不同文件下,也會被一起執行。

4. 跳過測試

pytest自身內置了一些標記:skip、skipif、xfail。
skip、skipif允許你跳過不希望運行的測試。
要跳過某個測試用例,只需簡單地在測試函數上添加@pytest.mark.skip()裝飾器即可。
實際上,可以給到跳過的測試用例添加理由和條件,比如希望它只在包版本低於0.2.0時才生效,應用skipif替代skip:

@pytest.mark.skipif(tasks.__version__ < 0.2.0,
					reason = 'not supported until version 0.2.0')

skipif()的判斷條件可以是任何Python表達式。
運行時可以通過-rs查看跳過的原因:
在這裏插入圖片描述

5. 標記預期會失敗的測試

使用skip、skipif標記,測試用例會被直接跳過,不會被執行。使用xfail標記,告訴pytest執行此測試用例,但預期會失敗。
添加兩個測試用例,均使用了xfail來標記,區別在於demo1的assert爲false,demo2的assert爲true:

@pytest.mark.xfail()
def test_demo1():
    t1 = 'a'
    t2 = 'b'
    assert t1 == t2


@pytest.mark.xfail()
def test_demo2():
    t1 = 'a'
    t2 = 'b'
    assert t1 != t2

運行結果如下:
在這裏插入圖片描述
x:XFAIL,expected to fail,預期失敗,實際上也失敗了
X:XPASS,expected to fail but passed,預期失敗,但實際運行並沒有失敗

6. 運行測試子集

運行測試子集有很多方式,不但可以選擇運行某個目錄、文件、類中的測試,還可以選擇運行某一個測試用例(可能在文件中,也可能在類中)。

  • 單個目錄:以目錄作爲pytest的參數即可。
  • 單個測試文件/模塊:運行單個文件裏的全部測試,以路徑名加文件名作爲pytest參數即可。
  • 單個測試函數:運行單個測試函數,在文件名後面添加::符號和函數名。
  • 單個測試類:運行測試類,在文件名後面添加::符號和類名(與運行單個測試函數類似)。
  • 單個測試類中的測試方法:在文件名後面添加::符號和方法名。

7. 參數化測試

可以使用@pytest.mark.parametrize(argnames, argvalues)裝飾器達到批量傳送參數的目的。

testdata_add = [(1, 2, 3), (3.12, 4.12, 7.24), (-100, 200, 100), ("a", "b", "ab"), ("中文1", "中文2", "中文1中文2"), ("space", " ", "space "), ("null", "", "null")]

# 執行時會根據數據的數量執行對應條數的用例
@pytest.mark.parametrize("num1, num2, expect", testdata_add)
def test_add(num1, num2, expect):  # 接收的變量名要和parametrize的一致
    """測試加法運算函數"""

    result = add(num1, num2)
    assert result == expect

運行結果如下:
在這裏插入圖片描述
也可以爲測試類添加parametrize()轉裝飾器,這種情況下,該數據集會被傳遞給該類的所有類方法。

接下來,會在《pytest測試實戰》筆記:三 中介紹如何使用fixture。fixture的作用是將一些非核心測試邏輯,如:測試數據的檢索和生成,從測試函數中分離出來,以便於其他測試函數複用,同時保持這邊邊緣邏輯的一致性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章