faceverification / test /test_face_verification.py
leandrodevai's picture
Sync from GitHub via hub-sync
c628352 verified
Raw
History Blame Contribute Delete
5.87 kB
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
@pytest.fixture
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()