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

1"""Testing Attributes on Elements""" 

2 

3import unittest 

4 

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 

11 

12 

13class TestElement(ProductBased): 

14 def __init__(self, *args, **kwargs): 

15 super().__init__(*args, **kwargs) 

16 self.x = 42 

17 ifc_types = {} 

18 

19 def _func1(self, name): 

20 return self.x 

21 

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) 

33 

34 

35class TestElementInherited(TestElement): 

36 def _func1(self, name): 

37 return 43 

38 

39 

40class TestAttribute(unittest.TestCase): 

41 

42 helper = SetupHelperHVAC() 

43 

44 def setUp(self): 

45 self.subject = self.helper.element_generator(TestElement) 

46 self.subject_inherited = self.helper.element_generator( 

47 TestElementInherited) 

48 

49 def tearDown(self): 

50 self.helper.reset() 

51 

52 def test_set_get(self): 

53 """Test setting and getting valid attribute values""" 

54 self.assertIsNone(self.subject.attr1) 

55 

56 self.subject.attr1 = 1.23 

57 self.assertEqual(1.23 * ureg.meter, self.subject.attr1) 

58 

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) 

62 

63 self.subject.attr1 = 0.2 

64 self.assertIs(type(0.2), type(self.subject.attr1.magnitude)) 

65 

66 self.subject.attr2 = 42 

67 self.assertIs(42, self.subject.attr2) 

68 

69 self.subject.attr3 = True 

70 self.assertIs(True, self.subject.attr3) 

71 

72 self.subject.attr4 = 'abc' 

73 self.assertIs('abc', self.subject.attr4) 

74 

75 def test_attribute_manager(self): 

76 """Test attribute manager""" 

77 self.assertIsNone(self.subject.attr1) 

78 

79 self.assertEqual(10, len(self.subject.attributes), 

80 "All Attributes should be registered in AttributeManager") 

81 

82 self.assertEqual(10, len(list(self.subject.attributes.names))) 

83 

84 self.assertIn('attr1', self.subject.attributes) 

85 

86 # set attribute 

87 self.subject.attr1 = 1. 

88 self.assertEqual(1. * ureg.meter, self.subject.attr1) 

89 

90 # set attribute manager value 

91 self.subject.attributes['attr2'] = 4 

92 self.assertEqual(self.subject.attr2, 4) 

93 

94 self.subject.attributes['attr3'] = True 

95 self.assertEqual(True, self.subject.attr3) 

96 

97 def test_attribute_manager_unit(self): 

98 """test get unit from manager""" 

99 self.assertEqual(ureg.meter, self.subject.attributes.get_unit('attr1')) 

100 

101 def test_attribute_manager_names(self): 

102 """test names of manager""" 

103 

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) 

109 

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) 

114 

115 def test_get_invalid_attribute(self): 

116 """Test getting an invalid attribute""" 

117 with self.assertRaises(KeyError): 

118 self.subject.attributes['invalid_attribute'] 

119 

120 def test_from_function(self): 

121 """test getting attribute from function""" 

122 self.assertEqual(42, self.subject.attr5) 

123 

124 def test_attribute_reset(self): 

125 """test reset an attribute""" 

126 self.assertIsNone(self.subject.attr1) 

127 

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)) 

131 

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") 

138 

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)) 

142 

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) 

148 

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) 

161 

162 def test_attribute_reset(self): 

163 """test reset an attribute""" 

164 self.assertIsNone(self.subject.attr1) 

165 

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)) 

169 

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") 

176 

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)) 

180 

181 def test_from_function_inheritance(self): 

182 self.assertEqual(43, self.subject_inherited.attr5) 

183 

184 

185class TestAttributeDecisions(unittest.TestCase): 

186 

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) 

194 

195 decision.value = 1 

196 self.assertEqual(1, ele.attr2) 

197 

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) 

206 

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 

213 

214 self.assertIsNone(decision1) 

215 self.assertIsNone(decision2) 

216 

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) 

229 

230 for d in bunch: 

231 d.value = 42 

232 

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) 

237 

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 

247 

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) 

254 

255 ext_decision.value = 99 

256 self.assertEqual(99, ele.attr2) 

257 

258 

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] 

273 

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) 

280 

281 

282if __name__ == '__main__': 

283 unittest.main()