Skip to content

Commit e5440a9

Browse files
committed
test: add comprehensive tests for max_failure_cases feature
Add tests to verify the new max_failure_cases configuration works correctly across different scenarios. - Add config tests for environment variable parsing - Add config_context tests for temporary overrides - Add pandas backend tests for error message formatting - Add polars backend tests for error message formatting - Test default (100), custom limits, -1 (unlimited), and 0 (none)
1 parent 8273bb2 commit e5440a9

3 files changed

Lines changed: 284 additions & 0 deletions

File tree

tests/pandas/test_config.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
("cache_dataframe", False, False, False, False),
5353
("keep_cached_dataframe", True, True, False, False),
5454
("keep_cached_dataframe", False, False, False, False),
55+
("max_failure_cases", 10, 10, 100, 100),
56+
("max_failure_cases", 5, 5, 100, 100),
57+
("max_failure_cases", -1, -1, 100, 100),
5558
],
5659
)
5760
def test_config_context(
@@ -106,6 +109,10 @@ def test_config_context(
106109
("cache_dataframe", True, False),
107110
("keep_cached_dataframe", False, True),
108111
("keep_cached_dataframe", True, False),
112+
("max_failure_cases", 10, 20),
113+
("max_failure_cases", 5, 15),
114+
("max_failure_cases", -1, 10),
115+
("max_failure_cases", 10, -1),
109116
],
110117
)
111118
def test_nested_config_context(setting, outer_value, inner_value):
@@ -143,3 +150,23 @@ def test_pandera_validation_enabled_from_env_vars():
143150
del os.environ["PANDERA_VALIDATION_ENABLED"]
144151
config = _config_from_env_vars()
145152
assert config.validation_enabled
153+
154+
155+
def test_pandera_max_failure_cases_from_env_vars():
156+
"""Test that max_failure_cases can be set from environment variables."""
157+
158+
os.environ["PANDERA_MAX_FAILURE_CASES"] = "10"
159+
config = _config_from_env_vars()
160+
assert config.max_failure_cases == 10
161+
162+
os.environ["PANDERA_MAX_FAILURE_CASES"] = "0"
163+
config = _config_from_env_vars()
164+
assert config.max_failure_cases == 0
165+
166+
os.environ["PANDERA_MAX_FAILURE_CASES"] = "invalid"
167+
config = _config_from_env_vars()
168+
assert config.max_failure_cases == 100
169+
170+
del os.environ["PANDERA_MAX_FAILURE_CASES"]
171+
config = _config_from_env_vars()
172+
assert config.max_failure_cases == 100
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
"""Tests for max_failure_cases error message formatting."""
2+
3+
import pandas as pd
4+
import pytest
5+
6+
import pandera.pandas as pa
7+
from pandera import Check, Column, DataFrameSchema
8+
from pandera.config import config_context
9+
10+
11+
def test_default_max_failure_cases():
12+
"""Test that default max_failure_cases is 100."""
13+
14+
# Create a DataFrame with 150 failing values
15+
df = pd.DataFrame({
16+
"col1": range(150), # All values will fail the check
17+
})
18+
19+
schema = DataFrameSchema({
20+
"col1": Column(int, Check.greater_than(200))
21+
})
22+
23+
# Test default behavior (should limit to 100)
24+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
25+
schema.validate(df, lazy=True)
26+
27+
error_message = str(exc_info.value)
28+
# Should show first 100 values and a summary
29+
assert "0, 1, 2, 3, 4" in error_message
30+
assert "99" in error_message # Should show up to 99 (100th value)
31+
assert "50 more failure cases (150 total)" in error_message
32+
assert "149" not in error_message # Should NOT show the last value
33+
34+
35+
def test_max_failure_cases_pandas():
36+
"""Test that max_failure_cases limits error message length for pandas."""
37+
38+
# Create a DataFrame with many failing values
39+
df = pd.DataFrame({
40+
"col1": range(100), # All values will fail the check
41+
})
42+
43+
schema = DataFrameSchema({
44+
"col1": Column(int, Check.greater_than(100))
45+
})
46+
47+
# Test without limit (default behavior)
48+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
49+
schema.validate(df, lazy=True)
50+
51+
error_message = str(exc_info.value)
52+
# Should contain all 100 failure cases in the error message
53+
assert "0, 1, 2, 3, 4, 5, 6, 7, 8, 9" in error_message
54+
assert "99" in error_message
55+
56+
# Test with max_failure_cases = 5
57+
with config_context(max_failure_cases=5):
58+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
59+
schema.validate(df, lazy=True)
60+
61+
error_message = str(exc_info.value)
62+
# Should only show first 5 failure cases
63+
assert "0, 1, 2, 3, 4" in error_message
64+
# Should show summary of omitted cases
65+
assert "95 more failure cases (100 total)" in error_message
66+
# Should NOT contain later values
67+
assert "99" not in error_message
68+
69+
# Test with max_failure_cases = 1
70+
with config_context(max_failure_cases=1):
71+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
72+
schema.validate(df, lazy=True)
73+
74+
error_message = str(exc_info.value)
75+
# Should only show first failure case
76+
assert "failure cases: 0" in error_message
77+
# Should show summary of omitted cases
78+
assert "99 more failure cases (100 total)" in error_message
79+
80+
81+
def test_max_failure_cases_multiple_checks():
82+
"""Test max_failure_cases with multiple failing checks."""
83+
84+
df = pd.DataFrame({
85+
"col1": range(50),
86+
"col2": range(50, 100),
87+
})
88+
89+
schema = DataFrameSchema({
90+
"col1": Column(int, [
91+
Check.greater_than(100), # All 50 values fail
92+
Check.less_than(-10), # All 50 values fail
93+
]),
94+
"col2": Column(int, Check.greater_than(200)) # All 50 values fail
95+
})
96+
97+
with config_context(max_failure_cases=3):
98+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
99+
schema.validate(df, lazy=True)
100+
101+
error_message = str(exc_info.value)
102+
103+
# Each check should show only 3 failure cases
104+
assert "0, 1, 2 ... and 47 more failure cases (50 total)" in error_message
105+
assert "50, 51, 52 ... and 47 more failure cases (50 total)" in error_message
106+
107+
108+
def test_max_failure_cases_edge_cases():
109+
"""Test edge cases for max_failure_cases."""
110+
111+
df = pd.DataFrame({
112+
"col1": [1, 2, 3],
113+
})
114+
115+
schema = DataFrameSchema({
116+
"col1": Column(int, Check.greater_than(10))
117+
})
118+
119+
# Test with max_failure_cases = 0 (should show no failure cases)
120+
with config_context(max_failure_cases=0):
121+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
122+
schema.validate(df, lazy=True)
123+
124+
error_message = str(exc_info.value)
125+
# Should show summary only
126+
assert "... 3 failure cases" in error_message
127+
128+
# Test with max_failure_cases greater than actual failures
129+
with config_context(max_failure_cases=10):
130+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
131+
schema.validate(df, lazy=True)
132+
133+
error_message = str(exc_info.value)
134+
# Should show all 3 failure cases
135+
assert "1, 2, 3" in error_message
136+
# Should NOT show summary since all cases are shown
137+
assert "more failure cases" not in error_message
138+
139+
# Test with max_failure_cases = -1 (default, no limit)
140+
with config_context(max_failure_cases=-1):
141+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
142+
schema.validate(df, lazy=True)
143+
144+
error_message = str(exc_info.value)
145+
# Should show all failure cases
146+
assert "1, 2, 3" in error_message
147+
assert "more failure cases" not in error_message
148+
149+
150+
def test_max_failure_cases_env_var(monkeypatch):
151+
"""Test that max_failure_cases can be set via environment variable."""
152+
153+
df = pd.DataFrame({
154+
"col1": range(20),
155+
})
156+
157+
schema = DataFrameSchema({
158+
"col1": Column(int, Check.greater_than(50))
159+
})
160+
161+
# Set environment variable
162+
monkeypatch.setenv("PANDERA_MAX_FAILURE_CASES", "7")
163+
164+
# Need to reload config to pick up env var
165+
from pandera import config
166+
config.CONFIG = config._config_from_env_vars()
167+
config._CONTEXT_CONFIG = config.copy(config.CONFIG)
168+
169+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
170+
schema.validate(df, lazy=True)
171+
172+
error_message = str(exc_info.value)
173+
# Should show first 7 failure cases
174+
assert "0, 1, 2, 3, 4, 5, 6" in error_message
175+
# Should show summary of omitted cases
176+
assert "13 more failure cases (20 total)" in error_message
177+
178+
# Reset config
179+
monkeypatch.delenv("PANDERA_MAX_FAILURE_CASES", raising=False)
180+
config.CONFIG = config._config_from_env_vars()
181+
config._CONTEXT_CONFIG = config.copy(config.CONFIG)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""Tests for max_failure_cases error message formatting in Polars."""
2+
3+
import polars as pl
4+
import pytest
5+
6+
import pandera.polars as pa
7+
from pandera.config import config_context
8+
9+
10+
def test_max_failure_cases_polars():
11+
"""Test that max_failure_cases limits error message length for polars."""
12+
13+
# Create a DataFrame with many failing values
14+
df = pl.DataFrame({
15+
"col1": range(100), # All values will fail the check
16+
})
17+
18+
schema = pa.DataFrameSchema({
19+
"col1": pa.Column(int, pa.Check.greater_than(100))
20+
})
21+
22+
# Test without limit (default behavior)
23+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
24+
schema.validate(df, lazy=True)
25+
26+
error_message = str(exc_info.value)
27+
# Polars shows failure cases differently (as a list of dicts)
28+
assert "failure case examples:" in error_message
29+
30+
# Test with max_failure_cases = 5
31+
with config_context(max_failure_cases=5):
32+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
33+
schema.validate(df, lazy=True)
34+
35+
error_message = str(exc_info.value)
36+
# Should show summary of omitted cases
37+
assert "95 more failure cases (100 total)" in error_message
38+
39+
# Test with max_failure_cases = 1
40+
with config_context(max_failure_cases=1):
41+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
42+
schema.validate(df, lazy=True)
43+
44+
error_message = str(exc_info.value)
45+
# Should show summary of omitted cases
46+
assert "99 more failure cases (100 total)" in error_message
47+
48+
49+
def test_max_failure_cases_polars_edge_cases():
50+
"""Test edge cases for max_failure_cases in polars."""
51+
52+
df = pl.DataFrame({
53+
"col1": [1, 2, 3],
54+
})
55+
56+
schema = pa.DataFrameSchema({
57+
"col1": pa.Column(int, pa.Check.greater_than(10))
58+
})
59+
60+
# Test with max_failure_cases greater than actual failures
61+
with config_context(max_failure_cases=10):
62+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
63+
schema.validate(df, lazy=True)
64+
65+
error_message = str(exc_info.value)
66+
# Should NOT show summary since all cases are shown
67+
assert "more failure cases" not in error_message
68+
69+
# Test with max_failure_cases = -1 (default, no limit)
70+
with config_context(max_failure_cases=-1):
71+
with pytest.raises(pa.errors.SchemaErrors) as exc_info:
72+
schema.validate(df, lazy=True)
73+
74+
error_message = str(exc_info.value)
75+
# Should NOT show summary
76+
assert "more failure cases" not in error_message

0 commit comments

Comments
 (0)