multilingual-absa / tests /unit /test_pipeline.py
Aryan Mishra
Deploy Gradio app to HF Spaces
2617189
Raw
History Blame Contribute Delete
4.15 kB
"""Unit tests for the rule-based ABSA pipeline aspect extraction + fallbacks."""
from __future__ import annotations
import os
os.environ.setdefault("DATABASE_URL", "sqlite:///./tests/fixtures/test.db")
from absa.pipeline.absa_pipeline import pipeline
def _aspects(text: str) -> list[dict]:
result = pipeline.predict(text, "en")
return [a.model_dump() if hasattr(a, "model_dump") else dict(a) for a in result.aspects]
def _sentiment_of(aspects: list[dict], aspect: str) -> str | None:
for a in aspects:
if a["aspect"].lower() == aspect.lower():
return a["sentiment"]
return None
def test_food_and_service_extracted_from_sentiment_words():
aspects = _aspects("The food was great but the service was terrible.")
labels = [a["aspect"].lower() for a in aspects]
assert "food" in labels
assert "service" in labels
assert _sentiment_of(aspects, "food") == "positive"
assert _sentiment_of(aspects, "service") == "negative"
def test_noun_after_sentiment_word_extracted():
aspects = _aspects("Great camera quality and a lovely experience overall.")
labels = [a["aspect"].lower() for a in aspects]
# "camera quality" is in the lexicon; "experience" must come from the fallback.
assert any("camera" in label or "experience" in label for label in labels)
def test_product_target_fallback():
aspects = _aspects("I absolutely love this product.")
assert _sentiment_of(aspects, "product") == "positive"
def test_generic_overall_fallback_when_no_aspect_noun():
aspects = _aspects("Absolutely terrible, do not recommend.")
assert aspects, "should always return at least one aspect"
assert _sentiment_of(aspects, "overall") == "negative"
def test_positive_bare_comment_returns_result():
aspects = _aspects("Amazing!")
assert aspects, "should always return at least one aspect"
assert _sentiment_of(aspects, "overall") == "positive"
def test_neutral_text_returns_overall_neutral():
aspects = _aspects("Hello there, just checking.")
assert aspects
assert _sentiment_of(aspects, "overall") == "neutral"
def test_devanagari_comment_gets_aspect_and_sentiment():
aspects = _aspects("खाना बहुत अच्छा था।")
assert aspects, "Devanagari comment should still produce a result"
assert any(a["aspect"].lower() in ("खाना", "overall") for a in aspects)
assert _sentiment_of(aspects, "खाना") == "positive"
def test_empty_text_never_crashes():
aspects = _aspects("")
assert aspects # generic fallback keeps the response non-empty
def test_lexicon_still_used_first():
aspects = _aspects("The battery life is amazing but the screen is too dim.")
labels = [a["aspect"].lower() for a in aspects]
assert "battery life" in labels or "battery" in labels
assert _sentiment_of(aspects, "battery life") == "positive"
assert _sentiment_of(aspects, "screen") == "negative"
def test_purchase_target_with_strong_negation():
aspects = _aspects("Worst purchase ever, do not buy.")
assert _sentiment_of(aspects, "purchase") == "negative"
def test_devanagari_mixed_clauses_split_on_lekin():
aspects = _aspects("खाना बढ़िया था लेकिन सेवा खराब थी।")
assert _sentiment_of(aspects, "खाना") == "positive"
assert _sentiment_of(aspects, "सेवा") == "negative"
def test_hinglish_mixed_clauses_split_on_lekin():
aspects = _aspects("The phone ka design badhiya hai lekin battery life kharab hai.")
assert _sentiment_of(aspects, "design") == "positive"
assert _sentiment_of(aspects, "battery life") == "negative"
def test_devanagari_word_never_split_inside():
# Regression: "बढ़िया" used to be split by the "या" clause separator.
aspects = _aspects("खाना बहुत बढ़िया था।")
assert _sentiment_of(aspects, "खाना") == "positive"
def test_experience_positive():
aspects = _aspects("Great experience overall, will order again.")
assert _sentiment_of(aspects, "experience") == "positive"