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