This rule raises an issue when a test uses a try-except block combined with fail() to verify whether an exception is
raised or not raised.
Using try-except blocks combined with fail() to test for the presence or absence of exceptions is an anti-pattern.
Modern testing frameworks like pytest and Python’s built-in unittest provide dedicated assertion methods that make
exception testing cleaner and more explicit. These methods eliminate boilerplate code, clearly communicate test intent, and make it easier to assert
on exception details.
The try-except-fail() pattern has several drawbacks:
Dedicated exception assertions solve these problems by providing a declarative way to express exception expectations.
Using try-except with fail() instead of dedicated exception assertions reduces test code quality and maintainability:
try-except patternReplace try-except blocks that use fail() with assertRaises used as a context manager. This built-in method
from Python’s unittest framework provides a clean way to verify exception behavior.
When you expect no exception, simply call the code directly without wrapping it in a try-except block. If an unexpected exception is
raised, the test framework will catch it and fail the test automatically.
When you expect an exception, use assertRaises as a context manager. This allows you to capture the exception and make additional
assertions on its properties.
import unittest
class UserServiceTest(unittest.TestCase):
def test_no_exception_thrown(self):
try:
self.user_service.register_user(self.valid_user)
except ValidationError:
self.fail("Should not have thrown any exception") # Noncompliant
When verifying that an exception is raised, use assertRaises as a context manager. This provides access to the exception object for
further assertions.
import unittest
class UserServiceTest(unittest.TestCase):
def test_exception_is_thrown(self):
try:
self.user_service.register_user(self.invalid_user)
self.fail("Expected ValidationError to be thrown") # Noncompliant
except ValidationError as e:
self.assertEqual("Invalid email", str(e))
Replace try-except blocks that use fail() with assertRaises used as a context manager. This built-in method
from Python’s unittest framework provides a clean way to verify exception behavior.
When you expect no exception, simply call the code directly without wrapping it in a try-except block. If an unexpected exception is
raised, the test framework will catch it and fail the test automatically.
When you expect an exception, use assertRaises as a context manager. This allows you to capture the exception and make additional
assertions on its properties.
import unittest
class UserServiceTest(unittest.TestCase):
def test_no_exception_thrown(self):
# Simply call the method - unittest will fail if an exception is raised
self.user_service.register_user(self.valid_user)
When verifying that an exception is raised, use assertRaises as a context manager. This provides access to the exception object for
further assertions.
import unittest
class UserServiceTest(unittest.TestCase):
def test_exception_is_thrown(self):
with self.assertRaises(ValidationError) as context:
self.user_service.register_user(self.invalid_user)
self.assertEqual("Invalid email", str(context.exception))
Replace try-except blocks with pytest.raises used as a context manager. Pytest is the most popular Python testing
framework and provides excellent exception testing support.
When you expect no exception, simply call the code directly. Pytest will fail the test if an unexpected exception occurs.
When you expect an exception, use pytest.raises as a context manager to verify the exception type and optionally inspect its
properties.
import pytest
def test_no_exception_thrown(user_service, valid_user):
try:
user_service.register_user(valid_user)
except ValidationError:
pytest.fail("Should not have thrown any exception") # Noncompliant
When verifying that an exception is raised with pytest, use pytest.raises as a context manager. This gives you access to the exception
object for additional assertions using the match parameter or the value attribute.
import pytest
def test_exception_is_thrown(user_service, invalid_user):
try:
user_service.register_user(invalid_user)
pytest.fail("Expected ValidationError to be thrown") # Noncompliant
except ValidationError as e:
assert str(e) == "Invalid email"
Replace try-except blocks with pytest.raises used as a context manager. Pytest is the most popular Python testing
framework and provides excellent exception testing support.
When you expect no exception, simply call the code directly. Pytest will fail the test if an unexpected exception occurs.
When you expect an exception, use pytest.raises as a context manager to verify the exception type and optionally inspect its
properties.
def test_no_exception_thrown(user_service, valid_user):
# Simply call the method - pytest will fail if an exception is raised
user_service.register_user(valid_user)
When verifying that an exception is raised with pytest, use pytest.raises as a context manager. This gives you access to the exception
object for additional assertions using the match parameter or the value attribute.
import pytest
def test_exception_is_thrown(user_service, invalid_user):
with pytest.raises(ValidationError) as exc_info:
user_service.register_user(invalid_user)
assert str(exc_info.value) == "Invalid email"