Coverage for test/unit/elements/mapping/test_attribute.py: 94%
177 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
1"""Testing Attributes on Elements"""
3import unittest
5from bim2sim.kernel.decision import DecisionBunch, RealDecision
6from bim2sim.elements.base_elements import ProductBased
7from bim2sim.elements.mapping.attribute import Attribute
8from bim2sim.elements.mapping.units import ureg
9from test.unit.elements.helper import SetupHelperHVAC
10from bim2sim.utilities.types import AttributeDataSource
13class TestElement(ProductBased):
14 def __init__(self, *args, **kwargs):
15 super().__init__(*args, **kwargs)
16 self.x = 42
17 ifc_types = {}
19 def _func1(self, name):
20 return self.x
22 attr1 = Attribute(
23 unit=ureg.meter
24 )
25 attr2 = Attribute()
26 attr3 = Attribute()
27 attr4 = Attribute()
28 attr5 = Attribute(
29 functions=[_func1]
30 )
31 attr6 = Attribute(attr_type=str)
32 attr7 = Attribute(attr_type=bool)
35class TestElementInherited(TestElement):
36 def _func1(self, name):
37 return 43
40class TestAttribute(unittest.TestCase):
42 helper = SetupHelperHVAC()
44 def setUp(self):
45 self.subject = self.helper.element_generator(TestElement)
46 self.subject_inherited = self.helper.element_generator(
47 TestElementInherited)
49 def tearDown(self):
50 self.helper.reset()
52 def test_set_get(self):
53 """Test setting and getting valid attribute values"""
54 self.assertIsNone(self.subject.attr1)
56 self.subject.attr1 = 1.23
57 self.assertEqual(1.23 * ureg.meter, self.subject.attr1)
59 def test_type_consistence(self):
60 """Test value of type int remains as int, float as float, etc."""
61 self.assertIsNone(self.subject.attr1)
63 self.subject.attr1 = 0.2
64 self.assertIs(type(0.2), type(self.subject.attr1.magnitude))
66 self.subject.attr2 = 42
67 self.assertIs(42, self.subject.attr2)
69 self.subject.attr3 = True
70 self.assertIs(True, self.subject.attr3)
72 self.subject.attr4 = 'abc'
73 self.assertIs('abc', self.subject.attr4)
75 def test_attribute_manager(self):
76 """Test attribute manager"""
77 self.assertIsNone(self.subject.attr1)
79 self.assertEqual(10, len(self.subject.attributes),
80 "All Attributes should be registered in AttributeManager")
82 self.assertEqual(10, len(list(self.subject.attributes.names)))
84 self.assertIn('attr1', self.subject.attributes)
86 # set attribute
87 self.subject.attr1 = 1.
88 self.assertEqual(1. * ureg.meter, self.subject.attr1)
90 # set attribute manager value
91 self.subject.attributes['attr2'] = 4
92 self.assertEqual(self.subject.attr2, 4)
94 self.subject.attributes['attr3'] = True
95 self.assertEqual(True, self.subject.attr3)
97 def test_attribute_manager_unit(self):
98 """test get unit from manager"""
99 self.assertEqual(ureg.meter, self.subject.attributes.get_unit('attr1'))
101 def test_attribute_manager_names(self):
102 """test names of manager"""
104 target = {'attr1', 'attr2', 'attr3', 'attr4', 'attr5', 'attr6',
105 'attr7', 'name', 'volume', 'position'
106 }
107 found = set(self.subject.attributes.names)
108 self.assertEqual(target, found)
110 def test_set_invalid_attribute(self):
111 """Test setting an invalid attribute"""
112 with self.assertRaises(AttributeError):
113 self.subject.attributes.set('invalid_attribute', -1)
115 def test_get_invalid_attribute(self):
116 """Test getting an invalid attribute"""
117 with self.assertRaises(KeyError):
118 self.subject.attributes['invalid_attribute']
120 def test_from_function(self):
121 """test getting attribute from function"""
122 self.assertEqual(42, self.subject.attr5)
124 def test_attribute_reset(self):
125 """test reset an attribute"""
126 self.assertIsNone(self.subject.attr1)
128 # set attribute and check if it is correctly set
129 self.subject.attr1 = 0.2
130 self.assertIs(type(0.2), type(self.subject.attr1.magnitude))
132 # reset attribute and check that it's correctly set
133 self.subject.reset('attr1')
134 self.assertIsNone(self.subject.attr1)
135 # status should be "NOT_AVAILABLE"
136 status = self.subject.attributes['attr1'][1]
137 self.assertEqual(status, "NOT_AVAILABLE")
139 # set attribute again and check if it is correctly set
140 self.subject.attr1 = 0.2
141 self.assertIs(type(0.2), type(self.subject.attr1.magnitude))
143 def test_attribute_by_function_reset(self):
144 """test reset an attribute that is calculated by a function."""
145 self.assertEqual(42, self.subject.attr5)
146 self.subject.reset('attr5')
147 self.assertEqual(42, self.subject.attr5)
149 def test_attribute_reset_with_function_change(self):
150 """test reset an attribute with a function change in meantime."""
151 # check that the attribute is correctly calculated
152 self.assertEqual(42, self.subject.attr5)
153 # change the value based on that the function calculates the attribute
154 self.subject.x = 10
155 # the calculated value still remains the same
156 self.assertEqual(42, self.subject.attr5)
157 # reset the attribute to make sure that is calculated again
158 self.subject.reset('attr5')
159 # check again that the new calculation returns the correct value
160 self.assertEqual(10, self.subject.attr5)
162 def test_attribute_reset(self):
163 """test reset an attribute"""
164 self.assertIsNone(self.subject.attr1)
166 # set attribute and check if it is correctly set
167 self.subject.attr1 = 0.2
168 self.assertIs(type(0.2), type(self.subject.attr1.magnitude))
170 # reset attribute and check that it's correctly set
171 self.subject.reset('attr1')
172 self.assertIsNone(self.subject.attr1)
173 # status should be "NOT_AVAILABLE"
174 status = self.subject.attributes['attr1'][1]
175 self.assertEqual(status, "NOT_AVAILABLE")
177 # set attribute again and check if it is correctly set
178 self.subject.attr1 = 0.2
179 self.assertIs(type(0.2), type(self.subject.attr1.magnitude))
181 def test_from_function_inheritance(self):
182 self.assertEqual(43, self.subject_inherited.attr5)
185class TestAttributeDecisions(unittest.TestCase):
187 def test_request_attribute(self):
188 """Test to set attribute by decision."""
189 ele = TestElement()
190 self.assertIsNone(ele.attr2)
191 ele.attributes['attr2']
192 decision = ele.request('attr2')
193 self.assertIsNone(ele.attr2)
195 decision.value = 1
196 self.assertEqual(1, ele.attr2)
198 def test_request_requested(self):
199 """Test requesting an already requested attribute"""
200 ele = TestElement()
201 decision1 = ele.request('attr2')
202 decision2 = ele.request('attr2')
203 self.assertIs(decision1, decision2)
204 decision1.value = 5
205 self.assertEqual(5, ele.attr2)
207 def test_request_available(self):
208 """Test requesting an already available attribute"""
209 ele = TestElement()
210 ele.attr3 = 7
211 decision1 = ele.request('attr3')
212 decision2 = ele.request('attr5') # from function
214 self.assertIsNone(decision1)
215 self.assertIsNone(decision2)
217 def test_request_many_attributes(self):
218 """Test getting many decisions for elements and answer them together."""
219 ele1 = TestElement()
220 ele1.attr3 = 3
221 ele2 = TestElement()
222 attrs = ('attr1', 'attr2', 'attr3')
223 bunch = DecisionBunch()
224 for attr in attrs:
225 for ele in (ele1, ele2):
226 decision = ele.request(attr)
227 if decision:
228 bunch.append(decision)
230 for d in bunch:
231 d.value = 42
233 self.assertEqual(42 * ureg.meter, ele1.attr1)
234 self.assertEqual(42 * ureg.meter, ele2.attr1)
235 self.assertEqual(3, ele1.attr3)
236 self.assertEqual(42, ele2.attr3)
238 def test_request_decision_bool(self):
239 """Test acceptance of input formats for different attr_types"""
240 ele = TestElement()
241 decision1 = ele.request('attr1')
242 decision2 = ele.request('attr6')
243 decision3 = ele.request('attr7')
244 decision1.value = 5.0
245 decision2.value = 'test'
246 decision3.value = True
248 def test_external_decision(self):
249 """Test to set attribute by external decision."""
250 ele = TestElement()
251 ext_decision = RealDecision("For attr2")
252 decision = ele.request('attr2', ext_decision)
253 self.assertIs(ext_decision, decision)
255 ext_decision.value = 99
256 self.assertEqual(99, ele.attr2)
259class TestAttributeDataSource(unittest.TestCase):
260 def test_data_source(self):
261 ele = TestElement()
262 ele.attr3 = 3
263 decision = ele.request('attr2')
264 decision.value = 10
265 data_source_attr1 = ele.attributes['attr1'][-1]
266 data_source_attr3 = ele.attributes['attr3'][-1]
267 data_source_attr4 = ele.attributes['attr4'][-1]
268 # get attribute values to make __get__ function run
269 attr2 = ele.attr2
270 attr5 = ele.attr5
271 data_source_attr2 = ele.attributes['attr2'][-1]
272 data_source_attr5 = ele.attributes['attr5'][-1]
274 self.assertEqual(data_source_attr1, None)
275 self.assertEqual(data_source_attr2, AttributeDataSource.decision)
276 self.assertEqual(
277 data_source_attr3, AttributeDataSource.manual_overwrite)
278 self.assertEqual(data_source_attr4, None)
279 self.assertEqual(data_source_attr5, AttributeDataSource.function)
282if __name__ == '__main__':
283 unittest.main()