Skip to content

Commit 3aa98be

Browse files
committed
refactoring more test and using utilities
1 parent a115fb6 commit 3aa98be

File tree

7 files changed

+71
-40
lines changed

7 files changed

+71
-40
lines changed

lambdas/shared/src/common/validator/parsers/csv_line_parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ def parse_csv_line(self, csv_row: str, csv_header: str) -> None:
3030

3131
# Retrieves the value of a specific column name as a list.
3232
def get_key_value(self, field_name: str) -> list[str]:
33-
retrieve_column_data = [self.csv_file_data[field_name]]
34-
return retrieve_column_data
33+
retrieve_column_value = [self.csv_file_data[field_name]]
34+
return retrieve_column_value

lambdas/shared/tests/test_common/validator/test_csv_line_parser.py

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,58 @@
1+
"""
2+
While there are tests to run the csv line against the validator,
3+
these tests focuses on the csv line parser functionality.
4+
Rows mean values and headers are keys
5+
"""
6+
17
import unittest
28

9+
from test_common.validator.testing_utils.constants import CSV_HEADER
10+
from test_common.validator.testing_utils.constants import CSV_VALUES
11+
from test_common.validator.testing_utils.csv_utils import build_row
12+
313
from common.validator.parsers.csv_line_parser import CSVLineParser
414

515

616
class TestCSVLineParser(unittest.TestCase):
717
def test_parse_normal(self):
8-
p = CSVLineParser()
9-
p.parse_csv_line("9011011,Tom,32", "nhs_number,name,age")
10-
self.assertEqual(p.csv_file_data, {"nhs_number": "9011011", "name": "Tom", "age": "32"})
11-
self.assertEqual(p.get_key_value("name"), ["Tom"])
18+
csv_parsers = CSVLineParser()
19+
csv_rows = build_row(CSV_HEADER, CSV_VALUES)
20+
csv_parsers.parse_csv_line(csv_rows, CSV_HEADER)
21+
self.assertEqual(csv_parsers.csv_file_data, CSV_VALUES)
22+
self.assertEqual(csv_parsers.get_key_value("NHS_NUMBER"), ["9000000009"])
1223

1324
def test_extra_values_ignored(self):
14-
p = CSVLineParser()
15-
p.parse_csv_line("1,2,3", "a,b")
16-
self.assertEqual(p.csv_file_data, {"a": "1", "b": "2"})
17-
self.assertEqual(p.get_key_value("b"), ["2"])
18-
19-
def test_fewer_values_missing_key_raises(self):
20-
p = CSVLineParser()
21-
p.parse_csv_line("alpha,beta", "a,b,c")
22-
self.assertIn("a", p.csv_file_data)
23-
self.assertIn("b", p.csv_file_data)
24-
self.assertNotIn("c", p.csv_file_data)
25+
"""
26+
Ignore values that do not have a corresponding key
27+
"""
28+
csv_parsers = CSVLineParser()
29+
csv_parsers.parse_csv_line("9000000009,Alex,Trent", "NHS_NUMBER,PERSON_FORENAME,PERSON_SURNAME")
30+
self.assertEqual(
31+
csv_parsers.csv_file_data,
32+
{"NHS_NUMBER": "9000000009", "PERSON_FORENAME": "Alex", "PERSON_SURNAME": "Trent"},
33+
)
34+
self.assertEqual(csv_parsers.get_key_value("PERSON_FORENAME"), ["Alex"])
35+
36+
def test_fewer_values_than_keys(self):
37+
"""
38+
Test that fewer values (rows) than keys (columns/headers)
39+
raises an error when accessing key without value
40+
"""
41+
csv_parsers = CSVLineParser()
42+
csv_parsers.parse_csv_line("9000000009,Alex", "NHS_NUMBER,PERSON_FORENAME,PERSON_SURNAME")
43+
self.assertIn("NHS_NUMBER", csv_parsers.csv_file_data)
44+
self.assertIn("PERSON_FORENAME", csv_parsers.csv_file_data)
45+
self.assertNotIn("PERSON_SURNAME", csv_parsers.csv_file_data)
2546
with self.assertRaises(KeyError):
26-
_ = p.get_key_value("c")
47+
_ = csv_parsers.get_key_value("PERSON_SURNAME")
2748

2849
def test_get_missing_key_raises(self):
29-
p = CSVLineParser()
30-
p.parse_csv_line("1,2", "a,b")
50+
"""
51+
Test that accessing a non-existent key raises KeyError"""
52+
csv_parsers = CSVLineParser()
53+
csv_parsers.parse_csv_line("9000000009,Alex", "NHS_NUMBER,PERSON_FORENAME,PERSON_SURNAME")
3154
with self.assertRaises(KeyError):
32-
_ = p.get_key_value("z")
55+
_ = csv_parsers.get_key_value("VACCINE_TYPE")
3356

3457

3558
if __name__ == "__main__":

lambdas/shared/tests/test_common/validator/test_csv_parser.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import unittest
33
from pathlib import Path
44

5+
from test_common.validator.testing_utils.constants import CSV_DELIMITER_SAMPLE as CSV_FILE
6+
57
from common.validator.parsers.csv_parser import CSVParser
68

79

@@ -12,13 +14,12 @@ def _write_temp_csv(self, content: str) -> str:
1214
return path
1315

1416
def test_parse_file_with_pipe_delimiter(self):
15-
csv_content = "nhs|name|age\n9011011|Tom|32\n9011012|Ana|27\n"
16-
path = self._write_temp_csv(csv_content)
17+
path = self._write_temp_csv(CSV_FILE)
1718
try:
1819
p = CSVParser()
1920
p.parse_csv_file(path, delimiter="|")
20-
self.assertEqual(p.get_key_value("name"), ["Tom", "Ana"])
21-
self.assertEqual(p.get_key_value("nhs"), ["9011011", "9011012"])
21+
self.assertEqual(p.get_key_value("NHS_NUMBER"), ["9990548609", "9990548617"])
22+
self.assertEqual(p.get_key_value("PERSON_FORENAME"), ["Emily", "James"])
2223
finally:
2324
Path(path).unlink(missing_ok=True)
2425

lambdas/shared/tests/test_common/validator/test_application_csv_row.py renamed to lambdas/shared/tests/test_common/validator/test_validate_csv_row.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from test_common.validator.testing_utils.constants import CSV_HEADER
77
from test_common.validator.testing_utils.constants import CSV_VALUES
8+
from test_common.validator.testing_utils.csv_utils import build_row
89

910
from common.validator.validator import Validator
1011

@@ -17,27 +18,18 @@ class TestValidator(unittest.TestCase):
1718
Unit tests for the CSV row validation logic using the Validator class.
1819
"""
1920

20-
@staticmethod
21-
def build_row(header: str, csv_file: dict) -> str:
22-
"""
23-
Construct a CSV row string from the provided csv_file.
24-
Any missing header columns get empty string values.
25-
"""
26-
cols = header.split(",")
27-
return ",".join(str(csv_file.get(col, "")) for col in cols)
28-
2921
def setUp(self):
3022
with open(schemaFilePath, encoding="utf-8") as file:
3123
schema_file = json.load(file)
3224
self.validator = Validator(schema_file)
3325

3426
def test_run_validation_on_valid_csv_row(self):
35-
valid_rows = self.build_row(CSV_HEADER, CSV_VALUES)
27+
valid_rows = build_row(CSV_HEADER, CSV_VALUES)
3628
error_report = self.validator.validate_csv_row(valid_rows, CSV_HEADER, True, True, True)
3729
self.assertEqual(error_report, [])
3830

3931
def test_run_validation_on_invalid_csv_row(self):
40-
invalid_rows = self.build_row(CSV_HEADER, {**CSV_VALUES, "NHS_NUMBER": ""})
32+
invalid_rows = build_row(CSV_HEADER, {**CSV_VALUES, "NHS_NUMBER": ""})
4133
error_report = self.validator.validate_csv_row(invalid_rows, CSV_HEADER, True, True, True)
4234
self.assertTrue(len(error_report) > 0)
4335
messages = [(e.name, e.message, e.details) for e in error_report]

lambdas/shared/tests/test_common/validator/test_application_csv_small.py renamed to lambdas/shared/tests/test_common/validator/test_validation_csv_small.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# Test application file
21
import json
32
import unittest
43
from pathlib import Path
@@ -10,8 +9,8 @@ class TestValidator(unittest.TestCase):
109
def setUp(self):
1110
self.parent_folder = Path(__file__).parent
1211
schema_file_path = self.parent_folder / "test_schemas/test_small_schema.json"
13-
with open(schema_file_path) as JSON:
14-
self.schema = json.load(JSON)
12+
with open(schema_file_path) as file:
13+
self.schema = json.load(file)
1514

1615
def test_run_validation_csv_success(self):
1716
good_file_path = self.parent_folder / "sample_data/test_small_ok.csv"

lambdas/shared/tests/test_common/validator/testing_utils/constants.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@
1919
"PRIMARY_SOURCE": "true",
2020
"VACCINATION_PROCEDURE_CODE": "PROC123",
2121
"VACCINATION_PROCEDURE_TERM": "Procedure Term",
22-
"DOSE_SEQUENCE": 1,
22+
"DOSE_SEQUENCE": "1",
2323
"VACCINE_PRODUCT_CODE": "VACC123",
2424
"VACCINE_PRODUCT_TERM": "Vaccine Term",
2525
"VACCINE_MANUFACTURER": "Manufacturer XYZ",
2626
"BATCH_NUMBER": "BATCH001",
2727
}
28+
29+
30+
CSV_DELIMITER_SAMPLE = """NHS_NUMBER|PERSON_FORENAME|PERSON_SURNAME|PERSON_DOB|PERSON_GENDER_CODE|PERSON_POSTCODE|DATE_AND_TIME|SITE_CODE|SITE_CODE_TYPE_URI|UNIQUE_ID|UNIQUE_ID_URI|ACTION_FLAG|PERFORMING_PROFESSIONAL_FORENAME|PERFORMING_PROFESSIONAL_SURNAME|RECORDED_DATE|PRIMARY_SOURCE|VACCINATION_PROCEDURE_CODE|VACCINATION_PROCEDURE_TERM|DOSE_SEQUENCE|VACCINE_PRODUCT_CODE|VACCINE_PRODUCT_TERM|VACCINE_MANUFACTURER|BATCH_NUMBER|EXPIRY_DATE|SITE_OF_VACCINATION_CODE|SITE_OF_VACCINATION_TERM|ROUTE_OF_VACCINATION_CODE|ROUTE_OF_VACCINATION_TERM|DOSE_AMOUNT|DOSE_UNIT_CODE|DOSE_UNIT_TERM|INDICATION_CODE|LOCATION_CODE|LOCATION_CODE_TYPE_URI
31+
9990548609|Emily|Watson|19870214|2|WF8 4ED|20250306T13281701|B0C4P|https://fhir.hl7.org.uk/Id/urn-school-number|ACME-vacc123456|https://supplierABC/identifiers/vacc|UPDATE|Darren Official|Furlong Official|20250306|956951000000104|Seasonal influenza vaccination (procedure)|2|39114911000001104|COVID-19 Vaccine Vaxzevria (ChAdOx1 S [recombinant]) 0.5ml dose suspension (AstraZeneca)|AstraZeneca Ltd|4120Z001|20250702|368208006|Left upper arm structure (body structure)|78421000|Intramuscular route (qualifier value)|0.5||milliliter|443684005|X99999|https://fhir.nhs.uk/Id/ods-organization-code|[]
32+
9990548617|James|Turner|19911230|1|WF8 4ED|20250306T14203001|B0C4P|https://fhir.hl7.org.uk/Id/urn-school-number|ACME-vacc123456|https://supplierABC/identifiers/vacc|UPDATE|Tessy Official|Pat Official|20250306||956951000000104|Seasonal influenza vaccination (procedure)|1|39114911000001104|COVID-19 Vaccine Vaxzevria (ChAdOx1 S [recombinant]) 0.5ml dose suspension (AstraZeneca)|AstraZeneca Ltd|4120Z002|20250702|368208006|Left upper arm structure (body structure)|78421000|Intramuscular route (qualifier value)|0.5||milliliter|443684005|X99999|https://fhir.nhs.uk/Id/ods-organization-code|[]
33+
"""
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Utility function to build CSV row strings
2+
3+
4+
def build_row(header: str, csv_file: dict) -> str:
5+
"""
6+
Construct a CSV row string from the provided csv_file.
7+
Any missing header columns get empty string values.
8+
"""
9+
cols = header.split(",")
10+
return ",".join(str(csv_file.get(col, "")) for col in cols)

0 commit comments

Comments
 (0)