Skip to content

Commit

Permalink
[#179] Add hypothesis and some property tests for core.model_metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
riley-harper committed Dec 11, 2024
1 parent 7817ed5 commit b93ab6f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
46 changes: 46 additions & 0 deletions hlink/tests/core/model_metrics_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
# For copyright and licensing information, see the NOTICE and LICENSE files
# in this project's top-level directory, and also on-line at:
# https://github.com/ipums/hlink
import math

from hypothesis import assume, given
import hypothesis.strategies as st

from hlink.linking.core.model_metrics import mcc, precision, recall

NonNegativeInt = st.integers(min_value=0)


def test_mcc_example() -> None:
tp = 3112
Expand All @@ -26,6 +32,26 @@ def test_precision_example() -> None:
), "expected precision to be near 0.9381972"


@given(true_pos=NonNegativeInt, false_pos=NonNegativeInt)
def test_precision_between_0_and_1(true_pos: int, false_pos: int) -> None:
"""
Under "normal circumstances" (there were at least some positive predictions)
precision()'s range is the interval [0.0, 1.0].
"""
assume(true_pos + false_pos > 0)
precision_score = precision(true_pos, false_pos)
assert 0.0 <= precision_score <= 1.0


def test_precision_no_positive_predictions() -> None:
"""
When there are no positive predictions, true_pos=0 and false_pos=0, and
precision is not well defined. In this case we return NaN.
"""
precision_score = precision(0, 0)
assert math.isnan(precision_score)


def test_recall_example() -> None:
tp = 3112
fn = 1134
Expand All @@ -34,3 +60,23 @@ def test_recall_example() -> None:
assert (
abs(recall_score - 0.7329251) < 0.0001
), "expected recall to be near 0.7329251"


@given(true_pos=NonNegativeInt, false_neg=NonNegativeInt)
def test_recall_between_0_and_1(true_pos: int, false_neg: int) -> None:
"""
Under "normal circumstances" (there is at least one true positive or false
negative), the range of recall() is the interval [0.0, 1.0].
"""
assume(true_pos + false_neg > 0)
recall_score = recall(true_pos, false_neg)
assert 0.0 <= recall_score <= 1.0


def test_recall_no_true_pos_or_false_neg() -> None:
"""
When both true_pos and false_neg are 0, recall is not well defined, and we
return NaN.
"""
recall_score = recall(0, 0)
assert math.isnan(recall_score)
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies = [
[project.optional-dependencies]
dev = [
"pytest>=7.1.0",
"hypothesis>=6.0",
"black>=23.0",
"flake8>=5.0",
"pre-commit>=2.0",
Expand Down

0 comments on commit b93ab6f

Please sign in to comment.