From fb7f5b6a95a390ba1e400f201d15d63681290c20 Mon Sep 17 00:00:00 2001 From: Sefik Ilkin Serengil Date: Wed, 13 Nov 2024 10:13:06 +0000 Subject: [PATCH] more unit tests added --- tests/test_api.py | 112 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/tests/test_api.py b/tests/test_api.py index 0506143f..ff56b48e 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -2,12 +2,19 @@ import os import base64 import unittest +from unittest.mock import patch, MagicMock +from packaging import version # 3rd party dependencies import gdown +import numpy as np +import flask +from flask import Flask +import werkzeug # project dependencies from deepface.api.src.app import create_app +from deepface.api.src.modules.core import routes from deepface.commons.logger import Logger logger = Logger() @@ -18,6 +25,7 @@ IMG2_SOURCE = ( "https://raw.githubusercontent.com/serengil/deepface/refs/heads/master/tests/dataset/img2.jpg" ) +DUMMY_APP = Flask(__name__) class TestVerifyEndpoint(unittest.TestCase): @@ -253,6 +261,9 @@ def test_invalid_analyze(self): assert response.status_code == 400 def test_analyze_for_multipart_form_data(self): + if is_form_data_file_testable() is False: + return + with open("/tmp/img1.jpg", "rb") as img_file: response = self.app.post( "/analyze", @@ -271,6 +282,9 @@ def test_analyze_for_multipart_form_data(self): logger.info("✅ analyze api for multipart form data test is done") def test_verify_for_multipart_form_data(self): + if is_form_data_file_testable() is False: + return + with open("/tmp/img1.jpg", "rb") as img1_file: with open("/tmp/img2.jpg", "rb") as img2_file: response = self.app.post( @@ -297,6 +311,9 @@ def test_verify_for_multipart_form_data(self): logger.info("✅ verify api for multipart form data test is done") def test_represent_for_multipart_form_data(self): + if is_form_data_file_testable() is False: + return + with open("/tmp/img1.jpg", "rb") as img_file: response = self.app.post( "/represent", @@ -313,6 +330,9 @@ def test_represent_for_multipart_form_data(self): logger.info("✅ represent api for multipart form data test is done") def test_represent_for_multipart_form_data_and_filepath(self): + if is_form_data_file_testable() is False: + return + response = self.app.post( "/represent", content_type="multipart/form-data", @@ -327,6 +347,78 @@ def test_represent_for_multipart_form_data_and_filepath(self): assert isinstance(result, dict) logger.info("✅ represent api for multipart form data and file path test is done") + def test_extract_image_from_form_data(self): + if is_form_data_file_testable() is False: + return + + img_key = "img1" + img_itself = np.zeros((100, 100, 3), dtype=np.uint8) + # Establish a temporary request context using the Flask app + with DUMMY_APP.test_request_context("/dummy_endpoint"): + # Mock the file part + with patch("deepface.api.src.modules.core.routes.request") as mock_request: + mock_file = MagicMock() + mock_file.filename = "image.jpg" + mock_request.files = {img_key: mock_file} + + # Mock the image loading function + with patch( + "deepface.commons.image_utils.load_image_from_file_storage", + return_value=img_itself, + ): + result = routes.extract_image_from_request(img_key) + + assert isinstance(result, np.ndarray) + assert np.array_equal(result, img_itself) + + logger.info("✅ test extract_image_from_request for real image from form data done") + + def test_extract_image_string_from_json_data(self): + if is_form_data_file_testable() is False: + return + + img_key = "img1" + img_data = "image_url_or_path_or_base64" + + with DUMMY_APP.test_request_context("/dummy_endpoint"): + with patch("deepface.api.src.modules.core.routes.request") as mock_request: + # Mock JSON data + mock_request.files = None + mock_request.is_json = True + mock_request.get_json = MagicMock(return_value={img_key: img_data}) + + result = routes.extract_image_from_request(img_key) + + assert isinstance(result, str) + assert result == img_data + + logger.info("✅ test extract_image_from_request for image string from json done") + + def test_extract_image_string_from_form_data(self): + if is_form_data_file_testable() is False: + return + + img_key = "img1" + img_data = "image_url_or_path_or_base64" + + with DUMMY_APP.test_request_context("/dummy_endpoint"): + with patch("deepface.api.src.modules.core.routes.request") as mock_request: + # Mock form data + mock_request.files = None + + mock_request.is_json = False + mock_request.get_json = MagicMock(return_value=None) + + mock_request.form = MagicMock() + mock_request.form.to_dict.return_value = {img_key: img_data} + + result = routes.extract_image_from_request(img_key) + + assert isinstance(result, str) + assert result == img_data + + logger.info("✅ test extract_image_from_request for image string from form done") + def download_test_images(url: str): file_name = url.split("/")[-1] @@ -335,3 +427,23 @@ def download_test_images(url: str): return gdown.download(url, target_file, quiet=False) + + +def is_form_data_file_testable() -> bool: + """ + Sending a file from form data fails in unit test with + 415 unsupported media type error for flask 3.X + but it is working for flask 2.0.2 + Returns: + is_form_data_file_testable (bool) + """ + flask_version = version.parse(flask.__version__) + werkzeus_version = version.parse(werkzeug.__version__) + threshold_version = version.parse("2.0.2") + is_testable = flask_version <= threshold_version and werkzeus_version <= threshold_version + if is_testable is False: + logger.warn( + "sending file in form data is not testable because of flask, werkzeus versions." + f"Expected <= {threshold_version}, but {flask_version=} and {werkzeus_version}." + ) + return is_testable