簡體   English   中英

在 Python 中為 `assertRaises()` 使用自定義失敗消息?

[英]Use a custom failure message for `assertRaises()` in Python?

Python 2.7 unittest 文檔說:

所有斷言方法(除了assertRaises()assertRaisesRegexp() )都接受一個msg參數,如果指定,則用作失敗時的錯誤消息

…但是如果我想為assertRaises()assertRaisesRegexp()指定錯誤消息怎么辦?

用例:在循環中測試各種值時,如果一個失敗,我想知道是哪個:

NON_INTEGERS = [0.21, 1.5, 23.462, math.pi]

class FactorizerTestCase(unittest.TestCase):
    def test_exception_raised_for_non_integers(self):
        for value in NON_INTEGERS:
            with self.assertRaises(ValueError):
                factorize(value)

如果其中任何一個失敗,我會得到:

AssertionError: ValueError not raised

這對我找出哪個失敗沒有太大幫助……如果我能像assertEqual()等一樣提供一個msg=參數就好了!

(我當然可以將它們分解成單獨的測試函數——但也許有很多我想測試的值,或者它需要一些緩慢/昂貴的設置,或者它是更長的功能測試的一部分)

如果我可以輕松地讓它報告類似以下內容,我會很高興:

AssertionError: ValueError not raised for input 23.462

— 但它也不是一個足夠重要的事情來保證重新實現/擴展assertRaises()並向我的測試添加更多代碼。

你也可以回self.fail使用self.fail這感覺很煩人,但我認為看起來有點不那么hacky

for value in NON_INTEGERS:
    with self.assertRaises(ValueError) as cm:
        factorize(value)
        self.fail('ValueError not raised for {}'.format(value))

1.我發現最容易(但很笨拙!)這樣做的方法是:

for value in NON_INTEGERS:
    with self.assertRaises(ValueError) as cm:
        cm.expected.__name__ = 'ValueError for {}'.format(value)  # custom failure msg
        factorize(value)

將在失敗時報告此情況:

AssertionError: ValueError for 23.462 not raised

請注意,這僅在使用with …語法時有效

它的工作原理是因為assertRaises()上下文管理器在內部執行此操作:

exc_name = self.expected.__name__
…
raise self.failureException(
    "{0} not raised".format(exc_name))

如果實現發生變化 ,那么可能會出現片狀 ,盡管Py3源代碼足夠相似,它也應該在那里工作(但不能說我已經嘗試過了)。

2. 依賴於實現的最簡單方法是捕獲錯誤並使用改進的消息重新提升它:

for value in NON_INTEGERS:
    try:
        with self.assertRaises(ValueError) as cm:
            factorize(value)
    except AssertionError as e:
        raise self.failureException('{} for {}'.format(e.message, value)), sys.exc_info()[2]

sys.exc_info()[2]位用於重用原始堆棧跟蹤 ,但此語法僅為Py2 這個答案解釋了如何為Py3做這個(並啟發了這個解決方案)。

但這已經讓測試難以閱讀,所以我更喜歡第一種選擇。

“正確”的解決方案需要編寫assertRaises_AssertRaisesContext類的包裝版本,當你遇到失敗時,你可能會拋出一些日志記錄,這聽起來有些過分。

在 Python 3 中, unittest現在將錯誤消息公開為您with self.assertRaises()從中獲取的_AssertRaisesContext實例的一個適當的、可公開訪問的屬性。 所以在Python 3中,可以這樣做:

with self.assertRaises(ValueError) as assertion:
    assertion.msg = f"ValueError not raised for input {value}"
    factorize(value)

我使用它而不是assertRaises

    def test_empty_username(self):
    # noinspection PyBroadException
    try:
        my_func(username="")
    except Exception:
        # If it does, we are OK.
        return
    # If not, we are here.
    self.fail("my_func() must reject empty username.")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM