Spaces:
Sleeping
Sleeping
| import importlib | |
| import sys | |
| from unittest.mock import Mock | |
| import numpy as np | |
| import pytest | |
| from PIL import Image | |
| from faceverification.core import image_processor as image_processor_module | |
| from faceverification.core import vectordb as vectordb_module | |
| from faceverification.core.image_processor import FaceNotDetectedError | |
| class FakeEmbedding: | |
| def __init__(self, value): | |
| self.value = value | |
| def cpu(self): | |
| return self | |
| def numpy(self): | |
| return self.value | |
| def service_module(monkeypatch): | |
| fake_image_processor = Mock() | |
| fake_vector_db = Mock() | |
| monkeypatch.setattr( | |
| image_processor_module, | |
| "ImageProcessor", | |
| lambda: fake_image_processor, | |
| ) | |
| monkeypatch.setattr(vectordb_module, "VectorDB", lambda: fake_vector_db) | |
| sys.modules.pop("faceverification.services.face_verification", None) | |
| module = importlib.import_module("faceverification.services.face_verification") | |
| return module, fake_image_processor, fake_vector_db | |
| def test_add_person_stores_embedding_and_returns_annotated_image(service_module): | |
| service, image_processor, vector_db = service_module | |
| original_image = Image.new("RGB", (10, 10), "white") | |
| annotated_image = Image.new("RGB", (10, 10), "black") | |
| embedding = np.array([0.1, 0.2, 0.3]) | |
| image_processor.detect_faces.return_value = (annotated_image, True) | |
| image_processor.get_embedding.return_value = FakeEmbedding(embedding) | |
| result = service.add_person(original_image, "Ada") | |
| assert result is annotated_image | |
| image_processor.detect_faces.assert_called_once_with(original_image) | |
| image_processor.get_embedding.assert_called_once_with(annotated_image) | |
| vector_db.add_embedding.assert_called_once() | |
| args = vector_db.add_embedding.call_args.args | |
| np.testing.assert_array_equal(args[0], embedding) | |
| assert args[1] == {"name": "Ada"} | |
| def test_add_person_raises_when_no_face_is_detected(service_module): | |
| service, image_processor, vector_db = service_module | |
| image_processor.detect_faces.return_value = (Image.new("RGB", (10, 10)), False) | |
| with pytest.raises(FaceNotDetectedError, match="No faces were detected"): | |
| service.add_person(Image.new("RGB", (10, 10)), "Ada") | |
| image_processor.get_embedding.assert_not_called() | |
| vector_db.add_embedding.assert_not_called() | |
| def test_add_person_raises_type_error_when_embedding_is_none(service_module): | |
| service, image_processor, vector_db = service_module | |
| image = Image.new("RGB", (10, 10)) | |
| image_processor.detect_faces.return_value = (image, True) | |
| image_processor.get_embedding.return_value = None | |
| with pytest.raises(TypeError, match="extracted face embedding"): | |
| service.add_person(image, "Ada") | |
| vector_db.add_embedding.assert_not_called() | |
| def test_verify_person_returns_matched_name_and_annotated_image(service_module): | |
| service, image_processor, vector_db = service_module | |
| original_image = Image.new("RGB", (10, 10), "white") | |
| detected_faces = Image.new("RGB", (10, 10), "black") | |
| embedding = np.array([0.4, 0.5, 0.6]) | |
| image_processor.detect_faces.return_value = (detected_faces, True) | |
| image_processor.get_embedding.return_value = FakeEmbedding(embedding) | |
| vector_db.query_embedding.return_value = ({"name": "Grace"}, 0.2) | |
| name, image = service.verify_person(original_image) | |
| assert name == "Grace" | |
| assert image is detected_faces | |
| detected_input = image_processor.detect_faces.call_args.args[0] | |
| assert detected_input is not original_image | |
| image_processor.get_embedding.assert_called_once_with(original_image) | |
| vector_db.query_embedding.assert_called_once() | |
| np.testing.assert_array_equal(vector_db.query_embedding.call_args.args[0], embedding) | |
| def test_verify_person_returns_unregistered_when_no_metadata_matches(service_module): | |
| service, image_processor, vector_db = service_module | |
| detected_faces = Image.new("RGB", (10, 10)) | |
| image_processor.detect_faces.return_value = (detected_faces, True) | |
| image_processor.get_embedding.return_value = FakeEmbedding(np.array([0.1, 0.2])) | |
| vector_db.query_embedding.return_value = (None, 1.5) | |
| name, image = service.verify_person(Image.new("RGB", (10, 10))) | |
| assert name == "Unregistered Person" | |
| assert image is detected_faces | |
| def test_verify_person_raises_when_vector_db_has_no_records(service_module): | |
| service, image_processor, vector_db = service_module | |
| detected_faces = Image.new("RGB", (10, 10)) | |
| image_processor.detect_faces.return_value = (detected_faces, True) | |
| image_processor.get_embedding.return_value = FakeEmbedding(np.array([0.1, 0.2])) | |
| vector_db.query_embedding.side_effect = ValueError( | |
| "No record found in the vector database. Add a person before verifying faces." | |
| ) | |
| with pytest.raises(ValueError, match="Add a person before verifying faces"): | |
| service.verify_person(Image.new("RGB", (10, 10))) | |
| def test_verify_person_raises_when_no_face_is_detected(service_module): | |
| service, image_processor, vector_db = service_module | |
| image_processor.detect_faces.return_value = (Image.new("RGB", (10, 10)), False) | |
| with pytest.raises(FaceNotDetectedError, match="No faces were detected"): | |
| service.verify_person(Image.new("RGB", (10, 10))) | |
| image_processor.get_embedding.assert_not_called() | |
| vector_db.query_embedding.assert_not_called() | |
| def test_verify_person_raises_when_embedding_is_none(service_module): | |
| service, image_processor, vector_db = service_module | |
| image_processor.detect_faces.return_value = (Image.new("RGB", (10, 10)), True) | |
| image_processor.get_embedding.return_value = None | |
| with pytest.raises(FaceNotDetectedError, match="No faces were detected"): | |
| service.verify_person(Image.new("RGB", (10, 10))) | |
| vector_db.query_embedding.assert_not_called() | |