File size: 3,875 Bytes
d9f5c15 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
"""
Tests for solver configuration functionality.
Tests the create_solver_config factory function and dynamic termination time.
"""
import pytest
from portfolio_optimization.solver import create_solver_config
from portfolio_optimization.domain import SolverConfigModel
class TestCreateSolverConfig:
"""Tests for the create_solver_config factory function."""
def test_default_termination(self):
"""Default solver should terminate after 30 seconds."""
config = create_solver_config()
assert config.termination_config.spent_limit.seconds == 30
def test_custom_termination_60s(self):
"""Custom termination time of 60 seconds should be respected."""
config = create_solver_config(termination_seconds=60)
assert config.termination_config.spent_limit.seconds == 60
def test_custom_termination_10s(self):
"""Minimum termination time of 10 seconds should work."""
config = create_solver_config(termination_seconds=10)
assert config.termination_config.spent_limit.seconds == 10
def test_custom_termination_300s(self):
"""Maximum termination time of 300 seconds (5 min) should work."""
config = create_solver_config(termination_seconds=300)
assert config.termination_config.spent_limit.seconds == 300
def test_solver_config_has_correct_solution_class(self):
"""Solver config should reference PortfolioOptimizationPlan."""
from portfolio_optimization.domain import PortfolioOptimizationPlan
config = create_solver_config()
assert config.solution_class == PortfolioOptimizationPlan
def test_solver_config_has_correct_entity_class(self):
"""Solver config should include StockSelection entity."""
from portfolio_optimization.domain import StockSelection
config = create_solver_config()
assert StockSelection in config.entity_class_list
class TestSolverConfigModel:
"""Tests for the SolverConfigModel Pydantic model."""
def test_default_values(self):
"""SolverConfigModel should have default termination of 30 seconds."""
model = SolverConfigModel()
assert model.termination_seconds == 30
def test_custom_termination(self):
"""SolverConfigModel should accept custom termination."""
model = SolverConfigModel(termination_seconds=60)
assert model.termination_seconds == 60
def test_alias_serialization(self):
"""SolverConfigModel should serialize with camelCase alias."""
model = SolverConfigModel(termination_seconds=45)
data = model.model_dump(by_alias=True)
assert "terminationSeconds" in data
assert data["terminationSeconds"] == 45
def test_alias_deserialization(self):
"""SolverConfigModel should deserialize from camelCase."""
model = SolverConfigModel.model_validate({"terminationSeconds": 90})
assert model.termination_seconds == 90
def test_minimum_validation(self):
"""SolverConfigModel should reject termination < 10 seconds."""
with pytest.raises(ValueError):
SolverConfigModel(termination_seconds=5)
def test_maximum_validation(self):
"""SolverConfigModel should reject termination > 300 seconds."""
with pytest.raises(ValueError):
SolverConfigModel(termination_seconds=400)
def test_boundary_min(self):
"""SolverConfigModel should accept exactly 10 seconds."""
model = SolverConfigModel(termination_seconds=10)
assert model.termination_seconds == 10
def test_boundary_max(self):
"""SolverConfigModel should accept exactly 300 seconds."""
model = SolverConfigModel(termination_seconds=300)
assert model.termination_seconds == 300
|