Skip to content

Commit

Permalink
Use fixtures to test extension validation
Browse files Browse the repository at this point in the history
  • Loading branch information
pipliggins committed Aug 20, 2024
1 parent 77f7572 commit bdd2952
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 78 deletions.
7 changes: 6 additions & 1 deletion fhirflat/resources/procedure.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ def validate_extension_contents(cls, extensions):
rel_phase_count = sum(isinstance(item, relativePeriod) for item in extensions)
detail_count = sum(isinstance(item, timingPhaseDetail) for item in extensions)

if duration_count > 1 or tim_phase_count > 1 or rel_phase_count > 1:
if (
duration_count > 1
or tim_phase_count > 1
or rel_phase_count > 1
or detail_count > 1
):
raise ValueError(
"duration, timingPhase, timingPhaseDetail and relativePeriod can only appear once." # noqa E501
)
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import pytest

from fixtures.extensions import (
raises_phase_plus_detail_error,
raises_phase_duplicate_error,
)
106 changes: 106 additions & 0 deletions tests/fixtures/extensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import pytest


@pytest.fixture
def raises_phase_plus_detail_error():
def _ext_test(fhir_input, resource):
fhir_input["extension"] = [
{
"url": "timingPhaseDetail",
"extension": [
{
"url": "timingDetail",
"valueRange": {
"low": {"value": -7, "unit": "days"},
"high": {"value": 0, "unit": "days"},
},
},
{
"url": "timingPhase",
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "281379000",
"display": "pre-admission",
}
]
},
},
],
},
{
"url": "timingPhase",
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": 278307001,
"display": "on admission",
}
]
},
},
]
source = fhir_input
with pytest.raises(ValueError, match="cannot appear together"):
resource(**source)

return _ext_test


@pytest.fixture
def raises_phase_duplicate_error():
def _ext_test(fhir_input, resource):
fhir_input["extension"] = [
{
"url": "timingPhaseDetail",
"extension": [
{
"url": "timingDetail",
"valueRange": {
"low": {"value": -7, "unit": "days"},
"high": {"value": 0, "unit": "days"},
},
},
{
"url": "timingPhase",
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "281379000",
"display": "pre-admission",
}
]
},
},
],
},
{
"url": "timingPhaseDetail",
"extension": [
{
"url": "timingPhase",
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": 278307001,
"display": "on admission",
}
]
},
},
{
"url": "timingDetail",
"valueString": "ever",
},
],
},
]
source = fhir_input
with pytest.raises(ValueError, match="can only appear once"):
resource(**source)

return _ext_test
41 changes: 22 additions & 19 deletions tests/test_condition_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,25 +200,6 @@
]
},
},
# {
# "url": "timingDetail",
# "valueRange": {
# "low": {"value": -7, "unit": "days"},
# "high": {"value": 0, "unit": "days"},
# },
# },
# {
# "url": "timingPhase",
# "valueCodeableConcept": {
# "coding": [
# {
# "system": "http://snomed.info/sct",
# "code": "281379000",
# "display": "pre-admission",
# }
# ]
# },
# },
{
"url": "timingPhaseDetail",
"extension": [
Expand Down Expand Up @@ -371,3 +352,25 @@ def test_condition_extension_validation_error():
def test_from_flat_validation_error_single():
with pytest.raises(ValidationError, match="1 validation error for Condition"):
Condition.from_flat("tests/data/condition_flat_missing_subject.parquet")


@pytest.mark.usefixtures(
"raises_phase_plus_detail_error", "raises_phase_duplicate_error"
)
def test_extension_raises_errors(
raises_phase_plus_detail_error, raises_phase_duplicate_error
):
fhir_input = {
"id": "c201",
"subject": {"reference": "Patient/f201"},
"clinicalStatus": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/condition-clinical", # noqa: E501
"code": "resolved",
}
]
},
}
raises_phase_plus_detail_error(fhir_input, Condition)
raises_phase_duplicate_error(fhir_input, Condition)
25 changes: 25 additions & 0 deletions tests/test_diagnosticreport_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
from fhirflat.resources.diagnosticreport import DiagnosticReport
import datetime
import pytest


DICT_INPUT = {
Expand Down Expand Up @@ -175,3 +176,27 @@ def test_observation_from_flat():
flat_report = DiagnosticReport.from_flat("tests/data/diagnosticreport_flat.parquet")

assert report == flat_report


@pytest.mark.usefixtures(
"raises_phase_plus_detail_error", "raises_phase_duplicate_error"
)
def test_extension_raises_errors(
raises_phase_plus_detail_error, raises_phase_duplicate_error
):
fhir_input = {
"resourceType": "DiagnosticReport",
"id": "f001",
"status": "final",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "58410-2",
"display": "Complete blood count (hemogram) panel - Blood by Automated count", # noqa: E501
}
]
},
}
raises_phase_plus_detail_error(fhir_input, DiagnosticReport)
raises_phase_duplicate_error(fhir_input, DiagnosticReport)
15 changes: 15 additions & 0 deletions tests/test_encounter_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,18 @@ def test_from_flat_validation_error_multi_resources():
assert len(errors) == 1
assert "invalid datetime format" in errors.iloc[0]["validation_error"]
os.remove("encounter_errors.csv")


@pytest.mark.usefixtures(
"raises_phase_plus_detail_error", "raises_phase_duplicate_error"
)
def test_extension_raises_errors(
raises_phase_plus_detail_error, raises_phase_duplicate_error
):
fhir_input = {
"resourceType": "Encounter",
"id": "f203",
"status": "completed",
}
raises_phase_plus_detail_error(fhir_input, Encounter)
raises_phase_duplicate_error(fhir_input, Encounter)
68 changes: 23 additions & 45 deletions tests/test_immunization_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,48 +238,26 @@ def test_immunization_from_flat():
assert vacc == flat_vacc


def test_immunization_extension_validation_error():
with pytest.raises(ValueError, match="can only appear once."):
Immunization(
**{
"id": 2,
"status": "in-progress",
"extension": [
{
"url": "timingPhase",
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": 278307001,
"display": "on admission",
}
]
},
},
{
"url": "timingPhase",
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": 278307005,
"display": "during admission",
}
]
},
},
],
"patient": {"reference": "Patient/example"},
"occurrenceDateTime": "2021-09-12T00:00:00",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx",
"code": "175",
"display": "Rabies - IM Diploid cell culture",
}
],
},
}
)
@pytest.mark.usefixtures(
"raises_phase_plus_detail_error", "raises_phase_duplicate_error"
)
def test_extension_raises_errors(
raises_phase_plus_detail_error, raises_phase_duplicate_error
):
fhir_input = {
"id": 2,
"status": "in-progress",
"patient": {"reference": "Patient/example"},
"occurrenceDateTime": "2021-09-12T00:00:00",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx",
"code": "175",
"display": "Rabies - IM Diploid cell culture",
}
],
},
}
raises_phase_plus_detail_error(fhir_input, Immunization)
raises_phase_duplicate_error(fhir_input, Immunization)
25 changes: 25 additions & 0 deletions tests/test_observation_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
from fhirflat.resources.observation import Observation
import datetime
import pytest

# TODO: extra observation with a single component for travel.

Expand Down Expand Up @@ -382,3 +383,27 @@ def test_observation_from_flat():
flat_bp = Observation.from_flat("tests/data/observation_flat.parquet")

assert bp == flat_bp


@pytest.mark.usefixtures(
"raises_phase_plus_detail_error", "raises_phase_duplicate_error"
)
def test_extension_raises_errors(
raises_phase_plus_detail_error, raises_phase_duplicate_error
):
fhir_input = {
"resourceType": "Observation",
"status": "final",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "85354-9",
"display": "Blood pressure panel with all children optional",
}
],
"text": "Blood pressure systolic & diastolic",
},
}
raises_phase_plus_detail_error(fhir_input, Observation)
raises_phase_duplicate_error(fhir_input, Observation)
26 changes: 13 additions & 13 deletions tests/test_procedure_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,16 @@ def test_procedure_from_flat():
assert chemo == flat_chemo


def test_procedure_extension_validation_error():
with pytest.raises(ValueError, match="can only appear once"):
Procedure(
**{
"id": 1,
"status": "completed",
"subject": {"reference": "Patient/example"},
"extension": [
{"url": "duration", "valueQuantity": {"value": 1, "unit": "d"}},
{"url": "duration", "valueQuantity": {"value": 2, "unit": "d"}},
],
}
)
@pytest.mark.usefixtures(
"raises_phase_plus_detail_error", "raises_phase_duplicate_error"
)
def test_extension_raises_errors(
raises_phase_plus_detail_error, raises_phase_duplicate_error
):
fhir_input = {
"id": 1,
"status": "completed",
"subject": {"reference": "Patient/example"},
}
raises_phase_plus_detail_error(fhir_input, Procedure)
raises_phase_duplicate_error(fhir_input, Procedure)

0 comments on commit bdd2952

Please sign in to comment.