Spaces:
Sleeping
Sleeping
rmm
commited on
Commit
·
5312fc3
1
Parent(s):
a847100
test: for setters and for to_dict method of InputObservation
Browse files- the last test here puts appropriate data into an InputObservation,
mimicks going through all the classification stages, and then
generates the dict that will be transmitted to the dataset/HF server
- tests/test_input_observation.py +157 -0
tests/test_input_observation.py
CHANGED
@@ -38,6 +38,7 @@ class MockUploadedFile(BytesIO):
|
|
38 |
|
39 |
self._file_urls = [None,]
|
40 |
|
|
|
41 |
@pytest.fixture
|
42 |
def mock_uploadedFile():
|
43 |
class MockGUIClass(MagicMock):
|
@@ -198,6 +199,7 @@ def test_input_observation_invalid(key, error_type, mock_uploadedFile):
|
|
198 |
inputs[key] = None
|
199 |
with pytest.raises(error_type):
|
200 |
obs = InputObservation(**inputs)
|
|
|
201 |
|
202 |
# we can take a similar approach to test equality.
|
203 |
# here, construct two dicts, each with valid inputs but all elements different.
|
@@ -263,3 +265,158 @@ def test_input_observation_equality(key, expect_equality, mock_uploadedFile):
|
|
263 |
assert obs1 != obs2
|
264 |
|
265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
self._file_urls = [None,]
|
40 |
|
41 |
+
|
42 |
@pytest.fixture
|
43 |
def mock_uploadedFile():
|
44 |
class MockGUIClass(MagicMock):
|
|
|
199 |
inputs[key] = None
|
200 |
with pytest.raises(error_type):
|
201 |
obs = InputObservation(**inputs)
|
202 |
+
|
203 |
|
204 |
# we can take a similar approach to test equality.
|
205 |
# here, construct two dicts, each with valid inputs but all elements different.
|
|
|
265 |
assert obs1 != obs2
|
266 |
|
267 |
|
268 |
+
# now let's test the setter methods (set_top_predictions, set_selected_class, set_class_overriden)
|
269 |
+
# ideally we get a fixture that produces a good / valid InputObservation object
|
270 |
+
# and from there, just test the setters + their expected changes / side effects
|
271 |
+
|
272 |
+
@pytest.fixture
|
273 |
+
def good_datadict_for_input_observation(mock_uploadedFile) -> dict:
|
274 |
+
# set up the good and bad inputs
|
275 |
+
_date="2023-10-10"
|
276 |
+
_time="10:10:10"
|
277 |
+
image_datetime_raw = _date + " " + _time
|
278 |
+
fname = "test_image.jpg"
|
279 |
+
image = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
|
280 |
+
|
281 |
+
dt_ok = datetime.datetime.strptime(image_datetime_raw, "%Y-%m-%d %H:%M:%S")
|
282 |
+
valid_inputs = {
|
283 |
+
"author_email": "[email protected]",
|
284 |
+
"uploaded_file": mock_uploadedFile(name=fname).get_data(),
|
285 |
+
"date": dt_ok.date(),
|
286 |
+
"time": dt_ok.time(),
|
287 |
+
"image": image,
|
288 |
+
"image_md5": 'd1d2515e6f6ac4c5ca6dd739d5143cd4', # 32 hex chars.
|
289 |
+
"image_datetime_raw": image_datetime_raw,
|
290 |
+
"latitude": 12.34,
|
291 |
+
"longitude": 56.78,
|
292 |
+
|
293 |
+
}
|
294 |
+
return valid_inputs
|
295 |
+
|
296 |
+
|
297 |
+
@pytest.fixture
|
298 |
+
def good_input_observation(good_datadict_for_input_observation) -> InputObservation:
|
299 |
+
observation = InputObservation(**good_datadict_for_input_observation)
|
300 |
+
|
301 |
+
return observation
|
302 |
+
|
303 |
+
|
304 |
+
#
|
305 |
+
def test_input_observation__set_top_predictions_populated(good_input_observation):
|
306 |
+
obs = good_input_observation
|
307 |
+
|
308 |
+
# before setting, expect empty list
|
309 |
+
assert obs.top_predictions == []
|
310 |
+
assert obs.selected_class == None
|
311 |
+
|
312 |
+
# set >0,
|
313 |
+
# - expect to find the same list in the property/attribute
|
314 |
+
# - expect to find the first element in the selected_class
|
315 |
+
top_predictions = ["beluga", "blue_whale", "common_dolphin"]
|
316 |
+
obs.set_top_predictions(top_predictions)
|
317 |
+
|
318 |
+
assert len(obs.top_predictions) == 3
|
319 |
+
assert obs.top_predictions == top_predictions
|
320 |
+
assert obs.selected_class == "beluga"
|
321 |
+
|
322 |
+
def test_input_observation__set_top_predictions_unpopulated(good_input_observation):
|
323 |
+
obs = good_input_observation
|
324 |
+
|
325 |
+
# before setting, expect empty list
|
326 |
+
assert obs.top_predictions == []
|
327 |
+
assert obs.selected_class == None
|
328 |
+
|
329 |
+
# set to empty list,
|
330 |
+
# - expect to find the same list in the property/attribute
|
331 |
+
# - expect to find selected_class to be None
|
332 |
+
top_predictions = []
|
333 |
+
obs.set_top_predictions(top_predictions)
|
334 |
+
|
335 |
+
assert len(obs.top_predictions) == 0
|
336 |
+
assert obs.top_predictions == []
|
337 |
+
assert obs.selected_class == None
|
338 |
+
|
339 |
+
def test_input_observation__set_selected_class_default(good_input_observation):
|
340 |
+
obs = good_input_observation
|
341 |
+
|
342 |
+
# before setting, expect empty list
|
343 |
+
assert obs.top_predictions == []
|
344 |
+
assert obs.selected_class == None
|
345 |
+
assert obs.class_overriden == False
|
346 |
+
|
347 |
+
# set >0, and then set_selected_class to the first element
|
348 |
+
# - expect to find the same list in the property/attribute
|
349 |
+
# - expect to find the first element in the selected_class
|
350 |
+
# - expect class_overriden to be False
|
351 |
+
top_predictions = ["beluga", "blue_whale", "common_dolphin"]
|
352 |
+
obs.set_top_predictions(top_predictions)
|
353 |
+
obs.set_selected_class(top_predictions[0])
|
354 |
+
|
355 |
+
assert len(obs.top_predictions) == 3
|
356 |
+
assert obs.top_predictions == top_predictions
|
357 |
+
assert obs.selected_class == "beluga"
|
358 |
+
|
359 |
+
def test_input_observation__set_selected_class_override(good_input_observation):
|
360 |
+
obs = good_input_observation
|
361 |
+
|
362 |
+
# before setting, expect empty list
|
363 |
+
assert obs.top_predictions == []
|
364 |
+
assert obs.selected_class == None
|
365 |
+
assert obs.class_overriden == False
|
366 |
+
|
367 |
+
# set >0, and then set_selected_class to something out of list
|
368 |
+
# - expect to find the same list in the property/attribute
|
369 |
+
# - expect to find the first element in the selected_class
|
370 |
+
# - expect class_overriden to be False
|
371 |
+
top_predictions = ["beluga", "blue_whale", "common_dolphin"]
|
372 |
+
obs.set_top_predictions(top_predictions)
|
373 |
+
obs.set_selected_class("brydes_whale")
|
374 |
+
|
375 |
+
assert len(obs.top_predictions) == 3
|
376 |
+
assert obs.top_predictions == top_predictions
|
377 |
+
assert obs.selected_class == "brydes_whale"
|
378 |
+
assert obs.class_overriden == True
|
379 |
+
|
380 |
+
|
381 |
+
# now we want to test to_dict, make sure it is compliant with the data to be
|
382 |
+
# transmitted to the dataset/server
|
383 |
+
|
384 |
+
def test_input_observation_to_dict(good_datadict_for_input_observation):
|
385 |
+
obs = InputObservation(**good_datadict_for_input_observation)
|
386 |
+
|
387 |
+
# set >0, and then set_selected_class to something out of list
|
388 |
+
# - expect to find the same list in the property/attribute
|
389 |
+
# - expect to find the first element in the selected_class
|
390 |
+
# - expect class_overriden to be False
|
391 |
+
top_predictions = ["beluga", "blue_whale", "common_dolphin"]
|
392 |
+
selected = "brydes_whale"
|
393 |
+
obs.set_top_predictions(top_predictions)
|
394 |
+
obs.set_selected_class(selected)
|
395 |
+
|
396 |
+
# as a first point, we expect the dict to be like the input dict...
|
397 |
+
expected_output = good_datadict_for_input_observation.copy()
|
398 |
+
# ... with a few changes
|
399 |
+
# - date and time get converted to str(date) str(time)
|
400 |
+
expected_output["date"] = str(expected_output["date"])
|
401 |
+
expected_output["time"] = str(expected_output["time"])
|
402 |
+
# - image_filename comes from uploaded_file.name
|
403 |
+
expected_output["image_filename"] = expected_output["uploaded_file"].name
|
404 |
+
# - uploaded_file and image are not in the transmitted data
|
405 |
+
del expected_output["uploaded_file"]
|
406 |
+
del expected_output["image"]
|
407 |
+
# - the classification results should be as set above
|
408 |
+
expected_output["top_prediction"] = top_predictions[0]
|
409 |
+
expected_output["selected_class"] = selected
|
410 |
+
expected_output["class_overriden"] = True
|
411 |
+
|
412 |
+
print(obs.to_dict())
|
413 |
+
assert obs.to_dict() == expected_output
|
414 |
+
|
415 |
+
# expected = {
|
416 |
+
# 'image_filename': 'test_image.jpg', 'image_md5':
|
417 |
+
# 'd1d2515e6f6ac4c5ca6dd739d5143cd4', 'latitude': 12.34, 'longitude':
|
418 |
+
# 56.78, 'author_email': '[email protected]', 'image_datetime_raw':
|
419 |
+
# '2023-10-10 10:10:10', 'date': '2023-10-10', 'time': '10:10:10',
|
420 |
+
# 'selected_class': 'brydes_whale', 'top_prediction': 'beluga',
|
421 |
+
# 'class_overriden': True
|
422 |
+
# }
|