This rule raises an issue when a test for an expected exception contains multiple method calls, making it unclear which call is expected to raise the exception.
When writing tests for exception handling, clarity is essential. If you chain multiple method calls within the code being tested for an exception, it becomes ambiguous which specific call is expected to raise that exception.
For example, both parse_payment(payload) and normalize() could raise a ValueError:
with pytest.raises(ValueError):
parse_payment(payload).normalize()
The test does not make it explicit which method is expected to raise the exception. This ambiguity makes the test harder to read and maintain.
By isolating the method call you want to test, you make your test explicit and unambiguous. This improves readability and maintainability, and makes your test suite a better specification of expected behavior.
Writing tests with multiple method calls when testing for exceptions reduces test quality:
When using pytest’s pytest.raises() context manager, extract intermediate method calls into separate variables before the assertion.
This ensures only the final method call that you want to test is inside the exception-testing block.
import pytest
def test_normalize_rejects_negative_amount():
with pytest.raises(ValueError): # Noncompliant
parse_payment(payload).normalize()
import pytest
def test_normalize_rejects_negative_amount():
payment = parse_payment(payload)
with pytest.raises(ValueError):
payment.normalize()
When using unittest’s assertRaises() method, extract intermediate method calls before the assertion. This makes it clear which
specific method is being tested for the exception.
import unittest
class TestPayment(unittest.TestCase):
def test_normalize_rejects_negative_amount(self):
self.assertRaises(ValueError, lambda: parse_payment(payload).normalize()) # Noncompliant
import unittest
class TestPayment(unittest.TestCase):
def test_normalize_rejects_negative_amount(self):
payment = parse_payment(payload)
self.assertRaises(ValueError, payment.normalize)