pytest.raises: get and check the error message (tested)

In pytest, catch the exception with with pytest.raises(ValueError) as excinfo: and read the message afterwards with str(excinfo.value), not str(excinfo). To check it in one line use match=, which is a regex search. Add a message to a plain assert with assert cond, "message".

Three related questions: how to read the message of an exception caught by pytest.raises, how to check it, and how to see the full message of a failed assert when the summary line cuts it off. Measured with pytest 9.1.1 on Python 3.13.5.

1. Get and check the exception message with pytest.raises

$ cat test_msg.py
import pytest

def parse_age(s):
    n = int(s)
    if n < 0:
        raise ValueError(f"age must be >= 0, got {n}")
    return n

def test_get_message():
    with pytest.raises(ValueError) as excinfo:
        parse_age("-3")
    print("type: ", excinfo.type.__name__)
    print("str:  ", str(excinfo.value))
    print("args: ", excinfo.value.args)
    assert str(excinfo.value) == "age must be >= 0, got -3"

def test_match_is_a_search():
    with pytest.raises(ValueError, match="got -3"):      # partial: passes
        parse_age("-3")
    with pytest.raises(ValueError, match=r"^age must be >= 0, got -3$"):
        parse_age("-3")

def test_str_of_excinfo_is_not_the_message():
    with pytest.raises(ValueError) as excinfo:
        parse_age("abc")
    print("str(excinfo):      ", str(excinfo)[:60])
    print("str(excinfo.value):", str(excinfo.value))
    assert "abc" in str(excinfo)
$ pytest -q -s -p no:cacheprovider test_msg.py; echo "exit $?"
type:  ValueError
str:   age must be >= 0, got -3
args:  ('age must be >= 0, got -3',)
..str(excinfo):       <ExceptionInfo ValueError("invalid literal for int() with ba
str(excinfo.value): invalid literal for int() with base 10: 'abc'
.
3 passed in 0.00s
exit 0

with pytest.raises(...) as excinfo gives you an ExceptionInfo. The exception itself is excinfo.value; its message is str(excinfo.value) (or excinfo.value.args), and the class is excinfo.type. Use these after the with block. str(excinfo) is not the message: it is a repr like <ExceptionInfo ValueError(...) tblen=...>, so an in check against it can pass by accident. match= is a re.search, so a fragment is enough; anchor with ^...$ for an exact match, and wrap literal text in re.escape() when it contains ( ) . [ ] + (see pytest Failed: DID NOT RAISE).

2. A custom message for a plain assert

$ cat test_assert.py
def test_custom_message():
    items = ["a", "b"]
    assert len(items) == 3, f"expected 3 items, got {items}"
$ pytest -q -p no:cacheprovider test_assert.py; echo "exit $?"
F                                                                        [100%]
=================================== FAILURES ===================================
_____________________________ test_custom_message ______________________________

    def test_custom_message():
        items = ["a", "b"]
>       assert len(items) == 3, f"expected 3 items, got {items}"
E       AssertionError: expected 3 items, got ['a', 'b']
E       assert 2 == 3
E        +  where 2 = len(['a', 'b'])

test_assert.py:3: AssertionError
=========================== short test summary info ============================
FAILED test_assert.py::test_custom_message - AssertionError: expected 3 items...
1 failed in 0.01s
exit 1

The text after the comma becomes the AssertionError message, and pytest still shows its own introspection (assert 2 == 3, where 2 = len([...])) below it. Exit code 1 means tests failed.

3. The short summary truncates the message: see it in full

$ pytest -q -p no:cacheprovider --tb=no test_assert.py | tail -2
FAILED test_assert.py::test_custom_message - AssertionError: expected 3 items...
1 failed in 0.00s
$ pytest -vv -p no:cacheprovider --tb=no test_assert.py | grep FAILED
test_assert.py::test_custom_message FAILED                               [100%]
FAILED test_assert.py::test_custom_message - AssertionError: expected 3 items, got ['a', 'b']
$ pytest -q -p no:cacheprovider --tb=line test_assert.py | grep -A1 AssertionError | head -2
E   AssertionError: expected 3 items, got ['a', 'b']
    assert 2 == 3

In the default short test summary the message ends in .... -vv prints the whole message on the FAILED line; --tb=line or the default traceback output also show it in full.

Related: pytest.fail with a message vs xfail, pytest error vs failure, assert log messages with caplog.

Frequently asked questions

How do I get the error message from pytest.raises?

Use with pytest.raises(SomeError) as excinfo: ... and then str(excinfo.value) after the with block. excinfo.type is the class and excinfo.value.args the arguments.

How do I check the exception message in pytest?

pytest.raises(SomeError, match="fragment") does a re.search on str(exception). Anchor with ^...$ for an exact match and use re.escape for literal text with special characters.

How do I see the full assert message in pytest?

The short summary truncates it with ...; run pytest -vv or look at the traceback section (or --tb=line) for the full message.

Written with AI assistance. Measured on 2026-10-23 with pytest 9.1.1 on Python 3.13.5 in a clean virtualenv. Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; pytest is free.