pytest-reraise
pytest-reraise is a pytest plugin designed to make multi-threaded test cases fail when exceptions occur in background threads. Without it, exceptions in threads separate from the main test thread might not be caught by pytest, leading to silently passing tests. The current version is 2.1.2, with a release cadence that focuses on bug fixes and minor feature enhancements.
Common errors
-
ModuleNotFoundError: No module named 'pytest_reraise'
cause The `pytest-reraise` package is not installed in your current Python environment.fixRun `pip install pytest-reraise` to install the package. -
SyntaxError: invalid syntax (on Python 3.5 or older after upgrading to pytest-reraise 2.x)
cause `pytest-reraise` dropped support for Python 3.5 in version 2.0.0, requiring Python 3.6.1 or newer.fixUpgrade your Python interpreter to 3.6.1 or newer, or downgrade `pytest-reraise` to a compatible version: `pip install "pytest-reraise<2.0.0"`. -
Test passes unexpectedly despite exception in a background thread.
cause The function executing in the background thread was not properly wrapped with `pytest_reraise.Reraise.wrap()` or an instance's `wrap()` method.fixModify your `threading.Thread` target to explicitly wrap the function: `threading.Thread(target=Reraise.wrap(your_function_that_raises))`.
Warnings
- breaking Python 3.5 support was officially dropped in version 2.0.0. If you are using an older Python version, you must either upgrade Python or pin `pytest-reraise` to `<2.0.0`.
- gotcha pytest-reraise only intercepts exceptions from functions explicitly wrapped with `Reraise.wrap()` (or an instance's `wrap()` method). It does not globally monkey-patch all thread exceptions.
- gotcha An `AttributeError` could occur when `pytest-reraise` is used alongside non-test plugins like `pytest-black` or `pytest-flake8`.
Install
-
pip install pytest-reraise
Imports
- Reraise
from pytest_reraise import Reraise
Quickstart
import threading
from pytest_reraise import Reraise
import pytest
def test_threaded_exception_is_caught():
# This test will fail due to the ValueError in the thread
# because pytest-reraise ensures the exception is re-raised.
# Option 1: Instantiate Reraise
reraise_instance = Reraise()
def func_with_error():
raise ValueError("This exception should fail the test!")
thread_with_error = threading.Thread(target=reraise_instance.wrap(func_with_error))
thread_with_error.start()
thread_with_error.join()
# Option 2: Use the class method (introduced in v2.1.0)
def another_func_with_error():
# Example of a division by zero
_ = 1 / 0
thread_with_another_error = threading.Thread(target=Reraise.wrap(another_func_with_error))
thread_with_another_error.start()
thread_with_another_error.join()
# To run this example:
# 1. Save it as `test_example.py`
# 2. Run `pytest test_example.py` in your terminal.
# Expected outcome: Both parts of the test will raise exceptions and cause the test to fail.