使用pytest断言异常时,AttributeError:'ExceptionInfo'对象没有属性'traceback' [英] AttributeError: 'ExceptionInfo' object has no attribute 'traceback' when using pytest to assert exceptions

查看:54
本文介绍了使用pytest断言异常时,AttributeError:'ExceptionInfo'对象没有属性'traceback'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用py.test

断言错误消息
import pandas as pd
import numpy as np

from inv_exception_store import InvAmtValError

MAX_INV_VAL = 10000000.0
MIN_INV_VAL = 0.0


class Invoices:

    def __init__(self, data=None):
        if data is None:
            self.__invoices = pd.Series([], dtype=np.float32)
        else:
            self.__invoices = pd.Series(pd.Series(data).astype(np.float32))

    def addInvoice(self, amount):
        try:
            if self.__invoices.size > MAX_INV_SIZE:
                raise InvNumError
            elif amount > MAX_INV_VAL or amount < MIN_INV_VAL:
                raise InvAmtValError(amount)
            else:
                self.__invoices = self.__invoices.append(pd.Series(amount).astype(np.float32), ignore_index=True)
        except (InvNumError, InvAmtValError) as e:
            print(str(e))


class InvAmtValError(Exception):
    def __init__(self, amount, message=None):
        if message is None:
            if amount > 100000000.0:
                message = 'The invoice amount(s) {} is invalid since it is > $100,000,00.00'.format(amount)
            elif amount < 0.0:
                message = 'The invoice amount(s) {} is invalid since it is < $0.00'.format(amount)
            else:
                message = 'The invoice amount(s) {} is invalid'.format(amount)

        super(InvAmtValError, self).__init__(str(self.__class__.__name__) + ': ' + message)
        self.message = message

    def __str__(self):
        return self.message

class TestInvoice(object):
        def test_invalid_inv_amount_err(self):
            with pytest.raises(InvAmtValError) as e:
                invoices = Invoices()

                invoices.addInvoice(-1.2)

                assert str(e) == 'The invoice amount(s) -1.2 is invalid since it is < $0.00'

                invoices.addInvoice(100000000.1)

                assert str(e) == 'The invoice amount(s) 100000000.1 is invalid since it is > $100,000,00.00'

通过运行测试,我获得了

self = <ExceptionInfo AttributeError tblen=2>

    def __str__(self):
>       entry = self.traceback[-1]
E       AttributeError: 'ExceptionInfo' object has no attribute 'traceback'

我想知道如何使py.test在此断言异常。

更新。已尝试建议的解决方案,

    def test_invalid_min_inv_amount_err(self):
        with pytest.raises(InvAmtValError) as e:
            invoices = Invoices()

            invoices.addInvoice(-1.2)
        assert str(e) == 'The invoice amount(s) -1.2 is invalid since it is < $0.00'
        assert e.type == InvAmtValError

已获取

>           invoices.addInvoice(-1.2)
E           Failed: DID NOT RAISE

推荐答案

您不能在with pytest.raises上下文内使用ExceptionInfo。运行预期在上下文中引发的代码,在外部处理异常信息:

with pytest.raises(InvAmtValError) as e:
    invoices = InvoiceStats()
    invoices.addInvoice(-1.2)

assert str(e) == 'The invoice amount(s) -1.2 is invalid since it is < $0.00'
assert e.type == InvAmtValError  # etc

但是,如果您只想断言异常消息,惯用的方法是将预期的消息直接传递给pytest.raises

expected = 'The invoice amount(s) -1.2 is invalid since it is < $0.00'
with pytest.raises(InvAmtValError, match=expected):
    invoices = InvoiceStats()
    invoices.addInvoice(-1.2)

expected = 'The invoice amount(s) 100000000.1 is invalid since it is > $100,000,00.00'
with pytest.raises(InvAmtValError, match=expected):
    invoices = InvoiceStats()
    invoices.addInvoice(100000000.1)

更新。尝试建议的解决方案,得到:

>           invoices.addInvoice(-1.2)
E           Failed: DID NOT RAISE

这是因为异常确实没有在addInvoice方法中引发-它在try挡路中引发并在之后立即捕获。或者完全删除try挡路,或者重新激活例外:

try:
    raise InvAmtValError(amount)
except InvAmtValError as e:
    print(str(e))
    raise e

这篇关于使用pytest断言异常时,AttributeError:&#39;ExceptionInfo&#39;对象没有属性&#39;traceback&#39;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆