From ec6506a498250854c45250b5ebd31c65ea1c39df Mon Sep 17 00:00:00 2001 From: Devasy Patel <110348311+Devasy23@users.noreply.github.com> Date: Sat, 9 Mar 2024 23:36:43 +0530 Subject: [PATCH 1/3] Remove deprecated code and update imports in API/route.py and update CHANGELOG.md --- API/route.py | 3 +-- CHANGELOG.md | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/API/route.py b/API/route.py index 0f7b048..7881010 100644 --- a/API/route.py +++ b/API/route.py @@ -8,11 +8,10 @@ from bson import ObjectId from deepface import DeepFace -from fastapi import APIRouter, Form, HTTPException, Response +from fastapi import APIRouter, HTTPException, Response from matplotlib import pyplot as plt from PIL import Image from pydantic import BaseModel -from pymongo import MongoClient from API.database import Database from API.utils import init_logging_config diff --git a/CHANGELOG.md b/CHANGELOG.md index 298d02e..f37df95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,4 +33,7 @@ - Split `test_face_lifecycle` function in [`test_face_cycle.py`](testing/test_face_cycle.py) into multiple smaller test cases that execute in a particularly specified order. Changes made by @Devasy23. ### Fixed -- Resolved issues in the test cases of [`test_face_cycle.py`](testing/test_face_cycle.py) to ensure they pass with the updated code structure. Fixes made by @Devasy23. \ No newline at end of file +- Resolved issues in the test cases of [`test_face_cycle.py`](testing/test_face_cycle.py) to ensure they pass with the updated code structure. Fixes made by @Devasy23. + +### Removed +- Removed deprecated code from various modules to improve performance and maintainability. Changes made by @Devasy23. \ No newline at end of file From 154d7b10af3f0d5ab81ec75e36c289b797260b02 Mon Sep 17 00:00:00 2001 From: Devasy Patel <110348311+Devasy23@users.noreply.github.com> Date: Sun, 10 Mar 2024 00:49:15 +0530 Subject: [PATCH 2/3] Add face registration and lifecycle tests --- API/route.py | 4 +- requirements.txt | 3 +- testing/test_face_endpoints.py | 164 +++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 testing/test_face_endpoints.py diff --git a/API/route.py b/API/route.py index 7881010..940015c 100644 --- a/API/route.py +++ b/API/route.py @@ -121,7 +121,7 @@ async def get_employees(): Name=employee.get("Name", "N/A"), gender=employee.get("gender", "N/A"), Department=employee.get("Department", "N/A"), - Images=employee.get("Images", "N/A"), + Images=employee.get("Images", []), ) for employee in employees_mongo ] @@ -226,7 +226,7 @@ async def update_employees(EmployeeCode: int, Employee: UpdateEmployee): try: update_result = client.update_one( collection, - filter={"_id": ObjectId(user_id["_id"])}, + {"_id": ObjectId(user_id["_id"])}, update={"$set": Employee_data}, ) logging.info(f"Update result {update_result}") diff --git a/requirements.txt b/requirements.txt index 4ce1e20..6bc968f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,4 +88,5 @@ urllib3==2.1.0 uvicorn==0.25.0 Werkzeug==3.0.1 wrapt==1.14.1 -zipp==3.17.0 \ No newline at end of file +zipp==3.17.0 +pytest-ordering \ No newline at end of file diff --git a/testing/test_face_endpoints.py b/testing/test_face_endpoints.py new file mode 100644 index 0000000..a4a834a --- /dev/null +++ b/testing/test_face_endpoints.py @@ -0,0 +1,164 @@ +import base64 +import logging +from unittest.mock import MagicMock, patch + +import pytest +from fastapi.testclient import TestClient + +from API.route import router +from API.utils import init_logging_config + +init_logging_config() + +client = TestClient(router) + + +@pytest.mark.run(order=1) +def test_register_face1(): + mock_doc = { + "_id": "65e6284d01f95cd96ea334a7", + "EmployeeCode": "1", + "Name": "Devansh", + "gender": "Male", + "Department": "IT", + "Images": ["encoded_string1", "encoded_string2"], + } + + mock_find = MagicMock(return_value=[mock_doc, mock_doc]) + mock_insert_one = MagicMock(return_value=MagicMock(inserted_id="1")) + mock_find_one = MagicMock(return_value=mock_doc) + mock_update_one = MagicMock(return_value=MagicMock(modified_count=1)) + mock_find_one_and_delete = MagicMock(return_value=mock_doc) + + with patch("API.database.Database.find", mock_find), patch( + "API.database.Database.insert_one", mock_insert_one + ), patch("API.database.Database.find_one", mock_find_one), patch( + "API.database.Database.update_one", mock_update_one + ), patch( + "API.database.Database.find_one_and_delete", mock_find_one_and_delete + ): + + with open("./test-faces/devansh.jpg", "rb") as image_file: + encoded_string1 = base64.b64encode(image_file.read()).decode("utf-8") + + response1 = client.post( + "/create_new_faceEntry", + json={ + "EmployeeCode": "1", + "Name": "Devansh", + "gender": "Male", + "Department": "IT", + "Images": [encoded_string1, encoded_string1], + }, + ) + assert response1.status_code == 200 + assert response1.json() == {"message": "Face entry created successfully"} + + +@pytest.mark.run(order=2) +def test_register_face2(): + mock_doc = { + "_id": "65e6284d01f95cd96ea334a7", + "EmployeeCode": "1", + "Name": "Devansh", + "gender": "Male", + "Department": "IT", + "Images": ["encoded_string1", "encoded_string2"], + } + + mock_find = MagicMock(return_value=[mock_doc, mock_doc]) + mock_insert_one = MagicMock(return_value=MagicMock(inserted_id="1")) + mock_find_one = MagicMock(return_value=mock_doc) + mock_update_one = MagicMock(return_value=MagicMock(modified_count=1)) + mock_find_one_and_delete = MagicMock(return_value=mock_doc) + + with patch("API.database.Database.find", mock_find), patch( + "API.database.Database.insert_one", mock_insert_one + ), patch("API.database.Database.find_one", mock_find_one), patch( + "API.database.Database.update_one", mock_update_one + ), patch( + "API.database.Database.find_one_and_delete", mock_find_one_and_delete + ): + + with open("./test-faces/devansh.jpg", "rb") as image_file: + encoded_string2 = base64.b64encode(image_file.read()).decode("utf-8") + + response2 = client.post( + "/create_new_faceEntry", + json={ + "EmployeeCode": "2", + "Name": "test", + "gender": "Female", + "Department": "IT", + "Images": [encoded_string2, encoded_string2], + }, + ) + assert response2.status_code == 200 + assert response2.json() == {"message": "Face entry created successfully"} + + +@pytest.mark.run(order=3) +def test_get_all_faces_after_registration(): + mock_doc = { + "_id": "65e6284d01f95cd96ea334a7", + "EmployeeCode": "1", + "Name": "Devansh", + "gender": "Male", + "Department": "IT", + "Images": ["encoded_string1", "encoded_string2"], + } + + mock_find = MagicMock(return_value=[mock_doc, mock_doc]) + + with patch("API.database.Database.find", mock_find): + response = client.get("/Data/") + assert response.status_code == 200 + logging.debug(response.json()) + assert len(response.json()) == 2 + + +@pytest.mark.run(order=4) +def test_update_face(): + mock_doc = { + "_id": "65e6284d01f95cd96ea334a7", + "EmployeeCode": "1", + "Name": "Devansh", + "gender": "Male", + "Department": "IT", + "Images": ["encoded_string1", "encoded_string2"], + } + + mock_find = MagicMock(return_value=[mock_doc, mock_doc]) + mock_insert_one = MagicMock(return_value=MagicMock(inserted_id="1")) + mock_find_one = MagicMock(return_value=mock_doc) + mock_update_one = MagicMock(return_value=MagicMock(modified_count=1)) + mock_find_one_and_delete = MagicMock(return_value=mock_doc) + + with patch("API.database.Database.find", mock_find), patch( + "API.database.Database.insert_one", mock_insert_one + ), patch("API.database.Database.find_one", mock_find_one), patch( + "API.database.Database.update_one", mock_update_one + ), patch( + "API.database.Database.find_one_and_delete", mock_find_one_and_delete + ): + with open("./test-faces/devansh.jpg", "rb") as image_file: + encoded_string2 = base64.b64encode(image_file.read()).decode("utf-8") + + response = client.put( + "/update/1", + json={ + "Name": "Test", + "gender": "Male", + "Department": "IT_Test", + "Images": [encoded_string2, encoded_string2], + }, + ) + assert response.status_code == 200 + assert response.json() == "Updated Successfully" + + +@pytest.mark.run(order=5) +def test_delete_face(): + response = client.delete("/delete/1") + assert response.status_code == 200 + assert response.json() == {"Message": "Successfully Deleted"} From a4913c642e1e179622f20d05fd25fd69e96ab05b Mon Sep 17 00:00:00 2001 From: Devasy Patel <110348311+Devasy23@users.noreply.github.com> Date: Sun, 10 Mar 2024 00:53:31 +0530 Subject: [PATCH 3/3] Refactored code, added new tests, and removed deprecated code and dependencies --- CHANGELOG.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f37df95..184faa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,4 +36,17 @@ - Resolved issues in the test cases of [`test_face_cycle.py`](testing/test_face_cycle.py) to ensure they pass with the updated code structure. Fixes made by @Devasy23. ### Removed -- Removed deprecated code from various modules to improve performance and maintainability. Changes made by @Devasy23. \ No newline at end of file +- Removed deprecated code from various modules to improve performance and maintainability. Changes made by @Devasy23. + +## [0.1.3] - 2024-03-10 - 00:51 + +### Added +- Created a new file [`test_face_endpoints.py`](testing/test_face_endpoints.py) to separately test each endpoint. Changes made by @Devasy23 +- Split the test cases in [`test_face_cycle.py`](testing/test_face_cycle.py) into smaller tests for each endpoint. +- Added new dependencies to the [`requirements.txt`](requirements.txt) file to support the latest features and improvements. + +### Fixed +- Resolved various bugs and issues identified during the testing process. + +### Removed +- Removed deprecated code and unused dependencies from the project. \ No newline at end of file