I'm testing code where one of two exceptions can be raised: MachineError or NotImplementedError. I would like to use pytest.raises
to make sure that at least one of them is raised when I run my test code, but it only seems to accept one exception type as an argument.
This is the signature for pytest.raises
:
raises(expected_exception, *args, **kwargs)
I tried using the or
keyword inside a context manager:
with pytest.raises(MachineError) or pytest.raises(NotImplementedError):
verb = Verb("donner<IND><FUT><REL><SG><1>")
verb.conjugate()
but I assume this only checks whether the first pytest.raises
is None
and sets the second one as the context manager if it is.
Passing multiple exceptions as positional arguments doesn't work, because pytest.raises
takes its second argument to be a callable. Every subsequent positional argument is passed as an argument to that callable.
From the documentation:
>>> raises(ZeroDivisionError, lambda: 1/0)
<ExceptionInfo ...>
>>> def f(x): return 1/x
...
>>> raises(ZeroDivisionError, f, 0)
<ExceptionInfo ...>
>>> raises(ZeroDivisionError, f, x=0)
<ExceptionInfo ...>
Passing the exceptions as a list doesn't work either:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
with pytest.raises([MachineError, NotImplementedError]):
File "/usr/local/lib/python3.4/dist-packages/_pytest/python.py", line 1290, in raises
raise TypeError(msg % type(expected_exception))
TypeError: exceptions must be old-style classes or derived from BaseException, not <class 'list'>
Is there a workaround for this? It doesn't have to use a context manager.
Strictly speaking you can't raise multiple exceptions but you could raise an object that contains multiple exceptions.
Pytest, by way of magic (also known as introspection) can infere the actual value, the expected value, and the operation used in a plain old assert statement and can provide a rather nice error message.
Pass the exceptions as a tuple to raises
:
with pytest.raises( (MachineError, NotImplementedError) ):
verb = ...
In the source for pytest
, pytest.raises
may:
expected_exception
; orexpected_exception
to a RaisesContext
instance, which then uses issubclass
to check whether the exception was one you wanted. In Python 3, except
statements can take a tuple of exceptions. The issubclass
function can also take a tuple. Therefore, using a tuple should be acceptable in either situation.
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