【pytest系列】- assert斷言的使用

miki_peng發表於2021-04-14

unittest斷言方式是用過框架自己實現的,即self.assertEqual()等,當我們使用pytest框架後,這種斷言方式是不可用的,因為測試類不會再繼承unittest.TestCase類,因此pytest使用的斷言是使用python內建的斷言assert,相對於unittest各種各樣的斷言方法,內建的斷言會更簡潔,它只有一種,詳情如下。

常用斷言

​ 關鍵程式碼:assert 表示式, 錯誤提示資訊

def test_login():
    # 使用python內建的斷言
    assert 1 == 2, '1是不等於2的'	# 錯誤資訊也可以不寫
    
test_login()

​ 執行結果:

C:\software\python\python.exe D:/learn/test.py
Traceback (most recent call last):
  File "D:/learn/test.py", line 13, in <module>
    test_login()
  File "D:/learn/test.py", line 11, in test_login
    assert 1 == 2, '1是不等於2的'
AssertionError: 1是不等於2的

Process finished with exit code 1

常用的斷言表達有以下幾種?

  • assert xx:判斷xx為真
  • assert not xx:判斷xx不為真
  • assert a in b :判斷b包含a
  • assert a not in b :判斷b不包含a
  • assert a == b:判斷a等於b
  • assert a != b:判斷a不等於b

異常斷言

​ 可以使用pytest.raises作為上下文管理器,當丟擲異常時可以獲取到對應的異常例項,然後斷言它丟擲的異常是不是預期的。

# 斷言異常
def test_zero_division():
    with pytest.raises(ZeroDivisionError):
        1 / 0

​ 如任意一個自然數除以0時,由於0不能作為被除數,執行時就會丟擲ZeroDivisionError異常,提示division by zero

# 詳細斷言異常
def test_zero_division_long():
    with pytest.raises(ZeroDivisionError) as excinfo:
        1 / 0

    # 斷言異常型別 type
    assert excinfo.type == ZeroDivisionError
    # 斷言異常 value 值
    assert "division by zero" in str(excinfo.value)

注意:斷言type的時候,異常型別是不需要加引號的,斷言value值的時候需轉str型別。

擴充套件

正則斷言

​ 可以將match關鍵字引數傳遞給上下文管理器,以測試正規表示式與異常的字串表示形式是否匹配

注意:這種方法只能斷言value,不能斷言type

# 自定義訊息
def test_zero_division_long():
    with pytest.raises(ZeroDivisionError, match=".*zero.*") as excinfo:
        1 / 0

​ 該match方法的regexp引數 re.search函式匹配,因此在上面的示例中match='zero'也可以使用

# 自定義訊息
def test_zero_division_long():
    with pytest.raises(ZeroDivisionError, match="zero") as excinfo:
        1 / 0

​ 執行結果:

檢查斷言裝飾器

​ 當程式碼丟擲異常時,如果和raises指定的異常類相匹配,就不會斷言失敗。

​ 它相當於一個檢查異常裝飾器,目的是檢查是否有異常(不確定是否有異常),不同使用場景:

  • with pytest.raise(ZeroDivisionError)對於故意測試異常程式碼的情況,使用可能會更好
  • @pytest.mark.xfail(raises=ZeroDivisionError) 對於檢查未修復的錯誤(即可能會發生異常),使用檢查斷言可能會更好
# 斷言裝飾器
@pytest.mark.xfail(raises=ZeroDivisionError)
def test_f():
    1 / 0

​ 執行結果:

相關文章