Skip to content

Commit 44d7717

Browse files
committed
test
1 parent 7ff30b4 commit 44d7717

File tree

10 files changed

+809
-452
lines changed

10 files changed

+809
-452
lines changed

e2e_batch/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
-include .env
22

3-
run-immunization-batch:
4-
ENVIRONMENT=$(environment) poetry run python -m unittest -v -c
3+
test:
4+
ENVIRONMENT=$(ENVIRONMENT) poetry run python -m unittest -v -c

e2e_batch/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# End-to-End Batch Test Suite (test_e2e_batch.py)
2+
3+
This test suite provides automated end-to-end (E2E) testing for the Immunisation FHIR API batch processing pipeline. It verifies that batch file submissions are correctly processed, acknowledged, and validated across the system.
4+
5+
## Overview
6+
- Framework: Python unittest
7+
- Purpose: Simulate real-world batch file submissions, poll for acknowledgements, and validate processing results.
8+
- Test Scenarios: Defined in the scenarios module and enabled in setUp().
9+
- Key Features:
10+
- - Uploads test batch files to S3.
11+
- - Waits for and validates ACK (acknowledgement) files.
12+
- - Cleans up SQS queues and test artifacts after each run.
13+
14+
## Test Flow
15+
1. Setup (setUp)
16+
- Loads and enables a set of test scenarios.
17+
- Prepares test data for batch submission.
18+
2. Test Execution (test_batch_submission)
19+
- Uploads ALL enabled test files to S3.
20+
- Polls for ALL ACK responses and forwarded files.
21+
- Validates the content and structure of ACK files.
22+
3. Teardown (tearDown)
23+
- Cleans up SQS queues and any generated test files.
24+
25+
## Key Functions
26+
- send_files(tests): Uploads enabled test files to the S3 input bucket.
27+
- poll_for_responses(tests, max_timeout): Polls for ACKs and processed files, with a timeout.
28+
- validate_responses(tests): Validates the content of ACK files and checks for expected outcomes.
29+
30+
## How to Run
31+
1. Ensure all dependencies and environment variables are set (see project root README).
32+
2. Run tests from vscode debugger or from makefile using
33+
```
34+
make test
35+
```

e2e_batch/clients.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
"""
44

55
import logging
6-
from constants import (environment, REGION)
6+
from constants import (
7+
environment, REGION,
8+
batch_fifo_queue_name, ack_metadata_queue_name, audit_table_name
9+
)
710
from boto3 import client as boto3_client, resource as boto3_resource
811

912

@@ -13,8 +16,12 @@
1316
s3_client = boto3_client("s3", region_name=REGION)
1417

1518
dynamodb = boto3_resource("dynamodb", region_name=REGION)
16-
table_name = f"imms-{environment}-imms-events"
17-
table = dynamodb.Table(table_name)
19+
sqs_client = boto3_client('sqs', region_name=REGION)
20+
events_table_name = f"imms-{environment}-imms-events"
21+
events_table = dynamodb.Table(events_table_name)
22+
audit_table = dynamodb.Table(audit_table_name)
23+
batch_fifo_queue_url = sqs_client.get_queue_url(QueueName=batch_fifo_queue_name)['QueueUrl']
24+
ack_metadata_queue_url = sqs_client.get_queue_url(QueueName=ack_metadata_queue_name)['QueueUrl']
1825
# Logger
1926
logging.basicConfig(level="INFO")
2027
logger = logging.getLogger()

e2e_batch/constants.py

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,110 @@
1212
POST_VALIDATION_ERROR = "Validation errors: contained[?(@.resourceType=='Patient')].name[0].given is a mandatory field"
1313
DUPLICATE = "The provided identifier:"
1414
ACK_PREFIX = "ack/"
15+
TEMP_ACK_PREFIX = "TempAck/"
1516
HEADER_RESPONSE_CODE_COLUMN = "HEADER_RESPONSE_CODE"
1617
FILE_NAME_VAL_ERROR = "Infrastructure Level Response Value - Processing Error"
1718
CONFIG_BUCKET = "imms-internal-dev-supplier-config"
1819
PERMISSIONS_CONFIG_FILE_KEY = "permissions_config.json"
20+
RAVS_URI = "https://www.ravs.england.nhs.uk/"
21+
batch_fifo_queue_name = f"imms-{environment}-batch-file-created-queue.fifo"
22+
ack_metadata_queue_name = f"imms-{environment}-ack-metadata-queue.fifo"
23+
audit_table_name = f"immunisation-batch-{environment}-audit-table"
1924

25+
class EventName():
26+
CREATE = "INSERT"
27+
UPDATE = "MODIFY"
28+
DELETE_LOGICAL = "MODIFY"
29+
DELETE_PHYSICAL = "REMOVE"
2030

21-
def create_row(unique_id, fore_name, dose_amount, action_flag, header):
31+
32+
class Operation():
33+
CREATE = "CREATE"
34+
UPDATE = "UPDATE"
35+
DELETE_LOGICAL = "DELETE"
36+
DELETE_PHYSICAL = "REMOVE"
37+
38+
39+
class ActionFlag():
40+
CREATE = "NEW"
41+
UPDATE = "UPDATE"
42+
DELETE_LOGICAL = "DELETE"
43+
NONE = "NONE"
44+
45+
46+
class InfResult:
47+
SUCCESS = "Success"
48+
PARTIAL_SUCCESS = "Partial Success"
49+
FATAL_ERROR = "Fatal Error"
50+
51+
52+
class BusRowResult():
53+
SUCCESS = "OK"
54+
FATAL_ERROR = "Fatal Error"
55+
IMMS_NOT_FOUND = "Immunization resource does not exist"
56+
NONE = "NONE"
57+
58+
59+
class OperationOutcome:
60+
IMMS_NOT_FOUND = "Immunization resource does not exist"
61+
TEST = "TEST"
62+
63+
64+
class OpMsgs:
65+
VALIDATION_ERROR = "Validation errors"
66+
MISSING_MANDATORY_FIELD = "is a mandatory field"
67+
DOSE_QUANTITY_NOT_NUMBER = "doseQuantity.value must be a number"
68+
IMM_NOT_EXIST = "Immunization resource does not exist"
69+
IDENTIFIER_PROVIDED = "The provided identifier:"
70+
INVALID_DATE_FORMAT = "is not in the correct format"
71+
72+
73+
class DestinationType:
74+
INF = ACK_PREFIX
75+
BUS = FORWARDEDFILE_PREFIX
76+
77+
78+
class ActionSequence():
79+
def __init__(self, desc: str, actions: list[ActionFlag], outcome: ActionFlag = None):
80+
self.actions = actions
81+
self.description = desc
82+
self.outcome = outcome if outcome else actions[-1]
83+
84+
85+
class PermPair():
86+
def __init__(self, ods_code: str, permissions: str):
87+
self.ods_code = ods_code
88+
self.permissions = permissions
89+
90+
91+
class TestSet():
92+
CREATE_OK = ActionSequence("Create. OK", [ActionFlag.CREATE])
93+
UPDATE_OK = ActionSequence("Update. OK", [ActionFlag.CREATE, ActionFlag.UPDATE])
94+
DELETE_OK = ActionSequence("Delete. OK", [ActionFlag.CREATE, ActionFlag.UPDATE, ActionFlag.DELETE_LOGICAL])
95+
REINSTATE_OK = ActionSequence("Reinstate. OK", [ActionFlag.CREATE, ActionFlag.DELETE_LOGICAL, ActionFlag.UPDATE])
96+
DELETE_FAIL = ActionSequence("Delete without Create. Fail", [ActionFlag.DELETE_LOGICAL])
97+
UPDATE_FAIL = ActionSequence("Update without Create. Fail", [ActionFlag.UPDATE], outcome=ActionFlag.NONE)
98+
99+
100+
def create_row(unique_id, dose_amount, action_flag: str, header, inject_char=None):
22101
"""Helper function to create a single row with the specified UNIQUE_ID and ACTION_FLAG."""
23102

103+
name = "James" if not inject_char else b'Jam\xe9s'
24104
return {
25105
header: "9732928395",
26-
"PERSON_FORENAME": fore_name,
27-
"PERSON_SURNAME": "James",
106+
"PERSON_FORENAME": "PHYLIS",
107+
"PERSON_SURNAME": name,
28108
"PERSON_DOB": "20080217",
29109
"PERSON_GENDER_CODE": "0",
30110
"PERSON_POSTCODE": "WD25 0DZ",
31111
"DATE_AND_TIME": datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S"),
32112
"SITE_CODE": "RVVKC",
33113
"SITE_CODE_TYPE_URI": "https://fhir.nhs.uk/Id/ods-organization-code",
34114
"UNIQUE_ID": unique_id,
35-
"UNIQUE_ID_URI": "https://www.ravs.england.nhs.uk/",
115+
"UNIQUE_ID_URI": RAVS_URI,
36116
"ACTION_FLAG": action_flag,
37117
"PERFORMING_PROFESSIONAL_FORENAME": "PHYLIS",
38-
"PERFORMING_PROFESSIONAL_SURNAME": "James",
118+
"PERFORMING_PROFESSIONAL_SURNAME": name,
39119
"RECORDED_DATE": datetime.now(timezone.utc).strftime("%Y%m%d"),
40120
"PRIMARY_SOURCE": "TRUE",
41121
"VACCINATION_PROCEDURE_CODE": "956951000000104",
@@ -57,32 +137,3 @@ def create_row(unique_id, fore_name, dose_amount, action_flag, header):
57137
"LOCATION_CODE": "RJC02",
58138
"LOCATION_CODE_TYPE_URI": "https://fhir.nhs.uk/Id/ods-organization-code",
59139
}
60-
61-
62-
def create_permissions_json(value):
63-
return {
64-
"all_permissions": {
65-
"DPSFULL": ["RSV_FULL", "COVID19_FULL", "FLU_FULL", "MMR_FULL"],
66-
"DPSREDUCED": ["COVID19_FULL", "FLU_FULL", "MMR_FULL"],
67-
"EMIS": [value, "RSV_FULL"],
68-
"PINNACLE": ["COVID19_UPDATE", "RSV_FULL"],
69-
"SONAR": "",
70-
"TPP": [""],
71-
"AGEM-NIVS": [""],
72-
"NIMS": [""],
73-
"EVA": [""],
74-
"RAVS": [""],
75-
"MEDICAL_DIRECTOR": [""],
76-
"WELSH_DA_1": [""],
77-
"WELSH_DA_2": [""],
78-
"NORTHERN_IRELAND_DA": [""],
79-
"SCOTLAND_DA": [""],
80-
"COVID19_VACCINE_RESOLUTION_SERVICEDESK": [""],
81-
},
82-
"definitions:": {
83-
"FULL": "Full permissions to create, update and delete a batch record",
84-
"CREATE": "Permission to create a batch record",
85-
"UPDATE": "Permission to update a batch record",
86-
"DELETE": "Permission to delete a batch record",
87-
},
88-
}

0 commit comments

Comments
 (0)