Skip to content

Commit

Permalink
added tests for facesdk
Browse files Browse the repository at this point in the history
  • Loading branch information
inecsor committed Dec 13, 2023
1 parent 916e5ba commit 79dd35f
Show file tree
Hide file tree
Showing 17 changed files with 622 additions and 0 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/full-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: run full test

on:

jobs:
run_smoke_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install pipenv
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade setuptools wheel
python -m pip install -r tests/misc/requirements.txt
- name: Install test dependencies
run: |
pip install -e ./
pip install -r tests/misc/requirements.txt
- name: Run smoke test
run: python pytest
working-directory: example
env:
API_BASE_PATH: "https://faceapi.regulaforensics.com/"
108 changes: 108 additions & 0 deletions tests/Tests_detect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from regula.facesdk.webclient.gen.model.detect_request_attributes import DetectRequestAttributes
from regula.facesdk.webclient.gen.model.output_image_params import OutputImageParams
from regula.facesdk.webclient.gen.model.quality_request import QualityRequest
from regula.facesdk.webclient.gen.model.detect_request import DetectRequest
from regula.facesdk.webclient.gen.model.process_param import ProcessParam
from regula.facesdk.webclient.gen.model.crop import Crop
from misc.paths_and_urls import *
import pytest
import base64


@pytest.fixture
def detect_setup():
face1 = read_image_bytes(FACE_1_PATH)
face1_b64 = base64.b64encode(face1).decode('utf-8')
sev_faces = read_image_bytes(SEVERAL_FACES_IMAGE_PATH)
sev_faces_b64 = base64.b64encode(sev_faces).decode('utf-8')
yield [face1_b64, sev_faces_b64]


def basic_assertions(response):
# We use this function to avoid repeating code in every test
assert response['code'] == 0
assert 'results' in response, "'results' field not found in response"
assert 'detections' in response['results'], "'detections' field not found in 'results'"
assert response['results']['detections'], "No detections found"


def test_detect_api(facesdk, detect_setup):
request = DetectRequest(image=detect_setup[0])
response = create_dictionary(facesdk.matching_api.detect(request))
basic_assertions(response)


def test_scenario(facesdk, detect_setup):
scenario = 'QUALITY_FULL'
params = ProcessParam(scenario=scenario)
request = DetectRequest(image=detect_setup[0], process_param=params)
response = create_dictionary(facesdk.matching_api.detect(request))
basic_assertions(response)
scenario = 'QUALITY_FULL'
assert response['results'][
'scenario'] == scenario, f"Expected "+scenario+" but got "+response['results']['scenario']


def test_cropAllFaces_scenario(facesdk, detect_setup):
params = ProcessParam(scenario='cropAllFaces', only_central_face=False)
request = DetectRequest(image=detect_setup[1], process_param=params)
response = create_dictionary(facesdk.matching_api.detect(request))
basic_assertions(response)
detections = response['results']['detections']
assert len(detections) == 5, f"Expected 5 detections, but got {len(detections)} detections"


def test_only_central_face(facesdk, detect_setup):
params = ProcessParam(only_central_face=True)
request = DetectRequest(image=detect_setup[1], process_param=params)
response = create_dictionary(facesdk.matching_api.detect(request))
basic_assertions(response)
detections = response['results']['detections']
assert len(detections) == 1, f"Expected 1 detection, but got {len(detections)} detections"


def test_outputImageParams(facesdk, detect_setup):
background_color = [128, 128, 128]
crop_params = Crop(type=0, pad_color=[0, 0, 0], size=[300, 400], )
oi_params = OutputImageParams(background_color=background_color, crop=crop_params)
params = ProcessParam(output_image_params=oi_params)
request = DetectRequest(image=detect_setup[1], process_param=params)
response = create_dictionary(facesdk.matching_api.detect(request))
basic_assertions(response)
detections = response['results']['detections']
assert len(detections) > 0, "No detections found in response"
assert detections[0]['crop'] != '', "'crop' field is empty"


def test_quality(facesdk, detect_setup):
attributes = DetectRequestAttributes(config=[{'name': 'Age', 'range': [5, 45]}])
quality_request = QualityRequest(
background_match_color=[128, 128, 128],
config=[{"name": "Roll", "range": [-5, 5]}]
)
params = ProcessParam(quality=quality_request)
request = DetectRequest(image=detect_setup[1], process_param=params, attributes=attributes)
response = create_dictionary(facesdk.matching_api.detect(request))
basic_assertions(response)
detection = response['results']['detections'][0]
assert len(detection) > 0, "No detections found in response"
assert detection['quality']['details'][0]['name'] == 'Roll'
assert detection['quality']['details'][0]['range'] == [-5.0, 5.0]


def test_attributes(facesdk, detect_setup):
attributes = DetectRequestAttributes(config=[{'name': 'Age', 'range': [5, 45]}])
request = DetectRequest(image=detect_setup[1], process_param=ProcessParam(attributes=attributes))
response = create_dictionary(facesdk.matching_api.detect(request))
basic_assertions(response)
detection = response['results']['detections'][0]
assert len(detection) > 0, "No detections found in response"
attribute_details = detection['attributes']['details']
assert attribute_details[0]['name'] == 'Age'
assert 5 <= attribute_details[0]['value'][0] <= 45
assert 5 <= attribute_details[0]['value'][1] <= 45


def test_without_attributes(facesdk, detect_setup):
request = DetectRequest(image=detect_setup[0])
facesdk.matching_api.detect(request)
147 changes: 147 additions & 0 deletions tests/Tests_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from regula.facesdk.webclient.gen.model.group_to_create import GroupToCreate
from regula.facesdk.webclient.gen.model.person_fields import PersonFields
from regula.facesdk.webclient.gen.model.update_group import UpdateGroup
from misc.paths_and_urls import *
import pytest

test_group_name = "test"
name_a = "Person A"
base_metadata = {'description': 'This is a test group'}


@pytest.fixture
def groups_setup(facesdk):
# This fixture creates a group before test, passes created group_id to the test and removes this group_id after test
created_group_response = (
create_dictionary(facesdk.group_api.create_group(group_name=test_group_name, metadata=base_metadata)))
group_id = created_group_response['id']
yield group_id, created_group_response
delete_response = facesdk.group_api.delete_group(group_id)
assert delete_response is None, f"Unexpected response: {delete_response}"


def test_create_and_delete_group(groups_setup):
# We don't need to create group because it's already created via fixture.
# We just need to check creation response, deletion response will be checked in groups_setup
group_id, response_dict = groups_setup
assert response_dict is not None, "No response received"
assert response_dict['name'] == test_group_name, "Name of the group is incorrect"
assert response_dict['metadata']['description'] == base_metadata['description'], ("Metadata of the group is "
"incorrect")


def test_get_all_groups(facesdk):
# Step 1: Make a list to store the ids of the created groups
created_group_ids = []
# Step 2: Creation of groups
for i in range(4):
# Create a group and get its id from response
create_response = create_dictionary(facesdk.group_api.create_group(f"{test_group_name}_{i}"))
group_id = create_response['id']
# Store the group_id for later deletion
created_group_ids.append(group_id)

# Step 3: Get all groups
response_dict = create_dictionary(facesdk.group_api.get_all_groups(page=2, size=2))

# Step 4: Deletion of groups
for group_id in created_group_ids:
# Remove the group using its id
delete_response = facesdk.group_api.delete_group(group_id)
assert delete_response is None, f"Unexpected response: {delete_response}"

# Step 5: check that page 2 with 2 items exist
assert response_dict is not None, "No response received"
assert len(response_dict['items']) == 2, f"Expected 2 items on page, but got {len(response_dict['items'])} items"
assert response_dict['page'] == 2, f"Expected page to be 2, but got {response_dict['page']}"


def test_get_all_persons_by_group_id(facesdk, groups_setup):
# Step 1: Getting created group_id from fixture
group_id = groups_setup[0]
# Step 2: Adding person to a created group
person_fields = PersonFields(name=name_a, groups=[group_id], metadata=base_metadata)
facesdk.person_api.create_person(person_fields)
# Step 3: Get persons from created group_id
persons_response = facesdk.group_api.get_all_persons_by_group_id(page=1, size=1, group_id=group_id)
persons_response_dict = create_dictionary(persons_response)

facesdk.person_api.delete_person(persons_response_dict['items'][0]['id'])
assert persons_response_dict is not None, "No response received"
assert persons_response_dict['items'][0]['name'] == name_a, "Name of Person is incorrect"
assert persons_response_dict['items'][0]['metadata']['description'] == base_metadata['description'], \
"Metadata of the group is incorrect"
assert persons_response_dict['items'][0]['groups'][0] == group_id, "group_id is incorrect"


def test_get_group(facesdk, groups_setup):
# Step 1: Get all groups and take the first group_id that appears
groups_response_dict = create_dictionary(facesdk.group_api.get_all_groups(page=1, size=1))
assert len(groups_response_dict['items']) > 0, "No groups found"
group_id = groups_response_dict['items'][0]['id']

# Step 2: Using obtained id to get chosen group
group_response_dict = create_dictionary(facesdk.group_api.get_group(group_id))
assert group_response_dict is not None, "No response received"
assert group_response_dict['id'] == group_id, "group_id is incorrect"


def test_group_update(facesdk, groups_setup):
# Step 1: Getting group_id from the fixture
group_id = groups_setup[0]
# Step 2: Updating group with new name
new_name = 'updated_test_group'
updated_metadata = {'description': 'updated meta'}
facesdk.group_api.update_group(group_id=group_id,
group_to_create=GroupToCreate(name=new_name, metadata=updated_metadata))
updated_group_response_dict = create_dictionary(facesdk.group_api.get_group(group_id))

# Step 3: Checking that name is updated
assert updated_group_response_dict[
'name'] == new_name, f"Group name not updated: {updated_group_response_dict['name']}"
assert updated_group_response_dict['metadata']['description'] == updated_metadata[
'description'], "Updated group meta is wrong"


def test_update_persons_in_group(facesdk, groups_setup):
# Step 1: Getting group_id from the fixture
group_id = groups_setup[0]

# Step 2: Creating some persons and adding them to the group
person_fields = PersonFields(name=name_a, groups=[group_id], metadata=base_metadata)
facesdk.person_api.create_person(person_fields)

# Step 3: Getting the group's persons
initial_persons_response = facesdk.group_api.get_all_persons_by_group_id(page=1, size=10, group_id=group_id)
initial_persons_response_dict = create_dictionary(initial_persons_response)
initial_person_ids = [person['id'] for person in initial_persons_response_dict['items']]

# Step 4: Removing them
update_group_remove = UpdateGroup(remove_items=initial_person_ids)
facesdk.group_api.update_persons_in_group(group_id=group_id, update_group=update_group_remove)

# Step 5: Creating new persons and adding them to the group
new_person_names = ["New Person A", "New Person B"]
new_person_ids = []
for name in new_person_names:
person_fields = PersonFields(name=name, groups=[group_id], metadata=base_metadata)
created_person_response_dict = create_dictionary(facesdk.person_api.create_person(person_fields))
new_person_ids.append(created_person_response_dict['id'])

# Step 6: Testing that they're here
updated_persons_response_dict = create_dictionary(
facesdk.group_api.get_all_persons_by_group_id(page=1, size=10, group_id=group_id))
updated_person_ids = [person['id'] for person in updated_persons_response_dict['items']]
assert set(updated_person_ids) == set(
new_person_ids), f"Updated person ids don't match: {updated_person_ids} != {new_person_ids}"
updated_person_names = [person['name'] for person in updated_persons_response_dict['items']]
assert set(updated_person_names) == set(
new_person_names), f"Updated person ids don't match: {updated_person_names} != {new_person_names}"
assert len(updated_persons_response_dict['items']) == 2, 'Expected 2 persons in updated list'


def test_create_group_without_metadata(facesdk):
created_group_response_dict = (
create_dictionary(facesdk.group_api.create_group(group_name=test_group_name)))
group_id = created_group_response_dict['id']
facesdk.group_api.delete_group(group_id)
63 changes: 63 additions & 0 deletions tests/Tests_matching.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from regula.facesdk.webclient.gen.model.image_source import ImageSource
from regula.facesdk.webclient import MatchImage, MatchRequest
from misc.paths_and_urls import *


def validate_response(response, expected_detections_count, expected_first, expected_second=None):
assert response['code'] == 0, f"Unexpected response code: {response['code']}"
assert isinstance(response.get('detections', []), list), "'detections' field should be an array"
assert len(response.get('detections', [])) == expected_detections_count, \
f"'detections' array should have {expected_detections_count} entries"
assert 'results' in response, "'results' field not found in response"
assert isinstance(response['results'], list), "'results' should be an array"
assert response['results'][0]['first'] == expected_first, f"Expected 'first' to be {expected_first}"
if expected_second is not None:
assert response['results'][0].get('second',
None) == expected_second, f"Expected 'second' to be {expected_second}"


def create_match_request(type1, path1, type2=None, path2=None):
images = [MatchImage(index=1, data=read_image_bytes(path1), type=type1)]
if type2 and path2:
images.append(MatchImage(index=2, data=read_image_bytes(path2), type=type2))
return MatchRequest(images=images)


def test_matching_api(facesdk):
match_request = create_match_request(ImageSource.LIVE, FACE_1_PATH, ImageSource.DOCUMENT_RFID, FACE_1_PATH)
response_dict = create_dictionary(facesdk.matching_api.match(match_request))
validate_response(response_dict, expected_detections_count=2, expected_first=3, expected_second=2)


def test_liveAndPrintedDoc_type(facesdk):
match_request = create_match_request(ImageSource.DOCUMENT_PRINTED, PRINTED_DOCUMENT_PATH, ImageSource.LIVE,
LIVE_PHOTO_PATH)
response_dict = create_dictionary(facesdk.matching_api.match(match_request))
validate_response(response_dict, expected_detections_count=2, expected_first=1, expected_second=3)


def test_docWithLive_type(facesdk):
match_request = create_match_request(ImageSource.DOCUMENT_WITH_LIVE, DOCUMENT_WITH_LIVE_PATH)
response_dict = create_dictionary(facesdk.matching_api.match(match_request))
validate_response(response_dict, expected_detections_count=1, expected_first=4)


def test_external_type(facesdk):
match_request = create_match_request(ImageSource.DOCUMENT_PRINTED, PRINTED_DOCUMENT_PATH, ImageSource.EXTERNAL,
LIVE_PHOTO_PATH)
response_dict = create_dictionary(facesdk.matching_api.match(match_request))
validate_response(response_dict, expected_detections_count=2, expected_first=1, expected_second=5)


def test_documentRFID_type(facesdk):
match_request = create_match_request(ImageSource.DOCUMENT_PRINTED, PRINTED_DOCUMENT_PATH, ImageSource.DOCUMENT_RFID,
LIVE_PHOTO_PATH)
response_dict = create_dictionary(facesdk.matching_api.match(match_request))
validate_response(response_dict, expected_detections_count=2, expected_first=1, expected_second=2)


def test_ghost_type(facesdk):
match_request = create_match_request(ImageSource.DOCUMENT_PRINTED, PRINTED_DOCUMENT_PATH, ImageSource.GHOST,
LIVE_PHOTO_PATH)
response_dict = create_dictionary(facesdk.matching_api.match(match_request))
validate_response(response_dict, expected_detections_count=2, expected_first=1, expected_second=6)
Loading

0 comments on commit 79dd35f

Please sign in to comment.