- Introduced a new activity to load model metadata from the model store. - Refactored training logic to utilize new model metadata and improved parameter handling. - Updated the `TrainModelParams` class to include additional fields for model configuration. - Replaced deprecated utility functions with a custom train-test split implementation. - Removed unused utility functions and cleaned up the data manager repository. - Adjusted experiment tracking to include model-specific metadata in notifications.
669 lines
28 KiB
Python
669 lines
28 KiB
Python
"""Unit tests for TrainModelParams with 100% coverage."""
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture
|
|
def valid_train_params_dict():
|
|
"""Create a valid dictionary for TrainModelParams."""
|
|
return {
|
|
'variable_columns': ['var1', 'var2'],
|
|
'lag_train': {'var1': 5, 'var2': 5},
|
|
'lag_val': {'var1': 3, 'var2': 3},
|
|
'target_variable': 'target',
|
|
'rem_static_win': True,
|
|
'low_lim': {'var1': 0.0, 'var2': 1.0},
|
|
'upp_lim': {'var1': 10.0, 'var2': 20.0},
|
|
'window': 10,
|
|
'use_scaler': True,
|
|
'include_ar': False,
|
|
'bucket_name': 'test-bucket',
|
|
'file_name': 'test-file.csv',
|
|
'line_separator': ',',
|
|
'decimal_separator': '.',
|
|
'train_size': 80,
|
|
'shuffle': True,
|
|
'experiment_run_id': 1,
|
|
'removed_intervals': [],
|
|
'model_name': 'Linear Regression',
|
|
'degree': 1,
|
|
'interaction_only': False,
|
|
'nan_treatment': 'drop',
|
|
'start_date': None,
|
|
'end_date': None,
|
|
'scaler_name': 'Standard Scaler',
|
|
'support_filters': {},
|
|
'static_threshold': None,
|
|
}
|
|
|
|
|
|
def test_train_model_params_from_dict_success(valid_train_params_dict):
|
|
"""Test TrainModelParams.from_dict with valid data."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
assert params.variable_columns == ['var1', 'var2']
|
|
assert params.lag_train == {'var1': 5, 'var2': 5}
|
|
assert params.lag_val == {'var1': 3, 'var2': 3}
|
|
assert params.target_variable == 'target'
|
|
assert params.rem_static_win is True
|
|
assert params.low_lim == {'var1': 0.0, 'var2': 1.0}
|
|
assert params.upp_lim == {'var1': 10.0, 'var2': 20.0}
|
|
assert params.window == 10
|
|
assert params.use_scaler is True
|
|
assert params.include_ar is False
|
|
assert params.bucket_name == 'test-bucket'
|
|
assert params.file_name == 'test-file.csv'
|
|
assert params.line_separator == ','
|
|
assert params.decimal_separator == '.'
|
|
assert params.train_size == 80
|
|
assert params.shuffle is True
|
|
assert params.experiment_run_id == 1
|
|
assert params.removed_intervals == []
|
|
|
|
|
|
def test_train_model_params_check_none_raises_value_error():
|
|
"""Test _check_none raises ValueError when value is None."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
with pytest.raises(ValueError, match='test_field is required and cannot be None'):
|
|
TrainModelParams._check_none(None, str, 'test_field')
|
|
|
|
|
|
def test_train_model_params_check_none_raises_type_error():
|
|
"""Test _check_none raises TypeError when type is incorrect."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
with pytest.raises(TypeError, match='test_field must be of type str, but got int'):
|
|
TrainModelParams._check_none(123, str, 'test_field')
|
|
|
|
|
|
def test_train_model_params_check_none_success():
|
|
"""Test _check_none returns value when valid."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
result = TrainModelParams._check_none('test_value', str, 'test_field')
|
|
assert result == 'test_value'
|
|
|
|
|
|
def test_train_model_params_check_type_raises_type_error():
|
|
"""Test _check_type raises TypeError when type is incorrect."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
with pytest.raises(TypeError, match='test_field must be of type int, but got str'):
|
|
TrainModelParams._check_type('not_an_int', int, 'test_field')
|
|
|
|
|
|
def test_train_model_params_check_type_success():
|
|
"""Test _check_type returns value when valid."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
result = TrainModelParams._check_type(42, int, 'test_field')
|
|
assert result == 42
|
|
|
|
|
|
def test_train_model_params_check_type_with_none():
|
|
"""Test _check_type allows None value."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
result = TrainModelParams._check_type(None, str, 'test_field')
|
|
assert result is None
|
|
|
|
|
|
def test_train_model_params_from_dict_missing_field(valid_train_params_dict):
|
|
"""Test from_dict raises ValueError when required field is missing."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
del valid_train_params_dict['variable_columns']
|
|
|
|
with pytest.raises(ValueError, match='variable_columns is required and cannot be None'):
|
|
TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
|
|
def test_train_model_params_from_dict_wrong_type(valid_train_params_dict):
|
|
"""Test from_dict raises TypeError when field has wrong type."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['lag_train'] = 'not_a_dict'
|
|
|
|
with pytest.raises(TypeError, match='lag_train must be of type dict, but got str'):
|
|
TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
|
|
def test_train_model_params_from_dict_with_none_removed_intervals(valid_train_params_dict):
|
|
"""Test from_dict allows None for removed_intervals."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['removed_intervals'] = None
|
|
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
assert params.removed_intervals is None
|
|
|
|
|
|
def test_validate_business_rules_success(valid_train_params_dict):
|
|
"""Test validate_business_rules with valid parameters."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_train_size_too_low(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when train_size < 10."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['train_size'] = 5
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='train_size must be between 10 and 100, got 5'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_train_size_too_high(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when train_size > 100."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['train_size'] = 101
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='train_size must be between 10 and 100, got 101'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_empty_variable_columns(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when variable_columns is empty."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['variable_columns'] = []
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='variable_columns cannot be empty'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_negative_lag_train(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when lag_train is negative."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['lag_train'] = {'var1': -1, 'var2': 5}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='lag_train for var1 must be non-negative, got -1'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_negative_lag_val(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when lag_val is negative."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['lag_val'] = {'var1': 3, 'var2': -2}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='lag_val for var2 must be non-negative, got -2'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_negative_window(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when window is negative."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['window'] = -5
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='window must be non-negative, got -5'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_mismatched_limit_keys(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when low_lim and upp_lim keys don't match."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['low_lim'] = {'var1': 0.0}
|
|
valid_train_params_dict['upp_lim'] = {'var1': 10.0, 'var2': 20.0}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='low_lim and upp_lim must have the same keys'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_low_lim_greater_than_upp_lim(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when low_lim >= upp_lim."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['low_lim'] = {'var1': 15.0, 'var2': 1.0}
|
|
valid_train_params_dict['upp_lim'] = {'var1': 10.0, 'var2': 20.0}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='low_lim must be less than upp_lim for variable "var1"'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_low_lim_equal_to_upp_lim(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when low_lim == upp_lim."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['low_lim'] = {'var1': 10.0, 'var2': 1.0}
|
|
valid_train_params_dict['upp_lim'] = {'var1': 10.0, 'var2': 20.0}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='low_lim must be less than upp_lim for variable "var1"'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_empty_bucket_name(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when bucket_name is empty."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['bucket_name'] = ''
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='bucket_name cannot be empty or whitespace'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_whitespace_bucket_name(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when bucket_name is whitespace."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['bucket_name'] = ' '
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='bucket_name cannot be empty or whitespace'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_empty_file_name(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when file_name is empty."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['file_name'] = ''
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='file_name cannot be empty or whitespace'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_whitespace_file_name(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when file_name is whitespace."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['file_name'] = ' \t '
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='file_name cannot be empty or whitespace'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_model_name_empty(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when model_name is empty."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['model_name'] = ''
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='model_name cannot be empty or whitespace'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_train_size_boundary_10(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts train_size = 10 (lower boundary)."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['train_size'] = 10
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_train_size_boundary_100(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts train_size = 100 (upper boundary)."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['train_size'] = 100
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_zero_lag_train(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts lag_train = 0."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['lag_train'] = {'var1': 0, 'var2': 0}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_zero_lag_val(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts lag_val = 0."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['lag_val'] = {'var1': 0, 'var2': 0}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_zero_window(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts window = 0."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['window'] = 0
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_empty_limits(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts empty low_lim and upp_lim."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['low_lim'] = {}
|
|
valid_train_params_dict['upp_lim'] = {}
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
# ============================================================================
|
|
# Additional tests for 100% coverage
|
|
# ============================================================================
|
|
|
|
|
|
def test_validate_business_rules_degree_less_than_1(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when degree < 1."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['degree'] = 0
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='degree must be at least 1, got 0'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_invalid_nan_treatment(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error for invalid nan_treatment."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['nan_treatment'] = 'invalid_treatment'
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='nan_treatment must be one of'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_invalid_scaler_name(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error for invalid scaler_name."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['scaler_name'] = 'Invalid Scaler'
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='scaler_name must be one of'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_invalid_model_name(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error for invalid model_name."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['model_name'] = 'Invalid Model'
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='model_name must be one of'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_polynomial_regression_degree_less_than_2(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error for Polynomial Regression with degree < 2."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['model_name'] = 'Polynomial Regression'
|
|
valid_train_params_dict['degree'] = 1
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='degree must be at least 2 for Polynomial Regression'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_polynomial_regression_without_scaler(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error for Polynomial Regression without scaler."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['model_name'] = 'Polynomial Regression'
|
|
valid_train_params_dict['degree'] = 2
|
|
valid_train_params_dict['scaler_name'] = 'None'
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='scaler_name must be set'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_linear_regression_degree_not_1(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error for Linear Regression with degree != 1."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['model_name'] = 'Linear Regression'
|
|
valid_train_params_dict['degree'] = 2
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='degree must be 1 for Linear Regression, got 2'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_removed_intervals_not_list(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when removed_intervals item is not list."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['removed_intervals'] = ['not_a_list']
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='removed_intervals\\[0\\] must be a list or tuple'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_removed_intervals_too_short(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when removed_intervals item has < 2 elements."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['removed_intervals'] = [['only_one_element']]
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='removed_intervals\\[0\\] must have at least 2 elements'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_start_date_wrong_type(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when start_date is not a string."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
# Create params normally first, then modify start_date to bypass from_dict validation
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
params.start_date = 12345 # type: ignore
|
|
|
|
with pytest.raises(TypeError, match='start_date must be a string, got int'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_end_date_wrong_type(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when end_date is not a string."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
# Create params normally first, then modify end_date to bypass from_dict validation
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
params.end_date = 12345 # type: ignore
|
|
|
|
with pytest.raises(TypeError, match='end_date must be a string, got int'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_empty_target_variable(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when target_variable is empty."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['target_variable'] = ''
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='target_variable cannot be empty or whitespace'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_whitespace_target_variable(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when target_variable is whitespace."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['target_variable'] = ' '
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='target_variable cannot be empty or whitespace'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_valid_removed_intervals(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts valid removed_intervals."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['removed_intervals'] = [['2023-01-01', '2023-01-02']]
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_valid_start_and_end_date(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts valid start_date and end_date."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['start_date'] = '2023-01-01'
|
|
valid_train_params_dict['end_date'] = '2023-12-31'
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_invalid_date_format(valid_train_params_dict):
|
|
"""Test validate_business_rules raises when date_format is not allowed."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
params.date_format = 'yyyy-MM-dd'
|
|
|
|
with pytest.raises(ValueError, match='Invalid date_format'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_valid_date_format(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts allowed date_format."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
params.date_format = 'yyyy-MM-dd HH:mm:ss'
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_polynomial_regression_valid(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts valid Polynomial Regression config."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['model_name'] = 'Polynomial Regression'
|
|
valid_train_params_dict['degree'] = 2
|
|
valid_train_params_dict['scaler_name'] = 'Standard Scaler'
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_static_threshold_valid(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts valid static_threshold when rem_static_win is True."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['rem_static_win'] = True
|
|
valid_train_params_dict['static_threshold'] = 500
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_static_threshold_min_valid(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts static_threshold = 1."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['rem_static_win'] = True
|
|
valid_train_params_dict['static_threshold'] = 1
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_static_threshold_max_valid(valid_train_params_dict):
|
|
"""Test validate_business_rules accepts static_threshold = 1000."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['rem_static_win'] = True
|
|
valid_train_params_dict['static_threshold'] = 1000
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise
|
|
|
|
|
|
def test_validate_business_rules_static_threshold_below_min(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when static_threshold < 1."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['rem_static_win'] = True
|
|
valid_train_params_dict['static_threshold'] = 0
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='static_threshold must be between 1 and 1000, got 0'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_static_threshold_above_max(valid_train_params_dict):
|
|
"""Test validate_business_rules raises error when static_threshold > 1000."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['rem_static_win'] = True
|
|
valid_train_params_dict['static_threshold'] = 1001
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
with pytest.raises(ValueError, match='static_threshold must be between 1 and 1000, got 1001'):
|
|
params.validate_business_rules()
|
|
|
|
|
|
def test_validate_business_rules_static_threshold_none_when_rem_static_win_true(
|
|
valid_train_params_dict,
|
|
):
|
|
"""Test validate_business_rules accepts None static_threshold when rem_static_win is True."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['rem_static_win'] = True
|
|
valid_train_params_dict['static_threshold'] = None
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise - None is allowed
|
|
|
|
|
|
def test_validate_business_rules_static_threshold_ignored_when_rem_static_win_false(
|
|
valid_train_params_dict,
|
|
):
|
|
"""Test validate_business_rules ignores static_threshold when rem_static_win is False."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['rem_static_win'] = False
|
|
valid_train_params_dict['static_threshold'] = 5000 # Invalid value, but should be ignored
|
|
params = TrainModelParams.from_dict(valid_train_params_dict)
|
|
|
|
params.validate_business_rules() # Should not raise - validation skipped
|
|
|
|
|
|
def test_from_dict_static_threshold_type_error(valid_train_params_dict):
|
|
"""Test from_dict raises TypeError when static_threshold has wrong type."""
|
|
from model_manager.utils.models.train_model_params import TrainModelParams
|
|
|
|
valid_train_params_dict['static_threshold'] = 'not_an_int'
|
|
|
|
with pytest.raises(TypeError, match='static_threshold must be of type int, but got str'):
|
|
TrainModelParams.from_dict(valid_train_params_dict)
|