Skip to content

Commit

Permalink
Merge branch 'fix/crp-units-and-normal-ranges' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanWillitts committed Sep 20, 2024
2 parents 03b1b37 + 58346e6 commit e0a422c
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ unreleased
- add QA reports for Missing Lab Values
- add Sodium field to Blood Result: Chemistry form (#521)
- add additional symptom choices to Signs and Symptoms form (#792)
- bump to edc 0.6.12
- add mg/L, update normal ranges for CRP (#618)
- bump to edc 0.6.13

0.1.55
------
Expand Down
279 changes: 279 additions & 0 deletions effect_subject/tests/tests/test_lab_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
PRESENT_AT_BASELINE,
TEN_X_9_PER_LITER,
)
from edc_reportable.units import MILLIGRAMS_PER_DECILITER, MILLIGRAMS_PER_LITER
from edc_utils import convert_php_dateformat, get_utcnow
from edc_visit_schedule.constants import DAY01, DAY03, DAY09

Expand Down Expand Up @@ -1142,3 +1143,281 @@ def test_sodium_g4_raises_if_not_acknowledged(self):
form_validator.validate()
except forms.ValidationError as e:
self.fail(f"ValidationError unexpectedly raised. Got {e}")

def test_negative_crp_values_lt_0_raises(self):
subject_visit = self.get_subject_visit(
subject_screening=self.subject_screening,
subject_consent=self.subject_consent,
visit_code=DAY01,
appt_datetime=self.subject_consent.consent_datetime,
)
panel_results_data = self.get_panel_results_data(subject_visit, "fbc")
for value in [-0.01, -0.02, -0.1, -0.2, -1, -9999]:
for units in [MILLIGRAMS_PER_DECILITER, MILLIGRAMS_PER_LITER]:
with self.subTest(value=value, units=units):
panel_results_data.update(
{
"crp_value": value,
"crp_units": units,
"crp_abnormal": NO,
"crp_reportable": NOT_APPLICABLE,
"results_abnormal": NO,
"results_reportable": NOT_APPLICABLE,
}
)
form = BloodResultsChemForm(panel_results_data)
self.assertFalse(form.is_valid(), "Expected form to be invalid.")
self.assertIn("crp_value", form.errors)
self.assertEqual(
["Ensure this value is greater than or equal to 0.0."],
form.errors.get("crp_value"),
)

def test_crp_in_normal_range_ok(self):
subject_visit = self.get_subject_visit(
subject_screening=self.subject_screening,
subject_consent=self.subject_consent,
visit_code=DAY01,
appt_datetime=self.subject_consent.consent_datetime,
)
panel_results_data = self.get_panel_results_data(subject_visit, "chemistry")
for normal_value in [0, 0.1, 1, 3, 4, 4.9, 5]:
for units in [MILLIGRAMS_PER_DECILITER, MILLIGRAMS_PER_LITER]:
with self.subTest(normal_value=normal_value, units=units):
panel_results_data.update(
{
"crp_value": (
normal_value
if units == MILLIGRAMS_PER_LITER
else round(normal_value / 10, 2)
),
"crp_units": units,
"crp_abnormal": NO,
"crp_reportable": NOT_APPLICABLE,
"results_abnormal": NO,
"results_reportable": NOT_APPLICABLE,
}
)

form = BloodResultsChemForm(panel_results_data)
self.assertTrue(
form.is_valid(),
f"Expected form to be valid. Got: {form.errors.as_data()}",
)

form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
try:
form_validator.validate()
except forms.ValidationError as e:
self.fail(f"ValidationError unexpectedly raised. Got {e}")

def test_abnormal_crp_raises_if_not_acknowledged_abnormal(self):
subject_visit = self.get_subject_visit(
subject_screening=self.subject_screening,
subject_consent=self.subject_consent,
visit_code=DAY01,
appt_datetime=self.subject_consent.consent_datetime,
)
panel_results_data = self.get_panel_results_data(subject_visit, "chemistry")
for normal_value in [5.05, 5.1, 6, 10, 50, 999]:
for units in [MILLIGRAMS_PER_DECILITER, MILLIGRAMS_PER_LITER]:
with self.subTest(normal_value=normal_value, units=units):
panel_results_data.update(
{
"crp_value": (
normal_value
if units == MILLIGRAMS_PER_LITER
else round(normal_value / 10, 2)
),
"crp_units": units,
"crp_abnormal": NO,
"crp_reportable": NOT_APPLICABLE,
"results_abnormal": NO,
"results_reportable": NOT_APPLICABLE,
}
)
form = BloodResultsChemForm(panel_results_data)
self.assertFalse(form.is_valid(), "Expected form to be invalid.")
self.assertIn("crp_value", form.errors)
self.assertIn(
"CRP is abnormal. ",
str(form.errors.get("crp_value")),
)

form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
with self.assertRaises(forms.ValidationError) as cm:
form_validator.validate()
self.assertIn("crp_value", cm.exception.error_dict)
self.assertIn(
"CRP is abnormal. ",
str(cm.exception.error_dict.get("crp_value")),
)
self.assertIn(
(
"Normal ranges: 0.0<=x<=5.0 mg/L "
if units == MILLIGRAMS_PER_LITER
else "Normal ranges: 0.0<=x<=0.5 mg/dL"
),
str(cm.exception.error_dict.get("crp_value")),
)

panel_results_data.update(
{
"crp_abnormal": YES,
"crp_reportable": NO,
"results_abnormal": NO,
"results_reportable": NO,
}
)
form = BloodResultsChemForm(panel_results_data)
self.assertFalse(form.is_valid(), "Expected form to be invalid.")
self.assertIn("results_abnormal", form.errors)
self.assertIn(
"1 of the above results is abnormal",
str(form.errors.get("results_abnormal")),
)

panel_results_data.update(
{
"crp_abnormal": YES,
"crp_reportable": NO,
"results_abnormal": YES,
"results_reportable": NO,
}
)
form = BloodResultsChemForm(panel_results_data)
self.assertTrue(
form.is_valid(),
f"Expected form to be valid. Got: {form.errors.as_data()}",
)

form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
try:
form_validator.validate()
except forms.ValidationError as e:
self.fail(f"ValidationError unexpectedly raised. Got {e}")

def test_abnormal_crp_not_reportable(self):
subject_visit = self.get_subject_visit(
subject_screening=self.subject_screening,
subject_consent=self.subject_consent,
visit_code=DAY01,
appt_datetime=self.subject_consent.consent_datetime,
)
panel_results_data = self.get_panel_results_data(subject_visit, "chemistry")
for normal_value in [5.05, 5.1, 6, 10, 50, 999]:
for units in [MILLIGRAMS_PER_DECILITER, MILLIGRAMS_PER_LITER]:
for crp_reportable in [
GRADE3,
GRADE4,
ALREADY_REPORTED,
PRESENT_AT_BASELINE,
]:
with self.subTest(
normal_value=normal_value,
units=units,
crp_reportable=crp_reportable,
):
panel_results_data.update(
{
"crp_value": (
normal_value
if units == MILLIGRAMS_PER_LITER
else round(normal_value / 10, 2)
),
"crp_units": units,
"crp_abnormal": YES,
"crp_reportable": NOT_APPLICABLE,
"results_abnormal": YES,
"results_reportable": NOT_APPLICABLE,
}
)
form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
with self.assertRaises(forms.ValidationError) as cm:
form_validator.validate()
self.assertIn("crp_reportable", cm.exception.error_dict)
self.assertIn(
"This field is applicable if result is abnormal",
str(cm.exception.error_dict.get("crp_reportable")),
)

panel_results_data.update(
{
"crp_abnormal": YES,
"crp_reportable": crp_reportable,
"results_abnormal": YES,
"results_reportable": NOT_APPLICABLE,
}
)
form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
with self.assertRaises(forms.ValidationError) as cm:
form_validator.validate()
self.assertIn("crp_reportable", cm.exception.error_dict)
self.assertIn(
"Invalid. Expected 'No' or 'Not applicable'.",
str(cm.exception.error_dict.get("crp_reportable")),
)

panel_results_data.update(
{
"crp_abnormal": YES,
"crp_reportable": NO,
"results_abnormal": YES,
"results_reportable": NOT_APPLICABLE,
}
)
form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
with self.assertRaises(forms.ValidationError) as cm:
form_validator.validate()
self.assertIn("results_reportable", cm.exception.error_dict)
self.assertIn(
"This field is applicable.",
str(cm.exception.error_dict.get("results_reportable")),
)

panel_results_data.update(
{
"crp_abnormal": YES,
"crp_reportable": NO,
"results_abnormal": YES,
"results_reportable": YES,
}
)
form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
with self.assertRaises(forms.ValidationError) as cm:
form_validator.validate()
self.assertIn("results_reportable", cm.exception.error_dict)
self.assertIn(
"None of the above results are reportable",
str(cm.exception.error_dict.get("results_reportable")),
)

panel_results_data.update(
{
"crp_abnormal": YES,
"crp_reportable": NO,
"results_abnormal": YES,
"results_reportable": NO,
}
)
form_validator = BloodResultsChemFormValidator(
cleaned_data=panel_results_data, model=BloodResultsChem
)
try:
form_validator.validate()
except forms.ValidationError as e:
self.fail(f"ValidationError unexpectedly raised. Got {e}")
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ zip_safe = False
include_package_data = True
packages = find:
install_requires =
edc==0.6.12
edc==0.6.13
edc-csf==0.3.6
edc-microbiology==0.3.10
beautifulsoup4
Expand Down

0 comments on commit e0a422c

Please sign in to comment.