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

Files changed (1) hide show
  1. 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
+ # }