This rule raises an issue when pytest.raises() is called without a with statement, including standalone calls, the deprecated callable-passing form, and typos that call the function before entering the context manager.

In Python, this refers to the different usages of pytest.raises() without a with statement, such as:

Why is this an issue?

Pytest cannot verify the outcome if the code under test is not wrapped in a with pytest.raises(…​): block.

Standalone calls

pytest.raises(ValueError) without with constructs a context manager and discards it. The test passes even when the following code does not raise:

def test_invalid_input():
    pytest.raises(ValueError)
    process_data('hello')  # No exception — test still passes

Deprecated callable-passing form

Pytest still supports passing the callable and its arguments:

pytest.raises(ValueError, bootstrap_session, df=-1)  # Deprecated

This executes bootstrap_session(df=-1) and fails when no exception is raised. It works, but pytest deprecates it. Refactoring this form into a bare standalone call silently stops verifying exceptions.

Typo: calling the function immediately

A common mistake adds parentheses around the call:

pytest.raises(NotImplementedError, bootstrap_session(df=10))  # Silent failure

Here bootstrap_session runs before pytest.raises is entered. When df=10 is valid and no exception is raised, pytest.raises receives the return value and the test passes without verifying anything.

Correct usage

with pytest.raises(ValueError):
    bootstrap_session(df=-1)

The with block must raise the expected exception, or the test fails.

What is the potential impact?

Tests that never enter the pytest.raises context manager can pass when no exception is raised, leaving error-handling regressions undetected. Deprecated callable-passing syntax and the parenthesis typo are prone to silent breakage during refactors.

How to fix it

In Python with pytest, use with pytest.raises(ValueError): around the code that should fail.

Wrap the code that should raise with with pytest.raises(ExpectedError):. To inspect the exception, use as exc_info or the match parameter.

Migrate deprecated callable-passing calls by moving the invocation into the with block.

Code examples

Noncompliant code example

import pytest

def process_data(data):
    return data.upper()

def test_invalid_input():
    pytest.raises(ValueError)  # Noncompliant: context manager never entered
    process_data('hello')

Compliant solution

import pytest

def process_data(data):
    return data.upper()

def test_invalid_input():
    with pytest.raises(ValueError):
        process_data('hello')

Noncompliant code example

import pytest

def bootstrap_session(df=10):
    if df <= 0:
        raise ValueError('df must be positive')
    if df > 20:
        raise NotImplementedError('df > 20 not supported')

def test_invalid_df():
    pytest.raises(ValueError, bootstrap_session, df=-1)  # Noncompliant: deprecated form

def test_unsupported_df():
    pytest.raises(NotImplementedError, bootstrap_session(df=10))  # Noncompliant: function called immediately

Compliant solution

import pytest

def bootstrap_session(df=10):
    if df <= 0:
        raise ValueError('df must be positive')
    if df > 20:
        raise NotImplementedError('df > 20 not supported')

def test_invalid_df():
    with pytest.raises(ValueError):
        bootstrap_session(df=-1)

def test_unsupported_df():
    with pytest.raises(NotImplementedError):
        bootstrap_session(df=25)

Resources

Documentation