vadugwi / engine /tests /test_word_classifier.py
deucebucket's picture
Data flywheel: 50q + word ratings + FastAPI backend (anonymous collection)
6da6c49 verified
Raw
History Blame Contribute Delete
6.38 kB
"""Tests for V3 Layer 1: Word Role Classifier."""
import pytest
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from engine.word_classifier import classify_sentence, classify_word, WordRole
class TestBasicRoles:
def test_self_reference(self):
roles = classify_sentence(["I", "am", "happy"])
assert roles[0].role == "SELF_REF"
def test_emotional_word(self):
roles = classify_sentence(["I", "am", "happy"])
assert roles[2].role == "EMOTIONAL"
assert roles[2].force is not None
assert roles[2].force[0] > 0 # happy = positive V
def test_negator(self):
roles = classify_sentence(["I", "am", "not", "happy"])
assert roles[2].role == "NEGATOR"
def test_amplifier(self):
roles = classify_sentence(["I", "am", "very", "happy"])
assert roles[2].role == "AMPLIFIER"
def test_transfer(self):
roles = classify_sentence(["I", "gave", "my", "dog", "to", "neighbor"])
assert roles[1].role == "TRANSFER"
assert roles[3].role == "RELATION_REF" # dog is relationship
assert roles[5].role == "RELATION_REF"
def test_method(self):
roles = classify_sentence(["bought", "a", "bunch", "of", "pills"])
assert roles[0].role == "ACQUIRE"
assert roles[4].role == "METHOD"
def test_finality(self):
roles = classify_sentence(["this", "is", "the", "last", "time"])
assert roles[3].role == "FINALITY"
class TestPositionOverrides:
def test_give_hug_not_transfer(self):
"""'give me a hug' — give is still TRANSFER but context matters at structure level."""
roles = classify_sentence(["give", "me", "a", "hug"])
assert roles[0].role == "TRANSFER"
# Structure detector (Task 3) will see TRANSFER + no POSSESSION = not farewell
def test_fine_after_self(self):
roles = classify_sentence(["im", "fine"])
assert roles[1].role == "PEACE"
def test_fine_without_self_ref(self):
"""'fine' not after SELF_REF should stay in its base role."""
roles = classify_sentence(["that", "is", "fine"])
# "fine" is in PEACE set, so it's PEACE regardless — position override
# only matters if it could be EMOTIONAL vs PEACE
assert roles[2].role == "PEACE"
def test_chopper(self):
roles = classify_sentence(["I", "love", "you", "but", "im", "leaving"])
assert roles[3].role == "CHOPPER"
def test_still_is_temporal(self):
"""'still' is always TEMPORAL — freshness/persistence marker."""
roles = classify_sentence(["I", "still", "feel", "bad"])
assert roles[1].role == "TEMPORAL"
def test_never_is_negator(self):
"""'never' should be NEGATOR, not TEMPORAL."""
roles = classify_sentence(["I", "never", "said", "that"])
assert roles[1].role == "NEGATOR"
def test_just_before_acquire_is_temporal(self):
"""'just bought' = recently acquired → TEMPORAL."""
roles = classify_sentence(["I", "just", "bought", "a", "car"])
assert roles[1].role == "TEMPORAL"
assert roles[2].role == "ACQUIRE"
def test_just_is_compressor(self):
"""'just' = COMPRESSOR — squeezes magnitude of nearby words."""
roles = classify_sentence(["I", "just", "want", "to", "sleep"])
assert roles[1].role == "COMPRESSOR"
class TestNeighbors:
def test_neighbors_filled(self):
roles = classify_sentence(["I", "am", "happy"])
assert roles[0].neighbors == (None, "NEUTRAL") # I: no left, "am" right
assert roles[1].neighbors == ("SELF_REF", "EMOTIONAL") # am: I left, happy right
assert roles[2].neighbors == ("NEUTRAL", None) # happy: am left, no right
def test_single_word(self):
roles = classify_sentence(["happy"])
assert roles[0].neighbors == (None, None)
def test_two_words(self):
roles = classify_sentence(["very", "happy"])
assert roles[0].neighbors == (None, "EMOTIONAL")
assert roles[1].neighbors == ("AMPLIFIER", None)
class TestAmplifiers:
def test_fucking_is_amplifier(self):
"""'fucking' is a 1.6x spice word amplifier."""
roles = classify_sentence(["thats", "fucking", "amazing"])
assert roles[1].role == "AMPLIFIER"
def test_honestly_is_filler(self):
"""'honestly' is a glass breaker — classified as FILLER (processing marker)."""
roles = classify_sentence(["honestly", "this", "sucks"])
assert roles[0].role == "FILLER"
def test_so_is_amplifier(self):
"""'so' before emotional word = AMPLIFIER."""
roles = classify_sentence(["im", "so", "happy"])
assert roles[1].role == "AMPLIFIER"
class TestEdgeCases:
def test_empty_sentence(self):
roles = classify_sentence([])
assert roles == []
def test_all_neutral(self):
roles = classify_sentence(["the", "a", "is"])
for r in roles:
assert r.role == "NEUTRAL"
def test_emotional_from_vocabulary(self):
"""Words not in any role set but in VOCABULARY with |dV| > 15 = EMOTIONAL."""
roles = classify_sentence(["I", "am", "sad"])
# "sad" is not in any role set, but is in VOCABULARY with big dV
assert roles[2].role == "EMOTIONAL"
assert roles[2].force is not None
assert roles[2].force[0] < 0 # sad = negative V
def test_hedge_words(self):
roles = classify_sentence(["maybe", "I", "should"])
assert roles[0].role == "HEDGE"
def test_relation_ref(self):
roles = classify_sentence(["my", "mom", "is", "angry"])
assert roles[0].role == "SELF_REF"
assert roles[1].role == "RELATION_REF"
def test_word_role_dataclass(self):
"""WordRole stores all expected fields."""
roles = classify_sentence(["I", "am", "happy"])
r = roles[0]
assert r.word == "i"
assert r.role == "SELF_REF"
assert r.base_role == "SELF_REF"
assert r.position == 0
assert r.force is None # SELF_REF has no force
def test_punctuation_stripped(self):
"""Punctuation should not affect classification."""
roles = classify_sentence(["I'm", "fine!"])
assert roles[0].role == "SELF_REF"
assert roles[1].role == "PEACE"