# Asserting Warnings

## Asserting warnings with the warns function

New in version 2.8.

You can check that code raises a particular warning using `pytest.warns`, which works in a similar manner to raises:

    import warnings
    import pytest

    def test_warning():
        with pytest.warns(UserWarning):
            warnings.warn("my warning", UserWarning)

The test will fail if the warning in question is not raised.

You can also call `pytest.warns` on a function or code string:

    pytest.warns(expected_warning, func, *args, **kwargs)
    pytest.warns(expected_warning, "func(*args, **kwargs)")

The function also returns a list of all raised warnings (as `warnings.WarningMessage` objects), which you can query for additional information:

    with pytest.warns(RuntimeWarning) as record:
        warnings.warn("another warning", RuntimeWarning)

    # check that only one warning was raised
    assert len(record) == 1
    # check that the message matches
    assert record[0].message.args[0] == "another warning"

Alternatively, you can examine raised warnings in detail using the recwarn fixture (see below).

Note

`DeprecationWarning` and `PendingDeprecationWarning` are treated differently; see Ensuring a function triggers a deprecation warning.

## Recording warnings

You can record raised warnings either using `pytest.warns` or with the `recwarn` fixture.

To record with `pytest.warns` without asserting anything about the warnings, pass `None` as the expected warning type:

    with pytest.warns(None) as record:
        warnings.warn("user", UserWarning)
        warnings.warn("runtime", RuntimeWarning)

    assert len(record) == 2
    assert str(record[0].message) == "user"
    assert str(record[1].message) == "runtime"

The `recwarn` fixture will record warnings for the whole function:

    import warnings

    def test_hello(recwarn):
        warnings.warn("hello", UserWarning)
        assert len(recwarn) == 1
        w = recwarn.pop(UserWarning)
        assert issubclass(w.category, UserWarning)
        assert str(w.message) == "hello"
        assert w.filename
        assert w.lineno

Both `recwarn` and `pytest.warns` return the same interface for recorded warnings: a WarningsRecorder instance. To view the recorded warnings, you can iterate over this instance, call `len` on it to get the number of recorded warnings, or index into it to get a particular recorded warning. It also provides these methods:

class `WarningsRecorder`

  A context manager to record raised warnings.

  Adapted from warnings.catch_warnings.

  `list`

    The list of recorded warnings.

  `pop`(cls=<type 'exceptions.Warning'>)

    Pop the first recorded warning, raise exception if not exists.

  `clear`()

    Clear the list of recorded warnings.

Each recorded warning has the attributes `message`, `category`, `filename`, `lineno`, `file`, and `line`. The `category` is the class of the warning. The `message` is the warning itself; calling `str(message)` will return the actual message of the warning.

Note

`DeprecationWarning` and `PendingDeprecationWarning` are treated differently; see Ensuring a function triggers a deprecation warning.

## Ensuring a function triggers a deprecation warning

You can also call a global helper for checking that a certain function call triggers a `DeprecationWarning` or `PendingDeprecationWarning`:

    import pytest

    def test_global():
        pytest.deprecated_call(myfunction, 17)

By default, `DeprecationWarning` and `PendingDeprecationWarning` will not be caught when using `pytest.warns` or `recwarn` because default Python warnings filters hide them. If you wish to record them in your own code, use the command `warnings.simplefilter('always')`:

    import warnings
    import pytest

    def test_deprecation(recwarn):
        warnings.simplefilter('always')
        warnings.warn("deprecated", DeprecationWarning)
        assert len(recwarn) == 1
        assert recwarn.pop(DeprecationWarning)