0
# Assertions and Exception Handling
1
2
Context managers and utilities for asserting exceptions, warnings, and performing approximate numerical comparisons. These tools provide comprehensive testing capabilities for exception handling, warning validation, and floating-point comparisons.
3
4
## Capabilities
5
6
### Exception Assertion
7
8
Context manager for asserting that specific exceptions are raised during code execution.
9
10
```python { .api }
11
def raises(expected_exception, *, match=None, check=None):
12
"""
13
Context manager for asserting exceptions are raised.
14
15
Parameters:
16
- expected_exception: Exception class or tuple of exception classes
17
- match: Regex pattern that exception message should match
18
- check: Callable to perform additional validation on exception
19
20
Returns:
21
RaisesExc context manager or ExceptionInfo if used as function decorator
22
"""
23
24
class RaisesExc:
25
"""Context manager for exception assertion with type checking."""
26
27
def matches(self, expected_exception) -> bool:
28
"""Check if captured exception matches expected type."""
29
30
def __enter__(self) -> ExceptionInfo:
31
"""Enter context manager."""
32
33
def __exit__(self, exc_type, exc_val, exc_tb) -> bool:
34
"""Exit context manager and validate exception."""
35
```
36
37
**Usage Example:**
38
39
```python
40
import pytest
41
import re
42
43
# Basic exception assertion
44
def test_division_by_zero():
45
with pytest.raises(ZeroDivisionError):
46
1 / 0
47
48
# With message matching
49
def test_invalid_input():
50
with pytest.raises(ValueError, match=r"invalid.*input"):
51
process_input("invalid data")
52
53
# Multiple exception types
54
def test_file_operations():
55
with pytest.raises((FileNotFoundError, PermissionError)):
56
open("/nonexistent/file", "r")
57
58
# Custom validation
59
def test_custom_exception():
60
with pytest.raises(CustomError) as exc_info:
61
raise_custom_error()
62
63
assert exc_info.value.error_code == 123
64
assert "custom message" in str(exc_info.value)
65
```
66
67
### Exception Group Assertion
68
69
Context manager for asserting ExceptionGroup exceptions (Python 3.11+).
70
71
```python { .api }
72
class RaisesGroup:
73
"""Context manager for ExceptionGroup assertion."""
74
75
def matches(self, expected_exceptions) -> bool:
76
"""Check if exception group contains expected exceptions."""
77
78
def expected_type(self) -> type:
79
"""Get the expected exception group type."""
80
```
81
82
### Exception Information
83
84
Provides detailed information about caught exceptions with advanced introspection capabilities.
85
86
```python { .api }
87
class ExceptionInfo:
88
"""Information about caught exceptions."""
89
90
type: type # Exception type
91
value: Exception # Exception instance
92
tb: types.TracebackType # Traceback object
93
typename: str # Exception type name as string
94
traceback: Traceback # pytest's enhanced traceback
95
96
def exconly(self, tryshort: bool = False) -> str:
97
"""Return exception as string without traceback."""
98
99
def errisinstance(self, exc: type | tuple[type, ...]) -> bool:
100
"""Check if exception is instance of given type(s)."""
101
102
def match(self, regexp: str | re.Pattern) -> bool:
103
"""Check if exception message matches regex pattern."""
104
105
def group_contains(self, expected_exception, *, match=None, depth: int = 1) -> bool:
106
"""Check if exception group contains specific exception type."""
107
```
108
109
### Warning Assertion
110
111
Context manager for asserting that specific warnings are issued during code execution.
112
113
```python { .api }
114
def warns(expected_warning, *, match=None):
115
"""
116
Context manager for asserting warnings are issued.
117
118
Parameters:
119
- expected_warning: Warning class or tuple of warning classes
120
- match: Regex pattern that warning message should match
121
122
Returns:
123
WarningsRecorder context manager
124
"""
125
126
class WarningsRecorder:
127
"""Records warnings during test execution."""
128
129
def pop(self, cls=Warning):
130
"""Remove and return last warning of given class."""
131
132
def clear(self):
133
"""Clear all recorded warnings."""
134
135
@property
136
def list(self) -> list:
137
"""List of all recorded warnings."""
138
```
139
140
**Usage Example:**
141
142
```python
143
import pytest
144
import warnings
145
146
def test_deprecation_warning():
147
with pytest.warns(DeprecationWarning):
148
warnings.warn("This is deprecated", DeprecationWarning)
149
150
def test_warning_message():
151
with pytest.warns(UserWarning, match=r"custom.*warning"):
152
warnings.warn("This is a custom warning", UserWarning)
153
154
def test_multiple_warnings():
155
with pytest.warns() as record:
156
warnings.warn("Warning 1", UserWarning)
157
warnings.warn("Warning 2", FutureWarning)
158
159
assert len(record) == 2
160
assert record[0].category == UserWarning
161
assert record[1].category == FutureWarning
162
```
163
164
### Deprecation Call Assertion
165
166
Context manager for asserting that deprecation warnings are issued during function calls.
167
168
```python { .api }
169
def deprecated_call(func=None, *args, **kwargs):
170
"""
171
Context manager for asserting deprecation warnings.
172
173
Parameters:
174
- func: Function to call (optional, can be used as context manager)
175
- args: Arguments to pass to function
176
- kwargs: Keyword arguments to pass to function
177
178
Returns:
179
WarningsRecorder if used as context manager, function result if used as function call
180
"""
181
```
182
183
**Usage Example:**
184
185
```python
186
import pytest
187
188
# As context manager
189
def test_deprecated_usage():
190
with pytest.deprecated_call():
191
deprecated_function()
192
193
# As function call
194
def test_deprecated_function():
195
result = pytest.deprecated_call(deprecated_function, arg1, arg2)
196
assert result == expected_value
197
```
198
199
### Approximate Comparisons
200
201
Create approximate comparison objects for floating-point numbers, sequences, and mappings.
202
203
```python { .api }
204
def approx(expected, rel=None, abs=None, nan_ok: bool = False):
205
"""
206
Create approximate comparison objects for floating-point numbers.
207
208
Parameters:
209
- expected: Expected value (number, sequence, or mapping)
210
- rel: Relative tolerance (default: 1e-6)
211
- abs: Absolute tolerance (default: 1e-12)
212
- nan_ok: Whether NaN values should be considered equal
213
214
Returns:
215
ApproxBase object (ApproxScalar, ApproxSequence, ApproxMapping, or ApproxNumpy)
216
"""
217
```
218
219
**Usage Example:**
220
221
```python
222
import pytest
223
import math
224
225
def test_float_comparison():
226
assert 0.1 + 0.2 == pytest.approx(0.3)
227
assert math.pi == pytest.approx(3.14159, rel=1e-4)
228
229
def test_sequence_comparison():
230
assert [0.1 + 0.2, 0.2 + 0.3] == pytest.approx([0.3, 0.5])
231
232
def test_dict_comparison():
233
result = {"a": 0.1 + 0.2, "b": 0.2 + 0.3}
234
expected = {"a": 0.3, "b": 0.5}
235
assert result == pytest.approx(expected)
236
237
def test_custom_tolerance():
238
assert 1.0001 == pytest.approx(1.0, abs=1e-3)
239
assert 1.01 == pytest.approx(1.0, rel=0.02)
240
241
def test_nan_handling():
242
assert float('nan') == pytest.approx(float('nan'), nan_ok=True)
243
```
244
245
## Types
246
247
```python { .api }
248
from typing import Any, Callable, Pattern, Union
249
import re
250
import types
251
252
# Type definitions for exception handling
253
ExceptionClass = type[Exception]
254
ExceptionTuple = tuple[ExceptionClass, ...]
255
ExceptionSpec = Union[ExceptionClass, ExceptionTuple]
256
257
MatchPattern = Union[str, Pattern[str]]
258
CheckFunction = Callable[[Exception], bool]
259
260
class ApproxBase:
261
"""Base class for approximate comparison objects."""
262
pass
263
264
class ApproxScalar(ApproxBase):
265
"""Approximate comparison for scalar values."""
266
pass
267
268
class ApproxSequence(ApproxBase):
269
"""Approximate comparison for sequences."""
270
pass
271
272
class ApproxMapping(ApproxBase):
273
"""Approximate comparison for mappings."""
274
pass
275
276
class ApproxNumpy(ApproxBase):
277
"""Approximate comparison for numpy arrays."""
278
pass
279
```