Warning Capture and Assertion
Purpose
This component addresses the need to **capture, check, and assert Python warnings** emitted during test execution. Warnings often signal deprecated features, potential issues, or future incompatibilities in the code under test. By providing a systematic way to record and verify these warnings, this subtopic ensures tests can explicitly validate that expected warnings occur (or do not occur), improving test accuracy and developer awareness.
Unlike the broader parent topic—which includes general capturing and reporting of warnings and unraisable exceptions—this subtopic focuses specifically on **fixtures and context managers** that enable fine-grained control and assertions over warning emissions during tests.
Functionality
At its core, this subtopic provides:
A fixture named
recwarnthat returns aWarningsRecorderinstance for recording all warnings during test function execution.Context managers and helper functions (
warns,deprecated_call) that assert specific warning types are raised, optionally matching warning messages using regex or substrings.A specialized class
WarningsCheckerthat extendsWarningsRecorderto check if expected warnings occurred, fail tests if not, and re-emit unmatched warnings to avoid hiding unexpected warnings.
Key Workflows
Recording Warnings with a Fixture
The
recwarnfixture can be used in test functions to collect all warnings:def test_something(recwarn): warnings.warn("deprecated", DeprecationWarning) recorded = recwarn.list assert any(w.category == DeprecationWarning for w in recorded)This provides access to all warnings raised during a test, enabling detailed inspection or conditional assertions.
Asserting Expected Warnings with Context Managers
The
warnsfunction can be used as a context manager to assert that a particular warning (or set of warnings) is emitted:with pytest.warns(DeprecationWarning, match="deprecated feature"): some_deprecated_api_call()If no matching warning is raised, the test fails with a descriptive message.
Deprecation-Specific Assertions
The
deprecated_callhelper wrapswarnsfor common deprecation-related warnings (DeprecationWarning,PendingDeprecationWarning,FutureWarning), simplifying their assertion:with pytest.deprecated_call(): old_api()Function Call Wrappers
Both
warnsanddeprecated_callcan also be called as functions passing a callable and its arguments. They assert the expected warnings occur during the call, returning the function’s result.Warning Matching and Re-emission
WarningsCheckerchecks if the expected warnings occurred and if their messages match an optional regex. It re-emits unmatched warnings after the context to prevent hiding unexpected warnings, preserving pytest’s transparency.
Simplified Code Snippet Illustrating Context Manager Usage
with pytest.warns(WarningType, match="regex pattern") as w:
call_code_that_warns()
# Access recorded warnings
assert any(warning for warning in w if matches_condition(warning))
Integration with Parent Topic and Other Subtopics
Parent Topic: While the parent topic covers capturing and reporting warnings and unraisable exceptions globally, this subtopic provides developer-facing APIs (fixtures and context managers) that allow precise control and assertion of warnings within individual tests.
Complementary Subtopics:
Works alongside Warning Filters and Reporting by enabling tests to assert expected warnings while filters control which warnings are shown.
Supports Unraisable Exception Management by focusing on catchable warnings within test code, complementing handling of exceptions that cannot be caught normally.
Integrates with Test Execution and Reporting by causing test failures if expected warnings do not occur, influencing test outcomes.
New Contribution: This subtopic introduces the
recwarnfixture andwarns/deprecated_callcontext managers as explicit tools to capture and assert warnings, a level of interaction not detailed in the parent or sibling subtopics.
Diagram: Warning Capture and Assertion Workflow
flowchart TD
Start[Start Test Execution]
EnterRecwarn[Enter recwarn Fixture (WarningsRecorder)]
TestCode[Run Test Code]
EmitWarning[Emit Warnings]
RecordWarning[Record Warning in Recorder]
ExitRecwarn[Exit recwarn Fixture]
AssertWarns[Use warns()/deprecated_call() to Assert Warnings]
FailIfNoWarn[Fail Test if Expected Warning Missing]
ReemitUnmatched[Re-emit Unmatched Warnings]
End[End Test Execution]
Start --> EnterRecwarn
EnterRecwarn --> TestCode
TestCode --> EmitWarning
EmitWarning --> RecordWarning
RecordWarning --> TestCode
TestCode --> ExitRecwarn
ExitRecwarn --> AssertWarns
AssertWarns --> FailIfNoWarn
FailIfNoWarn --> ReemitUnmatched
ReemitUnmatched --> End
This flowchart illustrates how warnings are captured during test execution via the `recwarn` fixture, how the `warns` or `deprecated_call` context managers assert the presence of expected warnings, and how unmatched warnings are re-emitted to maintain transparency.
This subtopic equips test authors with explicit mechanisms to verify warnings, improving test precision and fostering better code quality by ensuring warnings are neither missed nor silently ignored.