I have the following code to create an Object account. I raise an error if the account meets certain conditions, e.g. is too long. I want to use pytest to test that that functionality works.
class Account:
def __init__(self, acct):
self.tagged = {}
self.untagged = {}
self.acct_stats = {}
try:
if len(str(acct)) < 12:
prepend_digit_range = 12 - len(str(acct))
for i in range(prepend_digit_range):
acct = "0" + str(acct)
if len(str(acct)) > 12:
raise ValueError
except ValueError:
logging.error("Account ID " + str(acct) + " invalid")
raise
self.account_id = str(acct)
I'm trying to use pytest to test it.
First I tried this, which didn't work:
# Per https://www.authentise.com/post/pytest-and-parametrization
@pytest.mark.skip("WIP")
@pytest.mark.parametrize(
"account_id, expected",
[
pytest.mark.raises(
(31415926535897932384626, "Account ID 31415926535897932384626 invalid"),
exception=ValueError
)
]
)
def test_account_setup_raise_error1(account_id, expected):
account = Account(account_id)
with expected:
assert account.account_id == expected
Then I tried this:
# Per https://docs.pytest.org/en/stable/example/parametrize.html#parametrizing-conditional-raising
@pytest.mark.parametrize(
"account_id, expected",
[
(
(31415926535897932384626, "Account ID 31415926535897932384626 invalid"),
ValueError,
)
],
)
def test_account_setup_raise_error(account_id, expected):
account = Account(account_id)
with expected:
assert account.account_id == expected
which doesn't work either; I get this when I run pytest:
/usr/local/lib/python3.10/site-packages/pluggy/_hooks.py:265: in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
/usr/local/lib/python3.10/site-packages/pluggy/_manager.py:80: in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
/usr/local/lib/python3.10/site-packages/_pytest/python.py:272: in pytest_pycollect_makeitem
return list(collector._genfunctions(name, obj))
/usr/local/lib/python3.10/site-packages/_pytest/python.py:499: in _genfunctions
self.ihook.pytest_generate_tests.call_extra(methods, dict(metafunc=metafunc))
/usr/local/lib/python3.10/site-packages/pluggy/_hooks.py:292: in call_extra
return self(**kwargs)
/usr/local/lib/python3.10/site-packages/pluggy/_hooks.py:265: in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
/usr/local/lib/python3.10/site-packages/pluggy/_manager.py:80: in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
/usr/local/lib/python3.10/site-packages/_pytest/python.py:151: in pytest_generate_tests
metafunc.parametrize(*marker.args, **marker.kwargs, _param_mark=marker)
/usr/local/lib/python3.10/site-packages/_pytest/python.py:1300: in parametrize
argnames, parametersets = ParameterSet._for_parametrize(
/usr/local/lib/python3.10/site-packages/_pytest/mark/structures.py:166: in _for_parametrize
if len(param.values) != len(argnames):
E TypeError: object of type 'MarkDecorator' has no len()
UPDATE: I've implemented @pl3b's response and got the test code working. It is below; I've updated the parameters to match the changes.
@pytest.mark.parametrize(
"account_id",
[
(
(31415926535897932384626),
("blah"),
ValueError,
)
],
)
def test_account_setup_raise_error(account_id):
with pytest.raises(ValueError, match="invalid"):
account = Account(account_id)
print(account)
Note that I also added another test case, for which I updated the code itself:
if len(str(acct)) > 12 or re.match("^[0-9]+$", str(acct)) is None:
raise ValueError("Account ID " + str(acct) + " invalid")
Have you tried with pytest.raises()
?
with pytest.raises(ValueError, match='invalid'):
account = Account(account_id)