How to properly assert that an exception gets raised in pytest?
pytest.raises(Exception)
is what you need.
Code
import pytest
def test_passes():
with pytest.raises(Exception) as e_info:
x = 1 / 0
def test_passes_without_info():
with pytest.raises(Exception):
x = 1 / 0
def test_fails():
with pytest.raises(Exception) as e_info:
x = 1 / 1
def test_fails_without_info():
with pytest.raises(Exception):
x = 1 / 1
# Don't do this. Assertions are caught as exceptions.
def test_passes_but_should_not():
try:
x = 1 / 1
assert False
except Exception:
assert True
# Even if the appropriate exception is caught, it is bad style,
# because the test result is less informative
# than it would be with pytest.raises(e)
# (it just says pass or fail.)
def test_passes_but_bad_style():
try:
x = 1 / 0
assert False
except ZeroDivisionError:
assert True
def test_fails_but_bad_style():
try:
x = 1 / 1
assert False
except ZeroDivisionError:
assert True
Output
============================================================================================= test session starts ==============================================================================================
platform linux2 -- Python 2.7.6 -- py-1.4.26 -- pytest-2.6.4
collected 7 items
test.py ..FF..F
=================================================================================================== FAILURES ===================================================================================================
__________________________________________________________________________________________________ test_fails __________________________________________________________________________________________________
def test_fails():
with pytest.raises(Exception) as e_info:
> x = 1 / 1
E Failed: DID NOT RAISE
test.py:13: Failed
___________________________________________________________________________________________ test_fails_without_info ____________________________________________________________________________________________
def test_fails_without_info():
with pytest.raises(Exception):
> x = 1 / 1
E Failed: DID NOT RAISE
test.py:17: Failed
___________________________________________________________________________________________ test_fails_but_bad_style ___________________________________________________________________________________________
def test_fails_but_bad_style():
try:
x = 1 / 1
> assert False
E assert False
test.py:43: AssertionError
====================================================================================== 3 failed, 4 passed in 0.02 seconds ======================================================================================
Note that e_info
saves the exception object so you can extract details from it. For example, if you want to check the exception call stack or another nested exception inside.
Assert exception message?
I think what you're looking for is:
def failer():
raise myModule.CustomException()
def test_failer():
with pytest.raises(myModule.CustomException) as excinfo:
failer()
assert str(excinfo.value) == "boo!"
How do I test exceptions and errors using pytest?
This way:
with pytest.raises(<YourException>) as exc_info:
<your code that should raise YourException>
exception_raised = exc_info.value
<do asserts here>
Capture a custom exception with 'pytest.raises()' and assert the error message
As mentioned in my question, a comparison of the exception captured by pytest.raises()
seemed to differ from that which was imported from my code. I must confess, I'm not a Python expect and I don't understand why exactly this worked, but the solution was to add init.py to the core
module, and in there import all of the modules in that package.
from core.exception import *
from core.logging import *
# etc.
And then in tests/unit/test_requests.py I was able to import all objects from the core
package.
from myfunction.core import *
Now pytest
sees the exception it captured and the imported exception as the same and my tests are passing.
Test for proper exception with Pytest
For catching the exception, you can use pytest.raises()
like follows:
def test_n_is_a_string_returns_proper_exception(client) -> None:
test_url = f"{fibonacci_url}?n=str"
with pytest.raises(ValueError):
response = client.get(test_url)
You can even check the exception message:
def test_n_is_a_string_returns_proper_exception(client) -> None:
test_url = f"{fibonacci_url}?n=str"
with pytest.raises(ValueError, match="^The value of 'n' must be an integer\.$"):
response = client.get(test_url)
But the ValueError
being thrown inside your view is probably not what you wanted, as it will be shown as a generic 500 error.
Related Topics
If X:, VS If X == True, VS If X Is True
Python Multiprocessing on Windows, If _Name_ == "_Main_"
How to Convert a Given Ordinal Number (From Excel) to a Date
What Is Python Whitespace and How Does It Work
Parsing Datetime Strings Containing Nanoseconds
Calculate Area of Polygon Given (X,Y) Coordinates
"Sys.Getsizeof(Int)" Returns an Unreasonably Large Value
Defining a Discrete Colormap for Imshow in Matplotlib
Reading Unicode File Data with Bom Chars in Python
How to Sort a List of Tuples According to Another List
How to Escape Strings for SQLite Table/Column Names in Python
Pyinstaller and --Onefile: How to Include an Image in the Exe File
Getting a Callback When a Tkinter Listbox Selection Is Changed
How to Get Rid of Double Backslash in Python Windows File Path String
How to Find the Groups of Consecutive Elements in a Numpy Array