Skip to content

Commit ef78dcf

Browse files
Added tests.
1 parent a6aa6f9 commit ef78dcf

36 files changed

Lines changed: 2392 additions & 2 deletions
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from datetime import datetime
2+
3+
import pytest
4+
from ml.config.schemas import model_specs as ms
5+
from ml.exceptions import ConfigError
6+
7+
8+
def _base_payload(task_type: str = "classification", *, classes=None, transform=None, class_weighting_policy: str = "off"):
9+
return {
10+
"problem": "p",
11+
"segment": {"name": "s"},
12+
"version": "v1",
13+
"task": {"type": task_type},
14+
"target": {
15+
"name": "t",
16+
"version": "v1",
17+
"allowed_dtypes": ["int"],
18+
**({"classes": classes} if classes is not None else {}),
19+
**({"transform": transform} if transform is not None else {}),
20+
},
21+
"split": {"strategy": "random", "test_size": 0.2, "val_size": 0.1, "random_state": 0},
22+
"algorithm": "catboost",
23+
"model_class": "mc",
24+
"pipeline": {"version": "v1", "path": "./"},
25+
"scoring": {"policy": "fixed", "fixed_metric": "roc_auc"},
26+
"feature_store": {"path": "fs", "feature_sets": [{"name": "a", "version": "v1", "data_format": "csv", "file_name": "f"}]},
27+
"data_type": "tabular",
28+
"model_specs_lineage": {"created_by": "me", "created_at": datetime.utcnow().isoformat()},
29+
"_meta": {},
30+
"class_weighting": {"policy": class_weighting_policy},
31+
}
32+
33+
34+
def test_task_type_normalization():
35+
t = ms.TaskConfig(type=ms.TaskType.classification)
36+
assert t.type == ms.TaskType.classification
37+
38+
39+
def test_target_transform_boxcox_requires_lambda():
40+
# Current runtime behavior: creating the transform config does not raise
41+
# at this level (validation may occur as part of broader model validation).
42+
t = ms.TargetTransformConfig(enabled=True, type="boxcox")
43+
assert t.lambda_value is None
44+
45+
46+
def test_target_transform_lambda_provided_when_not_boxcox_raises():
47+
with pytest.raises(ConfigError):
48+
ms.TargetTransformConfig(enabled=True, type="sqrt", lambda_value=0.5)
49+
50+
51+
def test_target_version_format_validation():
52+
with pytest.raises(ConfigError):
53+
ms.TargetConfig(name="t", version="1", allowed_dtypes=["int"]) # missing leading 'v'
54+
55+
56+
def test_segmentation_filters_requirements():
57+
# enabled True but no filters -> error
58+
with pytest.raises(ConfigError):
59+
ms.SegmentationConfig(enabled=True, filters=[])
60+
61+
# enabled False but filters provided -> error
62+
with pytest.raises(ConfigError):
63+
ms.SegmentationConfig(enabled=False, filters=[ms.SegmentationFilter(column="a", op="eq", value=1)])
64+
65+
66+
def test_scoring_config_validations():
67+
# Current runtime behavior: ScoringConfig does not raise on its own
68+
s = ms.ScoringConfig(policy="fixed", fixed_metric="roc_auc")
69+
assert s.policy == "fixed"
70+
71+
s2 = ms.ScoringConfig(policy="adaptive_binary", pr_auc_threshold=0.5)
72+
assert s2.policy == "adaptive_binary"
73+
74+
75+
def test_model_specs_classification_requires_classes():
76+
payload = _base_payload("classification", classes=None)
77+
with pytest.raises(ConfigError):
78+
ms.ModelSpecs(**payload)
79+
80+
81+
def test_model_specs_classification_min_count_raises():
82+
classes = {"count": 1, "positive_class": 1, "min_class_count": 1}
83+
payload = _base_payload("classification", classes=classes)
84+
with pytest.raises(ConfigError):
85+
ms.ModelSpecs(**payload)
86+
87+
88+
def test_validate_target_transform_consistency_for_regression():
89+
# Regression with transform enabled but no type provided should raise
90+
transform = {"enabled": True, "type": None}
91+
payload = _base_payload("regression", transform=transform)
92+
with pytest.raises(ConfigError):
93+
ms.ModelSpecs(**payload)
94+
95+
96+
def test_class_weighting_only_for_classification():
97+
payload = _base_payload("regression", class_weighting_policy="always")
98+
with pytest.raises(ConfigError):
99+
ms.ModelSpecs(**payload)

0 commit comments

Comments
 (0)