Pytest ---- 斷言處理_assert和異常斷言


前言

  • 與unittest不同,pytest使用的是python自帶的assert關鍵字來進行斷言
  • assert關鍵字后面可以接一個表達式,只要表達式的最終結果為True,那么斷言通過,用例執行成功,否則用例執行失敗

 

Pytest的斷言方式及應用場景

  • 使用assert語句

  • 斷言預期的異常

  • 斷言預期的告警

  • 利用上下文信息進行斷言

  • 自定義斷言方式

使用assert語句進行斷言

  • pytest允許使用python的標准assert語句進行斷言處理

  • 采用assert斷言時,可添加備注信息,當斷言失敗時,備注信息會以assertionerror拋出,並在控制台輸出

import requests
 
class TestAssert():
 
    def test_assert(self):
        r = requests.get('http://www.baidu.com')
        assert r.status_code == 100, "返回200說明訪問成功"

示例2:在拋出異常之后輸出一些提示信息,執行之后就方便查看是什么原因了

# 異常信息
def f():
    return 3
def test_function():
    a = f()
    assert a % 2 == 0, "判斷 a 為偶數,當前 a 的值為:%s" % a

常用斷言

 

 

 

 

  

斷言預期的異常

  • 在測試過程中,對某些方法進行測試時,預測輸入某些特定數據,會拋出特定異常,若出現特定異常,則用例執行通過。

  • 對這類特定異常的斷言,可以采用pytest中的pytest.raises()進行處理。
    以下示例對一個判斷是否為閏年的方法進行測試:

# -*- coding: utf-8 -*-

"""
__title__  = pytest study
__Time__   = 2021-04-12 08:47
__Author__ = sary

"""
import pytest

def is_leap_year(year):
    # 先判斷year是不是整型
    if isinstance(year, int) is not True:
        raise TypeError("傳入的參數不是整數")
    elif year == 0:
        raise ValueError("公元元年是從公元一年開始!!")
    elif abs(year) != year:
        raise ValueError("傳入的參數不是正整數")
    elif (year % 4 ==0 and year % 100 != 0) or year % 400 == 0:
        print("%d年是閏年" % year)
        return True
    else:
        print("%d年不是閏年" % year)
        return False

class TestAssert():
    # 對一個判斷是否是閏年的方法進行測試
    def test_exception_typeerror(self):
        with pytest.raises(TypeError):
            is_leap_year('ss')

    def test_true(self):
        assert is_leap_year(2021) == True

  

2、將異常信息存儲到一個變量中,變量的類型則為異常類,包含異常的type、value和traceback等信息

# -*- coding: utf-8 -*-

"""
__title__  = pytest study
__Time__   = 2021-04-12 08:47
__Author__ = sary

"""
import pytest

def is_leap_year(year):
    # 先判斷year是不是整型
    if isinstance(year, int) is not True:
        raise TypeError("傳入的參數不是整數")
    elif year == 0:
        raise ValueError("公元元年是從公元一年開始!!")
    elif abs(year) != year:
        raise ValueError("傳入的參數不是正整數")
    elif (year % 4 ==0 and year % 100 != 0) or year % 400 == 0:
        print("%d年是閏年" % year)
        return True
    else:
        print("%d年不是閏年" % year)
        return False


class TestAssert():
    def test_exception_value(self):
        with pytest.raises(ValueError) as excinfo:
            is_leap_year(0)

        assert "從公元一年開始" in str(excinfo.value)
        assert excinfo.type == ValueError

  

3、可以在用例中定義拋出的異常信息是否與預期的異常信息匹配,若不匹配則用例執行失敗

# -*- coding: utf-8 -*-

"""
__title__  = pytest study
__Time__   = 2021-04-12 08:47
__Author__ = sary

"""
import pytest

def is_leap_year(year):
    # 先判斷year是不是整型
    if isinstance(year, int) is not True:
        raise TypeError("傳入的參數不是整數")
    elif year == 0:
        raise ValueError("公元元年是從公元一年開始!!")
    elif abs(year) != year:
        raise ValueError("傳入的參數不是正整數")
    elif (year % 4 ==0 and year % 100 != 0) or year % 400 == 0:
        print("%d年是閏年" % year)
        return True
    else:
        print("%d年不是閏年" % year)
        return False



class TestAssert():
    def test_exception_match(self):
        with pytest.raises(ValueError, match=r'公元33元年是從公元一年開始') as excinfo:
            is_leap_year(0)

        assert excinfo.type == ValueError

將match中的Pattern該為能夠匹配的信息,則該用例能夠執行成功。

4、使用標記函數檢查異常

pytest.mark.xfail(raises=xx)

 

異常斷言

可以使用 pytest.raises 作為上下文管理器,當拋出異常時可以獲取到對應的異常實例
# 斷言異常
def test_zero_division():
    with pytest.raises(ZeroDivisionError):
        1 / 0

  

異常斷言示例:

斷言場景:斷言它拋的異常是不是預期想要的

代碼執行:1/0
預期結果:拋的異常是ZeroDivisionError: division by zero
如何斷言:通常是斷言異常的 type 和 value 值了
具體方式:這里 1/0 的異常類型是 ZeroDivisionError,異常的 value 值是 divisionby 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)

 excinfo :是一個異常信息實例

主要屬性:  .type 、  .value 、 .traceback 
注意:斷言 type 的時候,異常類型是不需要加引號的,斷言 value值的時候需轉 str

拓展一:match

可以將  match 關鍵字參數傳遞給上下文管理器,以測試正則表達式與異常的字符串表示形式是否匹配
注意:這種方法只能斷言value,不能斷言type

 

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

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

 

拓展二:檢查斷言裝飾器

# 斷言裝飾器
@pytest.mark.xfail(raises=ZeroDivisionError)
def test_f():
    1 / 0

知識點

  • 代碼拋出異常,但是和raises指定的異常類相匹配,所以不會斷言失敗
  • 它相當於一個檢查異常裝飾器,功能:檢查是否有異常,不確定是否有異常
  • with pytest.raise(ZeroDivisionError)  對於故意測試異常代碼的情況,使用可能會更好
  • @pytest.mark.xfail(raises=ZeroDivisionError) 對於檢查未修復的錯誤(即,可能會發生異常),使用檢查斷言可能會更好

  

總結

pytest的斷言方式非常簡潔明確。本節主要介紹了對異常信息的斷言,包括4種情況:

  • 直接斷言,不添加assert語句

  • 將異常信息存儲在變量中,再讀取異常信息進行斷言判斷

  • 對異常的輸出信息進行斷言,異常類型、異常輸出信息同時匹配成功,用例才能執行成功

  • 采用標記函數進行異常斷言

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM