I need to assert an error message using 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'
by running the test, I got,
self = <ExceptionInfo AttributeError tblen=2>
def __str__(self):
> entry = self.traceback[-1]
E AttributeError: 'ExceptionInfo' object has no attribute 'traceback'
I am wondering how to make py.test
work for asserting exception here.
UPDATE. Tried the solution suggested,
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
got
> invoices.addInvoice(-1.2)
E Failed: DID NOT RAISE
You can't use the ExceptionInfo
inside the with pytest.raises
context. Run the code that is expected to raise in the context, work with the exception info outside:
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
However, if you just want to assert the exception message, the idiomatic way would be passing the expected message directly to 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)
UPDATE. Tried the solution suggested, got:
> invoices.addInvoice(-1.2) E Failed: DID NOT RAISE
That's because the exception is indeed not raised in the addInvoice
method - it is raised inside the try
block and immediately catched afterwards. Either remove the try
block altogether, or reraise the exception:
try:
raise InvAmtValError(amount)
except InvAmtValError as e:
print(str(e))
raise e
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With