-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest_eicr_augmenter.py
More file actions
224 lines (185 loc) · 9.43 KB
/
test_eicr_augmenter.py
File metadata and controls
224 lines (185 loc) · 9.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
from datetime import datetime
from pathlib import Path
from uuid import UUID
from zoneinfo import ZoneInfo
import pytest
from pytest_mock import MockerFixture
from pytest_snapshot.plugin import Snapshot
from augmentation.models import Metadata
from augmentation.models import NonstandardCodeInstanceMetadata
from augmentation.models.config import ApplicationCode
from augmentation.models.config import AugmenterConfig
from augmentation.models.config import TTCAugmenterConfig
from augmentation.services.augmenter import Augmenter
from augmentation.services.eicr_augmenter import EICRAugmenter
from shared_models import Code
from shared_models import DataField
from shared_models import NonstandardCodeInstance
EXAMPLE_EICRS_DIRECTORY = Path(__file__).parent.parent / "assets"
DATA_CONFIG: AugmenterConfig = TTCAugmenterConfig()
BASE_XPATH = "/ClinicalDocument/component/structuredBody/component/section/entry/component/observation/code/originalText/text()"
eicr_path = EXAMPLE_EICRS_DIRECTORY / "basic_test_eicr.xml"
with eicr_path.open() as f:
BASIC_ECR = f.read()
eicr_path = EXAMPLE_EICRS_DIRECTORY / "basic_test_eicr_related_doc.xml"
with eicr_path.open() as f:
BASIC_ECR_RELATED_DOC = f.read()
eicr_path = EXAMPLE_EICRS_DIRECTORY / "empty_eicr.xml"
with eicr_path.open() as f:
EMPTY_ECR = f.read()
@pytest.mark.time_machine(datetime(2026, 2, 13, 15, 27, 57, tzinfo=ZoneInfo("America/New_York")))
class TestEicrAugmenter:
def test_no_document_data(self):
"""Tests raising error when no document data is provided."""
with pytest.raises(ValueError, match=r"Document payload must be a non-empty string!"):
EICRAugmenter("", [])
def test_initialization(self):
"""Tests initialization of the TTC augmenter."""
augmenter = EICRAugmenter(BASIC_ECR, [])
assert augmenter.application_code.value == ApplicationCode.TEXT_TO_CODE.value
assert augmenter.config == DATA_CONFIG
assert augmenter.original_xml == BASIC_ECR
def test_basic_eicr(self, mocker: MockerFixture, snapshot: Snapshot):
"""Tests augmentor run method."""
doc_id = UUID("12345678-1234-5678-1234-567812345678")
set_id = UUID("87654321-4321-8765-4321-876543218765")
mocker.patch("augmentation.services.eicr_augmenter.uuid4", side_effect=[doc_id, set_id])
augmenter = EICRAugmenter(
BASIC_ECR,
[
NonstandardCodeInstance(
schematron_error="text-to-code-test",
schematron_error_xpath="/ClinicalDocument/component/structuredBody/component/section/entry/component/observation",
field_type=DataField.LAB_TEST_NAME_RESULTED,
new_translation=Code(
code="10101010",
display_name="Chad new LOINC code",
original_text="Loser old LOINC",
),
)
],
)
metadata = augmenter.augment()
result = augmenter.augmented_xml
# test was failing due to whitespace at the end of the result so stripping it here
snapshot.assert_match(result.strip(), "basic_eicr_augmented.xml")
assert metadata == Metadata(
original_eicr_id="c8516bdc-8bb2-40aa-8dae-20a77546488f",
augmented_eicr_id="12345678-1234-5678-1234-567812345678",
nonstandard_codes=[
NonstandardCodeInstanceMetadata(
schematron_error="text-to-code-test",
schematron_error_xpath="/ClinicalDocument/component/structuredBody/component/section/entry/component/observation",
field_type=DataField.LAB_TEST_NAME_RESULTED,
new_translation=Code(
code="10101010",
display_name="Chad new LOINC code",
original_text="Loser old LOINC",
),
new_translation_xpath="/ClinicalDocument/component/structuredBody/component/section/entry/component/observation/code/translation",
)
],
)
def test_eicr_related_doc(self, mocker: MockerFixture, snapshot: Snapshot):
"""Tests augmentor run method."""
doc_id = UUID("12345678-1234-5678-1234-567812345678")
set_id = UUID("87654321-4321-8765-4321-876543218765")
mocker.patch("augmentation.services.eicr_augmenter.uuid4", side_effect=[doc_id, set_id])
nonstandard_codes = [
NonstandardCodeInstance(
schematron_error="text-to-code-test",
schematron_error_xpath="/ClinicalDocument/component/structuredBody/component/section/entry/component/observation",
field_type=DataField.LAB_TEST_NAME_RESULTED,
new_translation=Code(
code="10101010",
display_name="Chad new LOINC code",
original_text="Loser old LOINC",
),
)
]
augmenter = EICRAugmenter(
BASIC_ECR_RELATED_DOC,
nonstandard_codes,
)
metadata = augmenter.augment()
result = augmenter.augmented_xml
# test was failing due to whitespace at the end of the result so stripping it here
snapshot.assert_match(result.strip(), "basic_eicr_related_doc_augmented.xml")
assert metadata == Metadata(
original_eicr_id="c8516bdc-8bb2-40aa-8dae-20a77546488f",
augmented_eicr_id="12345678-1234-5678-1234-567812345678",
nonstandard_codes=[
NonstandardCodeInstanceMetadata(
schematron_error="text-to-code-test",
schematron_error_xpath="/ClinicalDocument/component/structuredBody/component/section/entry/component/observation",
field_type=DataField.LAB_TEST_NAME_RESULTED,
new_translation=Code(
code="10101010",
display_name="Chad new LOINC code",
original_text="Loser old LOINC",
),
new_translation_xpath="/ClinicalDocument/component/structuredBody/component/section/entry/component/observation/code/translation",
)
],
)
def test_get_old_document_id_preserves_assigning_authority_name_when_present(self):
"""Tests old document id preserves assigningAuthorityName when present."""
eicr_with_assigning_authority_name = BASIC_ECR.replace(
' assigningAuthorityName="original-document"',
' assigningAuthorityName="original-document"',
).replace(
' assigningAuthorityName="TEXT_TO_CODE"',
"",
)
augmenter = EICRAugmenter(eicr_with_assigning_authority_name, [])
parent_doc_id = augmenter._get_old_document_id()
assert parent_doc_id.get("assigningAuthorityName") == "original-document"
def test_empty_eicr(self, mocker: MockerFixture):
"""Tests augmentor run method."""
doc_id = UUID("12345678-1234-5678-1234-567812345678")
set_id = UUID("87654321-4321-8765-4321-876543218765")
mocker.patch("augmentation.services.eicr_augmenter.uuid4", side_effect=[doc_id, set_id])
with pytest.raises(
ValueError,
match=r"Unable to find tag in eICR document for XPath: /ClinicalDocument/id/@root",
):
EICRAugmenter(EMPTY_ECR, [])
def test_get_old_document_id_sets_assigning_authority_name_when_missing(self):
"""Tests old document id gets assigningAuthorityName when missing."""
augmenter = EICRAugmenter(BASIC_ECR, [])
parent_doc_id = augmenter._get_old_document_id()
assert parent_doc_id.get("assigningAuthorityName") == "original-document"
def test_get_old_xrfm_related_document_returns_none_when_missing(self):
"""Tests old XFRM relatedDocument returns None when missing."""
augmenter = EICRAugmenter(BASIC_ECR, [])
related_document = augmenter._get_old_xrfm_related_document()
assert related_document is None
def test_get_old_xrfm_related_document_returns_element_when_present(self):
"""Tests old XFRM relatedDocument is returned when present."""
augmenter = EICRAugmenter(BASIC_ECR_RELATED_DOC, [])
related_document = augmenter._get_old_xrfm_related_document()
assert related_document is not None
assert related_document.tag == "relatedDocument"
assert related_document.get("typeCode") == "XFRM"
def test_validate_config_raises_value_error_when_application_code_does_not_match(self):
"""Tests config validation when application code does not match."""
class TestAugmenter(Augmenter):
def augment(self) -> Metadata:
return Metadata(
original_eicr_id="original-doc-id",
augmented_eicr_id="augmented-doc-id",
nonstandard_codes=[],
)
class InvalidConfig:
application_code = "wrong-application-code"
with pytest.raises(
ValueError,
match=r"Config application code wrong-application-code does not match Augmenter application code ApplicationCode.TEXT_TO_CODE.",
):
TestAugmenter(
BASIC_ECR,
InvalidConfig(),
)
def test_augment_base_method_returns_none(self):
"""Tests abstract base augment method body."""
assert Augmenter.augment(object()) is None