-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
622 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Oops, something went wrong.