Skip to content

Commit

Permalink
refactor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bwalsh committed Jan 4, 2025
1 parent 48fb4b3 commit a58f274
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 18 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ To use the `fq` command, you need to provide the necessary options. Below is an
```sh
fq --fhir-base-url <FHIR_BASE_URL> \
--graph-definition-id <GRAPH_DEFINITION_ID> \
--start-resource-type <START_RESOURCE_TYPE> \
--start-resource-id <START_RESOURCE_ID> \
--path </Resource?params> \
[--graph-definition-file-path <GRAPH_DEFINITION_FILE_PATH>] \
[--db_path <DB_PATH>] \
[--debug]
Expand Down
6 changes: 3 additions & 3 deletions fhir_query/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,14 +419,14 @@ def __init__(self, fhir_base_url: str):
"""
self.fhir_base_url = fhir_base_url

async def fetch_resource(self, resource_type: str, spinner: Halo = None) -> list[dict[str, Any]]:
async def fetch_resource(self, resource_type: str, spinner: Halo = None) -> dict[str, dict[Any, Any]]:
"""
Fetch resources of a given type from the FHIR server.
:param spinner: A Halo spinner object to show progress.
:param resource_type: The type of resource to fetch.
:return: A list of resources.
"""
counts = {resource_type: {}}
counts: dict = {resource_type: {}}
category_counts = counts[resource_type]
# A client with a 60s timeout for connecting, and a 10s timeout elsewhere.
timeout = httpx.Timeout(10.0, connect=60.0)
Expand Down Expand Up @@ -464,7 +464,7 @@ async def fetch_resource(self, resource_type: str, spinner: Halo = None) -> list
url = next_link
return counts

async def collect(self, resource_types: list[str], spinner: Halo = None) -> dict:
async def collect(self, resource_types: list[str], spinner: Halo = None) -> list:
"""
Collect vocabularies from the specified resource types.
:param spinner: A Halo spinner object to show progress.
Expand Down
2 changes: 1 addition & 1 deletion fhir_query/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def vocabularies(
if fhir_base_url.endswith("/"):
fhir_base_url = fhir_base_url[:-1]

async def collect_vocabularies(_runner: VocabularyRunner, _spinner: Halo) -> dict:
async def collect_vocabularies(_runner: VocabularyRunner, _spinner: Halo) -> list:
_counts = await _runner.collect(
resource_types=["Observation", "Condition", "Procedure", "Medication", "Specimen", "Encounter", "DocumentReference"],
spinner=_spinner,
Expand Down
2 changes: 1 addition & 1 deletion fhir_query/dataframer.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ def get_resources_by_reference(self, resource_type: str, reference_field: str, r
resource = json.loads(raw_resource)

# determine which how to process the field
if reference_field == "focus":
if reference_field == "focus" and "focus" in resource:
# add the resource (eg observation) for each focus reference to the dict
for i in range(len(resource["focus"])):
reference_key = get_nested_value(resource, [reference_field, i, "reference"])
Expand Down
141 changes: 139 additions & 2 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ def mock_fhir_server(httpx_mock: HTTPXMock) -> Generator[HTTPXMock, Any, Any]:
def dummy_callback(request: httpx.Request) -> Response:

logging.warning(f"Request: {request.url.path}, {str(request.url.params)}")

if request.url.path == "/ResearchStudy" and str(request.url.params) == "_id=123":
return Response(
200, json={"resourceType": "Bundle", "entry": [{"resource": {"resourceType": "ResearchStudy", "id": "123"}}]}
)

if request.url.path == "/ResearchSubject":
return Response(
200,
json={
"resourceType": "Bundle",
"entry": [
{"resource": {"resourceType": "ResearchSubject", "id": "123RS", "subject": {"reference": "Patient/123"}}},
],
},
)

if request.url.path == "/Patient/123":
return Response(200, json={"resourceType": "Patient", "id": "123"})

Expand All @@ -23,7 +40,7 @@ def dummy_callback(request: httpx.Request) -> Response:
if (
request.url.path == "/Patient"
and str(request.url.params)
== "_has%3AResearchSubject%3Asubject%3Astudy=ResearchStudy%2F123&_revinclude=Group%3Amember&_count=1000&_total=accurate"
== "_has%3AResearchSubject%3Asubject%3Astudy=ResearchStudy%2F123&_revinclude=ResearchSubject%3Asubject&_revinclude=Group%3Amember&_count=1000&_total=accurate"
):
return Response(
200,
Expand Down Expand Up @@ -52,9 +69,129 @@ def dummy_callback(request: httpx.Request) -> Response:
},
)

if request.url.path == "/Group" and "member=Specimen" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "Group", "id": "G1"}},
],
},
)

if request.url.path == "/DocumentReference" and "subject=Group" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "DocumentReference", "id": "DR1"}},
],
},
)

if request.url.path == "/DocumentReference" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "DocumentReference", "id": "DR2"}},
],
},
)

if request.url.path == "/Observation" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "Observation", "id": "O1"}},
],
},
)

if request.url.path == "/Procedure" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "Procedure", "id": "P1"}},
],
},
)

if request.url.path == "/ServiceRequest" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "ServiceRequest", "id": "SR1"}},
],
},
)

if request.url.path == "/ImagingStudy" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "ImagingStudy", "id": "IS1"}},
],
},
)

if request.url.path == "/Condition" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "Condition", "id": "C1"}},
],
},
)

if request.url.path == "/Medication" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "Medication", "id": "M1"}},
],
},
)

if request.url.path == "/MedicationAdministration" and "subject=Patient" in str(request.url.params):
return Response(
200,
json={
"resourceType": "Bundle",
"type": "searchset",
"entry": [
{"resource": {"resourceType": "MedicationAdministration", "id": "MA1"}},
],
},
)

# unexpected request
print(request.url, str(request.url.params))
assert False, f"Unexpected url {request.url.path}, {str(request.url.params)}"
assert False, f"Unexpected url:{request.url} path:{request.url.path}, params:{str(request.url.params)}"

httpx_mock.add_callback(dummy_callback)

Expand Down
3 changes: 1 addition & 2 deletions tests/unit/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ def test_help_option() -> None:
assert "--fhir-base-url" in output
assert "--graph-definition-id" in output
assert "--graph-definition-file-path" in output
assert "--start-resource-type" in output
assert "--start-resource-id" in output
assert "--path" in output
assert "--db-path" in output
assert "--dry-run" in output
assert "--debug" in output
Expand Down
43 changes: 36 additions & 7 deletions tests/unit/test_mock_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,12 @@ def test_runner(tmp_path: str) -> None:
[
"--fhir-base-url",
"http://testserver",
"--start-resource-type",
"ResearchStudy",
"--start-resource-id",
"123",
"--path",
"/ResearchStudy?_id=123",
"--db-path",
f"{tmp_path}/fhir-query.sqlite",
"--graph-definition-file-path",
"tests/fixtures/GraphDefinition.yaml",
"tests/fixtures/ResearchStudyGraph.yaml",
"--log-file",
f"{tmp_path}/fhir-query.log",
"--debug",
Expand All @@ -59,10 +57,41 @@ def test_runner(tmp_path: str) -> None:
# test the database

db = Dataframer(f"{tmp_path}/fhir-query.sqlite")
assert db.count_resource_types() == {"Patient": 3, "Specimen": 3}
count_resource_types = db.count_resource_types()
print(count_resource_types)
assert count_resource_types == {
"Condition": 1,
"DocumentReference": 2,
"Group": 1,
"ImagingStudy": 1,
"MedicationAdministration": 1,
"Observation": 1,
"Patient": 3,
"Procedure": 1,
"ResearchStudy": 1,
"ResearchSubject": 1,
"ServiceRequest": 1,
"Specimen": 3,
}

aggregated = db.aggregate()
assert sorted(aggregated.keys()) == ["Patient", "Specimen"]
aggregated_keys = sorted(aggregated.keys())
print(aggregated_keys)
assert aggregated_keys == [
"Condition",
"DocumentReference",
"Group",
"ImagingStudy",
"MedicationAdministration",
"Observation",
"Patient",
"Procedure",
"ResearchStudy",
"ResearchSubject",
"ServiceRequest",
"Specimen",
]

assert aggregated["Patient"]["count"] == 3
assert aggregated["Specimen"]["count"] == 3
assert aggregated["Specimen"]["references"]["Patient"]["count"] == 3
Expand Down

0 comments on commit a58f274

Please sign in to comment.