Skip to content

Commit 05a76ef

Browse files
Testcase refinement for rules stop
1 parent d61d88d commit 05a76ef

File tree

3 files changed

+26
-35
lines changed

3 files changed

+26
-35
lines changed

src/eligibility_signposting_api/model/rules.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ class IterationRule(BaseModel):
103103
rule_stop: RuleStop | None = Field(None, alias="RuleStop")
104104

105105
@field_validator("rule_stop", mode="before")
106-
def parse_yn_to_bool(cls, v: str) -> bool: # noqa: N805
106+
def parse_yn_to_bool(cls, v: str | bool) -> bool: # noqa: N805
107107
if isinstance(v, str):
108108
return v.upper() == "Y"
109-
return False
109+
return v
110110

111111
model_config = {"populate_by_name": True, "extra": "ignore"}
112112

tests/unit/model/test_rules.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import json
2+
13
import pytest
24
from dateutil.relativedelta import relativedelta
35
from faker import Faker
4-
from hamcrest import assert_that, equal_to, is_
6+
from hamcrest import assert_that
57

68
from eligibility_signposting_api.model.rules import IterationRule
79
from tests.fixtures.builders.model.rule import IterationFactory, RawCampaignConfigFactory
10+
from tests.fixtures.matchers.rules import is_iteration_rule
811

912

1013
def test_campaign_must_have_at_least_one_iteration():
@@ -72,23 +75,20 @@ def test_iteration_must_have_active_iteration_from_its_start(faker: Faker):
7275
(None, False),
7376
],
7477
)
75-
def test_rules_stop_in_iteration_rules_assigns_yn_to_bool(rule_stop: str, expected):
78+
def test_iteration_rule_deserialisation(rule_stop: str, expected):
7679
# Given
77-
iteration_rules_json = {
78-
"Type": "F",
79-
"Name": "Exclude TOO YOUNG",
80-
"Description": "Exclude too Young less than 75 on the day of run",
81-
"Priority": 110,
82-
"AttributeLevel": "PERSON",
83-
"AttributeName": "DATE_OF_BIRTH",
84-
"Operator": "Y>",
85-
"Comparator": "-75",
86-
"CohortLabel": "rsv_75_rolling",
87-
"RuleStop": rule_stop,
88-
}
80+
rule_json = f"""{{"Type": "F",
81+
"Name": "Exclude TOO YOUNG",
82+
"Description": "Exclude too Young less than 75 on the day of run",
83+
"Priority": 110,
84+
"AttributeLevel": "PERSON",
85+
"AttributeName": "DATE_OF_BIRTH",
86+
"Operator": "Y>",
87+
"Comparator": "-75",
88+
"RuleStop": "{rule_stop if rule_stop is not None else "null"}"}}"""
8989

9090
# When
91-
iteration_rules = IterationRule.model_validate(iteration_rules_json)
91+
actual = IterationRule.model_validate(json.loads(rule_json))
9292

9393
# Then
94-
assert_that(iteration_rules.rule_stop, is_(equal_to(expected)))
94+
assert_that(actual, is_iteration_rule().with_rule_stop(expected))

tests/unit/services/calculators/test_eligibility_calculator.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -816,39 +816,30 @@ def test_status_if_iteration_rules_contains_cohort_label_field(
816816
@pytest.mark.parametrize(
817817
("rule_stop", "expected_status", "test_comment"),
818818
[
819-
("Y", Status.not_actionable, "Stops at the first rule"),
820-
("N", Status.not_eligible, "Both the rules are executed"),
821-
("", Status.not_eligible, "Both the rules are executed"),
822-
(None, Status.not_eligible, "Both the rules are executed"),
819+
(True, Status.not_actionable, "Stops at the first rule"),
820+
(False, Status.not_eligible, "Both the rules are executed"),
823821
],
824822
)
825-
def test_rules_stop_behavior(rule_stop: str | None, expected_status: Status, test_comment: str, faker: Faker) -> None:
823+
def test_rules_stop_behavior(rule_stop: bool, expected_status: Status, test_comment: str, faker: Faker) -> None: # noqa: FBT001
826824
# Given
827825
nhs_number = NHSNumber(faker.nhs_number())
828826
date_of_birth = DateOfBirth(faker.date_of_birth(minimum_age=18, maximum_age=74))
829827
person_rows = person_rows_builder(nhs_number, date_of_birth=date_of_birth, cohorts=["cohort1"])
830828

831-
# Base rule template
832-
# Not using model factory to create Iteration rules since it sets boolean values for "Y"/"N"
833-
iteration_rules = [
834-
rule_builder.PersonAgeSuppressionRuleFactory.build(
835-
type=rules.RuleType.suppression, priority=10, rule_stop=rule_stop
836-
),
837-
rule_builder.PersonAgeSuppressionRuleFactory.build(type=rules.RuleType.suppression, priority=10),
838-
rule_builder.PersonAgeSuppressionRuleFactory.build(type=rules.RuleType.filter, priority=15),
839-
]
840-
841829
# Build campaign configuration
842830
campaign_config = rule_builder.CampaignConfigFactory.build(
843831
target="RSV",
844832
iterations=[
845833
rule_builder.IterationFactory.build(
846-
iteration_rules=[],
834+
iteration_rules=[
835+
rule_builder.PersonAgeSuppressionRuleFactory.build(priority=10, rule_stop=rule_stop),
836+
rule_builder.PersonAgeSuppressionRuleFactory.build(priority=10),
837+
rule_builder.PersonAgeSuppressionRuleFactory.build(type=rules.RuleType.filter, priority=15),
838+
],
847839
iteration_cohorts=[rule_builder.IterationCohortFactory.build(cohort_label="cohort1")],
848840
)
849841
],
850842
)
851-
campaign_config.iterations[0].iteration_rules.extend(iteration_rules)
852843

853844
calculator = EligibilityCalculator(person_rows, [campaign_config])
854845

0 commit comments

Comments
 (0)