Skip to content

Commit 41e6e38

Browse files
test: add integration tests for min_value parameter
Add min_value to the configuration precedence test to verify it is correctly resolved from vars, model config, and test config levels. Add a parametrized behavioral test that validates min_value suppresses anomaly detection when the metric value falls below the threshold. Ref: elementary-data/elementary#2177 Made-with: Cursor
1 parent eea1122 commit 41e6e38

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

integration_tests/tests/test_anomaly_test_configuration.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class ParamValues(Generic[T]):
6161
{"count": 90, "period": "day"},
6262
),
6363
"exclude_final_results": ParamValues(*(["1 = 1"] * 3)),
64+
"min_value": ParamValues(0.5, 1.0, 2.0),
6465
}
6566

6667

@@ -88,6 +89,7 @@ def get_value(key: str):
8889
"freshness_column": None, # Deprecated
8990
"dimensions": None, # should only be set at the test level,
9091
"exclude_final_results": get_value("exclude_final_results"),
92+
"min_value": get_value("min_value"),
9193
"exclude_detection_period_from_training": None,
9294
}
9395

integration_tests/tests/test_column_anomalies.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,60 @@ def test_volume_anomaly_static_data_drop(
215215
assert test_result["status"] == expected_result
216216

217217

218+
@Parametrization.autodetect_parameters()
219+
@Parametrization.case(
220+
name="anomaly_detected_without_min_value",
221+
expected_result="fail",
222+
min_value=None,
223+
)
224+
@Parametrization.case(
225+
name="anomaly_suppressed_with_min_value",
226+
expected_result="pass",
227+
min_value=5,
228+
)
229+
def test_column_anomalies_with_min_value(
230+
test_id: str,
231+
dbt_project: DbtProject,
232+
expected_result: str,
233+
min_value,
234+
):
235+
now = datetime.utcnow()
236+
data = [
237+
{TIMESTAMP_COLUMN: cur_date.strftime(DATE_FORMAT), "superhero": "Batman"}
238+
for cur_date in generate_dates(base_date=now, step=timedelta(days=1))
239+
if cur_date < now - timedelta(days=1)
240+
] * 50
241+
data += [
242+
{
243+
TIMESTAMP_COLUMN: (now - timedelta(days=1)).strftime(DATE_FORMAT),
244+
"superhero": "Batman",
245+
}
246+
] * 47
247+
data += [
248+
{
249+
TIMESTAMP_COLUMN: (now - timedelta(days=1)).strftime(DATE_FORMAT),
250+
"superhero": None,
251+
}
252+
] * 3
253+
254+
# Training: 50 rows/day, 0 nulls -> null_count = 0
255+
# Detection: 50 rows, 3 nulls -> null_count = 3
256+
# Without min_value: null_count 3 vs training avg 0 -> anomaly detected (fail)
257+
# With min_value=5: null_count 3 < 5 -> anomaly suppressed (pass)
258+
259+
test_args = {
260+
**DBT_TEST_ARGS,
261+
"time_bucket": {"period": "day", "count": 1},
262+
"column_anomalies": ["null_count"],
263+
}
264+
if min_value is not None:
265+
test_args["min_value"] = min_value
266+
test_result = dbt_project.test(
267+
test_id, DBT_TEST_NAME, test_args, data=data, test_column="superhero"
268+
)
269+
assert test_result["status"] == expected_result
270+
271+
218272
def test_anomalyless_column_anomalies_group(test_id: str, dbt_project: DbtProject):
219273
utc_today = datetime.utcnow().date()
220274
data: List[Dict[str, Any]] = [

0 commit comments

Comments
 (0)