Spaces:
Sleeping
Sleeping
File size: 3,016 Bytes
bfd6783 | 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 | import pytest
from finbot.categories import CATEGORIES, categorise, coerce, is_valid, label
class TestCategorise:
@pytest.mark.parametrize(
"text,expected",
[
("uber ride home", "transport"),
("netflix monthly", "subscriptions"),
("bigbasket order", "groceries"),
("swiggy dinner", "food_dining"),
("petrol pump", "fuel"),
("electricity bill", "utilities"),
("apollo pharmacy", "health"),
("bookmyshow tickets", "entertainment"),
("amazon order", "shopping"),
("atm withdrawal", "cash"),
("salary credited", "income"),
],
)
def test_keyword_hits(self, text, expected):
category, confidence = categorise(text)
assert category == expected
assert confidence == 1.0
def test_unknown_returns_other_with_zero_confidence(self):
category, confidence = categorise("blorptastic widget")
assert category == "other"
assert confidence == 0.0
def test_empty_input(self):
assert categorise("") == ("other", 0.0)
def test_specificity_order_fuel_beats_transport(self):
# A petrol pump is fuel, even though it is transport-adjacent.
assert categorise("indian oil petrol")[0] == "fuel"
def test_specificity_order_subscription_beats_entertainment(self):
assert categorise("netflix")[0] == "subscriptions"
def test_word_boundaries_prevent_false_hits(self):
# "cashew" must not match the "cash" keyword.
assert categorise("cashew nuts")[0] != "cash"
# "gasket" must not match "gas station".
assert categorise("engine gasket")[0] != "fuel"
def test_merchant_is_considered(self):
category, _ = categorise("monthly charge", merchant="Spotify")
assert category == "subscriptions"
def test_case_insensitive(self):
assert categorise("UBER RIDE")[0] == "transport"
class TestCoerce:
@pytest.mark.parametrize(
"raw,expected",
[
("food_dining", "food_dining"),
("Food", "food_dining"),
("dining", "food_dining"),
("grocery", "groceries"),
("healthcare", "health"),
("Subscription", "subscriptions"),
("misc", "other"),
("", "other"),
("total nonsense", "other"),
],
)
def test_coerce(self, raw, expected):
assert coerce(raw) == expected
def test_every_result_is_a_valid_category(self):
# A stray label from a model must never reach the ledger, or totals
# fragment across categories that do not exist.
for raw in ["", "???", "Investments", "food", "TRANSPORT", "x" * 200]:
assert is_valid(coerce(raw))
class TestLabels:
def test_every_category_has_a_label(self):
for category in CATEGORIES:
assert label(category)
assert label(category) != category or "_" not in category
|