Как я могу использовать pytest.raises с несколькими исключениями?

Я тестирую код, в котором может возникнуть одно из двух исключений: MachineError или NotImplementedError. Я хотел бы использовать pytest.raises, чтобы убедиться, что по крайней мере один из них вызывается при запуске моего тестового кода, но кажется, что он принимает только один тип исключения в качестве аргумента.

Это подпись для pytest.raises:

raises(expected_exception, *args, **kwargs)

Я пытался использовать ключевое слово or внутри контекстного менеджера:

with pytest.raises(MachineError) or pytest.raises(NotImplementedError):
    verb = Verb("donner<IND><FUT><REL><SG><1>")
    verb.conjugate()

но я предполагаю, что это только проверяет, является ли первый pytest.raises None, и устанавливает второе как менеджер контекста, если оно есть.

Передача нескольких исключений в качестве позиционных аргументов не работает, потому что pytest.raises воспринимает свой второй аргумент как вызываемый. Каждый последующий позиционный аргумент передается как аргумент этому вызываемому.

Из документации:

>>> raises(ZeroDivisionError, lambda: 1/0)
<ExceptionInfo ...>

>>> def f(x): return 1/x
...
>>> raises(ZeroDivisionError, f, 0)
<ExceptionInfo ...>
>>> raises(ZeroDivisionError, f, x=0)
<ExceptionInfo ...>

Передача исключений в виде списка также не работает:

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'>

Есть ли обходной путь для этого? Он не должен использовать менеджер контекста.

Ответ 1

Передайте исключения как кортеж в raises:

with pytest.raises( (MachineError, NotImplementedError) ):
    verb = ...

В источнике pytest, pytest.raises может:

В Python 3 операторы except могут принимать несколько исключений. Функция issubclass также может принимать кортеж. Следовательно, использование кортежа должно быть приемлемым в любой ситуации.