• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SMTorg / smt-optim / 28806559135

06 Jul 2026 04:23PM UTC coverage: 87.169% (+0.6%) from 86.529%
28806559135

push

github

web-flow
  Fix: Resolve RSCV constraint bug, correct variance margins for relaxation, and fix CI Coveralls (#21)

109 of 110 new or added lines in 4 files covered. (99.09%)

360 existing lines in 43 files now uncovered.

3757 of 4310 relevant lines covered (87.17%)

1.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.22
/src/tests/test_unit/test_benchmarks.py
1
import unittest
2✔
2

3
import warnings
2✔
4
import numpy as np
2✔
5
import scipy.stats as stats
2✔
6

7
import smt.design_space as ds
2✔
8
from smt.sampling_methods import LHS
2✔
9
from smt.applications.mixed_integer import MixedIntegerSamplingMethod
2✔
10

11
from smt_optim.benchmarks.registry import list_problems, get_problem
2✔
12

13

14
class TestBenchmarkProblems(unittest.TestCase):
2✔
15

16
    def test_all_benchmark_attributes(self):
2✔
17

18

19
        required_attributes = [
2✔
20
            "name",
21
            "num_dim",
22
            "num_obj",
23
            "num_cstr",
24
            "num_fidelity",
25
            # "bounds",
26
            # "objective",
27
            # "constraints",
28
        ]
29

30

31
        problems = list_problems(
2✔
32
            num_dim=None,
33
            num_obj=None,
34
            num_cstr=None,
35
            num_fidelity=None,
36
        )
37

38

39
        for prob in problems:
2✔
40

41
            with self.subTest(problem=prob.__class__.__name__):
2✔
42

43
                # test that prob has all the required attributes -> .num_dim, num_cstr, num_obj, etc.
44
                for attr in required_attributes:
2✔
45
                    value = getattr(prob, attr)
2✔
46

47
                    self.assertIsNotNone(
2✔
48
                        value,
49
                        msg=f"{prob.__class__.__name__}: '{attr}' was not implemented"
50
                    )
51

52

53
                # test that it has the corresponding number of objective, constraints and fidelities.
54

55
                # test num_dim
56
                if isinstance(prob.num_dim, int):
2✔
57
                    pass
2✔
58
                elif prob.num_dim == "variable":
2✔
59
                    prob.set_dim(2)
2✔
60
                    if not isinstance(prob.num_obj, int):
2✔
UNCOV
61
                        raise NotImplementedError()
×
62
                else:
UNCOV
63
                    raise TypeError()
×
64

65
                # test bounds
66
                if prob.bounds is not None:
2✔
67

68
                    self.assertEqual(
2✔
69
                        prob.bounds.shape,
70
                        (prob.num_dim, 2),
71
                        msg=f"{prob.name}: bounds should have shape "
72
                            f"({prob.num_dim}, 2)",
73
                    )
74

75
                    lower = prob.bounds[:, 0]
2✔
76
                    upper = prob.bounds[:, 1]
2✔
77

78
                    self.assertTrue(
2✔
79
                        np.all(lower < upper),
80
                        msg=f"{prob.name}: lower bounds must be < upper bounds",
81
                    )
82

83
                else:
84
                    self.assertIsInstance(prob.design_space, ds.DesignSpace)
2✔
85

86

87
                # test num_obj
88
                # single objective
89
                if prob.num_obj == 1:
2✔
90
                    if prob.num_fidelity == 1:
2✔
91
                        self.assertTrue(callable(prob.objective))
2✔
92
                    else:
93
                        self.assertEqual(len(prob.objective), prob.num_fidelity)
2✔
94

95
                # multi-objective
UNCOV
96
                elif prob.num_obj > 1:
×
UNCOV
97
                    self.assertIsInstance(prob.objective, list)
×
UNCOV
98
                    self.assertEqual(len(prob.objective), prob.num_obj)
×
99

100
                # num_obj < 1 ?
101
                else:
UNCOV
102
                    raise ValueError()
×
103

104

105
                # test_num_cstr
106
                if prob.num_cstr > 0:
2✔
107
                    self.assertEqual(len(prob.constraints), prob.num_cstr)
2✔
108
                else:
109
                    self.assertTrue(prob.constraints is None)
2✔
110

111
                if prob.num_obj == 1:
2✔
112
                    objective = [prob.objective]
2✔
113
                else:
UNCOV
114
                    objective = prob.objective
×
115

116
                # test_fidelity
117
                if prob.num_fidelity > 1:
2✔
118
                    for obj_idx in range(prob.num_obj):
2✔
119
                        self.assertEqual(len(objective[obj_idx]), prob.num_fidelity)
2✔
120

121
                    for cstr_idx in range(prob.num_cstr):
2✔
122
                        self.assertEqual(len(prob.constraints[cstr_idx]), prob.num_fidelity)
2✔
123

124
                # test that all objectives and constraints are callables and respect their domain.
125
                num_sample = 3
2✔
126

127
                if isinstance(prob.bounds, np.ndarray):
2✔
128
                    sampler = stats.qmc.LatinHypercube(d=prob.num_dim, seed=0)
2✔
129
                    doe = sampler.random(num_sample)
2✔
130
                    doe = stats.qmc.scale(doe, prob.bounds[:, 0], prob.bounds[:, 1])
2✔
131

132
                elif isinstance(prob.design_space, ds.DesignSpace):
2✔
133
                    # sampler = LHS(xlimits=prob.design_space.get_unfolded_num_bounds(),
134
                    #               criterion="ese",
135
                    #               seed=0)
136
                    # doe = sampler(num_sample)
137

138
                    sampler = MixedIntegerSamplingMethod(LHS, prob.design_space, criterion="ese", seed=0)
2✔
139
                    doe = sampler(10)
2✔
140

141
                else:
UNCOV
142
                    raise TypeError()
×
143

144
                for idx in range(doe.shape[0]):
2✔
145

146
                    for lvl in range(prob.num_fidelity):
2✔
147
                        for obj_idx in range(prob.num_obj):
2✔
148
                            if prob.num_fidelity == 1:
2✔
149
                                val = objective[obj_idx](doe[idx, :])
2✔
150
                            else:
151
                                val = objective[obj_idx][lvl](doe[idx, :])
2✔
152

153
                            is_scalar = isinstance(val, float)
2✔
154
                            is_np_1d = (isinstance(val, np.ndarray) and val.ndim == 1)
2✔
155
                            self.assertTrue(is_scalar or is_np_1d)
2✔
156

157

158
                        for cstr_idx in range(prob.num_cstr):
2✔
159
                            if prob.num_fidelity == 1:
2✔
160
                                val = prob.constraints[cstr_idx](doe[idx, :])
2✔
161
                            else:
162
                                val = prob.constraints[cstr_idx][lvl](doe[idx, :])
2✔
163

164
                            is_scalar = isinstance(val, float)
2✔
165
                            is_np_1d = (isinstance(val, np.ndarray) and val.ndim == 1)
2✔
166
                            self.assertTrue(is_scalar or is_np_1d)
2✔
167

168

169
    def test_get_problem_returns_independent_instances(self):
2✔
170
        prob1 = get_problem("Alos")
2✔
171
        prob2 = get_problem("Alos")
2✔
172

173
        # Different objects
174
        self.assertIsNot(prob1, prob2)
2✔
175

176
        # Mutate one instance
177
        original = prob2.num_dim
2✔
178
        prob1.num_dim = 999
2✔
179

180
        # Other instance is unchanged
181
        self.assertIsNot(prob1, prob2)
2✔
182
        self.assertEqual(prob2.num_dim, original)
2✔
183

184
        prob1.tags.append("new_tag")
2✔
185
        self.assertNotIn("new_tag", prob2.tags)
2✔
186

187

188
    def test_list_problems_returns_independent_instances(self):
2✔
189
        probs1 = list_problems()
2✔
190
        probs2 = list_problems()
2✔
191

192
        # Lists themselves are different objects
193
        self.assertIsNot(probs1, probs2)
2✔
194

195
        # Problem instances are different objects
196
        for p1, p2 in zip(probs1, probs2):
2✔
197
            self.assertIsNot(p1, p2)
2✔
198

199

200
if __name__ == "__main__":
2✔
UNCOV
201
    unittest.main()
×
202

203

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc