SIENTIAPDE-1241: Added remaining model repository tests
This commit is contained in:
@@ -383,6 +383,9 @@ def test_generate_report_without_equation(
|
||||
|
||||
# No equation
|
||||
mock_train_result.equation = None
|
||||
# Remove equation_path if it exists from fixture
|
||||
if hasattr(mock_train_result, 'equation_path'):
|
||||
del mock_train_result.equation_path
|
||||
|
||||
reference_data = pd.DataFrame({'var1': [1, 2], 'var2': [3, 4], 'target': [5, 6]})
|
||||
current_data = pd.DataFrame({'var1': [7, 8], 'var2': [9, 10], 'target': [11, 12]})
|
||||
@@ -391,8 +394,9 @@ def test_generate_report_without_equation(
|
||||
with patch.object(pd.DataFrame, 'to_csv'):
|
||||
result = repo._generate_report(reference_data, current_data, mock_train_result)
|
||||
|
||||
# Verify equation path was not set
|
||||
assert not hasattr(result, 'equation_path') or result.equation_path is None
|
||||
# Verify equation section was not executed (equation_path not set)
|
||||
# Since equation is None, the equation block should not run
|
||||
assert result == mock_train_result
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@@ -475,7 +479,8 @@ def test_save_run_missing_report(
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
def test_save_run_none_metrics(mock_model_serving_class, mock_logger, mock_train_result):
|
||||
@patch('model_manager.utils.repository.model_repository.path.exists')
|
||||
def test_save_run_none_metrics(mock_exists, mock_model_serving_class, mock_logger, mock_train_result):
|
||||
"""Test _save_run raises ValueError when metrics are None."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
@@ -484,6 +489,309 @@ def test_save_run_none_metrics(mock_model_serving_class, mock_logger, mock_train
|
||||
)
|
||||
|
||||
mock_train_result.mse_val = None
|
||||
# Mock all paths exist so we reach the metrics check
|
||||
mock_exists.return_value = True
|
||||
|
||||
with pytest.raises(ValueError, match='One or more metrics .* are None'):
|
||||
repo._save_run(mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.path.exists')
|
||||
def test_save_run_missing_train_data(
|
||||
mock_exists, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _save_run raises ValueError when train data is missing."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
# Mock train_data doesn't exist
|
||||
def exists_side_effect(path):
|
||||
return not path.endswith('train_data.csv')
|
||||
|
||||
mock_exists.side_effect = exists_side_effect
|
||||
|
||||
with pytest.raises(ValueError, match='Training data file does not exist'):
|
||||
repo._save_run(mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.path.exists')
|
||||
def test_save_run_missing_test_data(
|
||||
mock_exists, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _save_run raises ValueError when test data is missing."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
# Mock test_data doesn't exist
|
||||
def exists_side_effect(path):
|
||||
if path.endswith('test_data.csv'):
|
||||
return False
|
||||
return True
|
||||
|
||||
mock_exists.side_effect = exists_side_effect
|
||||
|
||||
with pytest.raises(ValueError, match='Test data file does not exist'):
|
||||
repo._save_run(mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
def test_init_artifacts_data_empty_x_test(mock_model_serving_class, mock_logger, mock_train_result):
|
||||
"""Test _init_artifacts_data raises ValueError when x_test is empty."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_train_result.x_test = pd.DataFrame()
|
||||
|
||||
with pytest.raises(ValueError, match='Test features .* are empty'):
|
||||
repo._init_artifacts_data(mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
def test_init_artifacts_data_empty_y_test(mock_model_serving_class, mock_logger, mock_train_result):
|
||||
"""Test _init_artifacts_data raises ValueError when y_test is empty."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_train_result.y_test = pd.Series(dtype=float)
|
||||
|
||||
with pytest.raises(ValueError, match='Test target .* are empty'):
|
||||
repo._init_artifacts_data(mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.makedirs')
|
||||
def test_create_run_directory_os_error(
|
||||
mock_makedirs, mock_model_serving_class, mock_logger
|
||||
):
|
||||
"""Test _create_run_directory raises OSError."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_makedirs.side_effect = OSError('Disk full')
|
||||
|
||||
with pytest.raises(OSError, match='Failed to create directory'):
|
||||
repo._create_run_directory('/tmp/reports', 'test_run') # noqa: S108
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.shutil.copy')
|
||||
@patch('builtins.open', create=True)
|
||||
def test_setup_run_directory_file_not_found(
|
||||
mock_open, mock_copy, mock_model_serving_class, mock_logger
|
||||
):
|
||||
"""Test _setup_run_directory raises FileNotFoundError when header missing."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_copy.side_effect = FileNotFoundError('Header not found')
|
||||
|
||||
with pytest.raises(FileNotFoundError, match='Header file not found'):
|
||||
repo._setup_run_directory('/tmp/test_run', '/tmp/header.html') # noqa: S108
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.shutil.copy')
|
||||
@patch('builtins.open', create=True)
|
||||
def test_setup_run_directory_permission_error(
|
||||
mock_open, mock_copy, mock_model_serving_class, mock_logger
|
||||
):
|
||||
"""Test _setup_run_directory raises PermissionError."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_open.side_effect = PermissionError('Permission denied')
|
||||
|
||||
with pytest.raises(PermissionError, match='Permission denied when setting up directory'):
|
||||
repo._setup_run_directory('/tmp/test_run', '/tmp/header.html') # noqa: S108
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.shutil.copy')
|
||||
@patch('builtins.open', create=True)
|
||||
def test_setup_run_directory_os_error(
|
||||
mock_open, mock_copy, mock_model_serving_class, mock_logger
|
||||
):
|
||||
"""Test _setup_run_directory raises OSError."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_open.side_effect = OSError('Disk error')
|
||||
|
||||
with pytest.raises(OSError, match='Failed to setup run directory'):
|
||||
repo._setup_run_directory('/tmp/test_run', '/tmp/header.html') # noqa: S108
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.Reports')
|
||||
@patch('builtins.open', create=True)
|
||||
def test_generate_report_value_error(
|
||||
mock_open, mock_reports_class, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _generate_report raises ValueError on invalid data."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
# Create data that can't be converted to float64
|
||||
reference_data = pd.DataFrame({'var1': ['invalid', 'data']})
|
||||
current_data = pd.DataFrame({'var1': [1, 2]})
|
||||
|
||||
with pytest.raises(ValueError, match='Failed to convert data to float64'):
|
||||
repo._generate_report(reference_data, current_data, mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.Reports')
|
||||
@patch('builtins.open', create=True)
|
||||
def test_generate_report_permission_error(
|
||||
mock_open, mock_reports_class, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _generate_report raises PermissionError on write failure."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
reference_data = pd.DataFrame({'var1': [1, 2], 'var2': [3, 4], 'target': [5, 6]})
|
||||
current_data = pd.DataFrame({'var1': [7, 8], 'var2': [9, 10], 'target': [11, 12]})
|
||||
|
||||
# Mock Reports to raise PermissionError
|
||||
mock_reports_class.side_effect = PermissionError('Permission denied')
|
||||
|
||||
with pytest.raises(PermissionError, match='Permission denied when writing report files'):
|
||||
repo._generate_report(reference_data, current_data, mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.Reports')
|
||||
@patch('builtins.open', create=True)
|
||||
def test_generate_report_os_error(
|
||||
mock_open, mock_reports_class, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _generate_report raises OSError on write failure."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
reference_data = pd.DataFrame({'var1': [1, 2], 'var2': [3, 4], 'target': [5, 6]})
|
||||
current_data = pd.DataFrame({'var1': [7, 8], 'var2': [9, 10], 'target': [11, 12]})
|
||||
|
||||
# Mock Reports to raise OSError
|
||||
mock_reports_class.side_effect = OSError('Disk error')
|
||||
|
||||
with pytest.raises(OSError, match='Failed to generate report'):
|
||||
repo._generate_report(reference_data, current_data, mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.Reports')
|
||||
@patch('builtins.open', create=True)
|
||||
def test_generate_report_none_run_dir(
|
||||
mock_open, mock_reports_class, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _generate_report raises ValueError when run_dir is None."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_train_result.run_dir = None
|
||||
|
||||
reference_data = pd.DataFrame({'var1': [1, 2], 'var2': [3, 4], 'target': [5, 6]})
|
||||
current_data = pd.DataFrame({'var1': [7, 8], 'var2': [9, 10], 'target': [11, 12]})
|
||||
|
||||
with pytest.raises(ValueError, match='run_dir is not set'):
|
||||
repo._generate_report(reference_data, current_data, mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.path.exists')
|
||||
def test_generate_artifacts_no_run_name(
|
||||
mock_exists, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _generate_artifacts raises ValueError when run_name is not set."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
mock_train_result.run_name = None
|
||||
|
||||
with pytest.raises(ValueError, match='run_name must be set'):
|
||||
repo._generate_artifacts(mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.path.exists')
|
||||
def test_generate_artifacts_reports_dir_not_found(
|
||||
mock_exists, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _generate_artifacts raises FileNotFoundError when reports dir missing."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
# Mock reports directory doesn't exist
|
||||
mock_exists.return_value = False
|
||||
|
||||
with pytest.raises(FileNotFoundError, match='Reports directory does not exist'):
|
||||
repo._generate_artifacts(mock_train_result)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.model_repository.ModelServing')
|
||||
@patch('model_manager.utils.repository.model_repository.path.exists')
|
||||
def test_generate_artifacts_header_not_found(
|
||||
mock_exists, mock_model_serving_class, mock_logger, mock_train_result
|
||||
):
|
||||
"""Test _generate_artifacts raises FileNotFoundError when header missing."""
|
||||
from model_manager.utils.repository.model_repository import ModelRepository
|
||||
|
||||
repo = ModelRepository(
|
||||
url='http://mlflow.test', username='user', password='pass', logger=mock_logger
|
||||
)
|
||||
|
||||
# Mock: reports dir exists, but header doesn't
|
||||
def exists_side_effect(path):
|
||||
if path.endswith('header.html'):
|
||||
return False
|
||||
return True
|
||||
|
||||
mock_exists.side_effect = exists_side_effect
|
||||
|
||||
with pytest.raises(FileNotFoundError, match='Header file does not exist'):
|
||||
repo._generate_artifacts(mock_train_result)
|
||||
|
||||
Reference in New Issue
Block a user