Skip to content

Commit 60f3f2a

Browse files
committed
fixup! Implement ListComponents
Add tests for Bounds
1 parent 21c4c55 commit 60f3f2a

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

tests/metrics/test_bounds.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# License: MIT
2+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3+
4+
"""Tests for the Bounds class."""
5+
6+
from dataclasses import dataclass
7+
8+
import pytest
9+
from frequenz.api.common.v1.metrics import bounds_pb2
10+
11+
from frequenz.client.microgrid.metrics import Bounds
12+
from frequenz.client.microgrid.metrics._bounds_proto import bounds_from_proto
13+
14+
15+
@dataclass(frozen=True, kw_only=True)
16+
class ProtoConversionTestCase:
17+
"""Test case for protobuf conversion."""
18+
19+
name: str
20+
"""Description of the test case."""
21+
22+
has_lower: bool
23+
"""Whether to include lower bound in the protobuf message."""
24+
25+
has_upper: bool
26+
"""Whether to include upper bound in the protobuf message."""
27+
28+
lower: float | None
29+
"""The lower bound value to set."""
30+
31+
upper: float | None
32+
"""The upper bound value to set."""
33+
34+
35+
def test_bounds_creation() -> None:
36+
"""Test creation of Bounds with valid values."""
37+
bounds = Bounds(lower=-10.0, upper=10.0)
38+
assert bounds.lower == -10.0
39+
assert bounds.upper == 10.0
40+
41+
42+
def test_bounds_invalid_values() -> None:
43+
"""Test that Bounds creation fails with invalid values."""
44+
with pytest.raises(
45+
ValueError, match="Lower bound must be less than or equal to upper bound"
46+
):
47+
Bounds(lower=10.0, upper=-10.0)
48+
49+
50+
def test_bounds_str_representation() -> None:
51+
"""Test string representation of Bounds."""
52+
bounds = Bounds(lower=-10.0, upper=10.0)
53+
assert str(bounds) == "[-10.0, 10.0]"
54+
55+
56+
def test_bounds_equality() -> None:
57+
"""Test equality comparison of Bounds objects."""
58+
bounds1 = Bounds(lower=-10.0, upper=10.0)
59+
bounds2 = Bounds(lower=-10.0, upper=10.0)
60+
bounds3 = Bounds(lower=-5.0, upper=5.0)
61+
62+
assert bounds1 == bounds2
63+
assert bounds1 != bounds3
64+
assert bounds2 != bounds3
65+
66+
67+
def test_bounds_hash() -> None:
68+
"""Test that Bounds objects can be used in sets and as dictionary keys."""
69+
bounds1 = Bounds(lower=-10.0, upper=10.0)
70+
bounds2 = Bounds(lower=-10.0, upper=10.0)
71+
bounds3 = Bounds(lower=-5.0, upper=5.0)
72+
73+
bounds_set = {bounds1, bounds2, bounds3}
74+
assert len(bounds_set) == 2 # bounds1 and bounds2 are equal
75+
76+
bounds_dict = {bounds1: "test1", bounds3: "test2"}
77+
assert len(bounds_dict) == 2
78+
79+
80+
@pytest.mark.parametrize(
81+
"case",
82+
[
83+
ProtoConversionTestCase(
84+
name="all fields present",
85+
has_lower=True,
86+
has_upper=True,
87+
lower=-10.0,
88+
upper=10.0,
89+
),
90+
ProtoConversionTestCase(
91+
name="only lower bound",
92+
has_lower=True,
93+
has_upper=False,
94+
lower=-10.0,
95+
upper=None,
96+
),
97+
ProtoConversionTestCase(
98+
name="only upper bound",
99+
has_lower=False,
100+
has_upper=True,
101+
lower=None,
102+
upper=10.0,
103+
),
104+
ProtoConversionTestCase(
105+
name="no bounds",
106+
has_lower=False,
107+
has_upper=False,
108+
lower=None,
109+
upper=None,
110+
),
111+
],
112+
ids=lambda case: case.name,
113+
)
114+
def test_bounds_from_proto(case: ProtoConversionTestCase) -> None:
115+
"""Test conversion from protobuf message to Bounds.
116+
117+
Args:
118+
case: Test case parameters
119+
120+
Raises:
121+
AssertionError: If the conversion doesn't match expected values
122+
"""
123+
proto = bounds_pb2.Bounds()
124+
if case.has_lower and case.lower is not None:
125+
proto.lower = case.lower
126+
if case.has_upper and case.upper is not None:
127+
proto.upper = case.upper
128+
129+
bounds = bounds_from_proto(proto)
130+
131+
assert bounds.lower == case.lower
132+
assert bounds.upper == case.upper

0 commit comments

Comments
 (0)