代码之家  ›  专栏  ›  技术社区  ›  daiyue

attributeerror:“exceptioninfo”对象在使用pytest断言异常时没有“traceback”属性

  •  3
  • daiyue  · 技术社区  · 6 年前

    我需要使用 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.试验 在这里声明异常。

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

        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
    
    1 回复  |  直到 6 年前
        1
  •  5
  •   hoefling    6 年前

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

    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, message=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, message=expected):
        invoices = InvoiceStats()
        invoices.addInvoice(100000000.1)
    

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

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

    这是因为 addInvoice 方法-它在 try 拦住,然后立即抓住。或者移除 尝试 完全阻止,或重新引发异常:

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