kisan-sathi / tests /test_components.py
sxandie's picture
fix: improve mock backend conversation memory and history-aware responses
1207b92
Raw
History Blame Contribute Delete
7.52 kB
import sys
import os
# Append project root to sys.path to enable src imports
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import src.llm as llm
import src.contacts as contacts
import src.ledger as ledger
def test_llm_mock():
print("[TEST] Testing mock LLM backend...")
stream = llm.generate_mock("पीलापन रोग के बारे में बताएं")
response = ""
for chunk in stream:
response += chunk
assert "पीलापन" in response or "Nitrogen" in response
print("[PASS] Mock LLM backend passed!")
def test_emergency_router():
print("[TEST] Testing emergency safety keywords router...")
# Trigger query (Hindi)
is_emergency, warning = contacts.check_emergency_query("मुझे यूरिया कीटनाशक जहर चढ़ गया है")
assert is_emergency is True
assert "सुरक्षा चेतावनी" in warning or "SAFETY WARNING" in warning
# Hinglish suicidal query
is_emergency, warning = contacts.check_emergency_query("mujhe suicidal feel ho raha h")
assert is_emergency is True
assert "1800-599-0019" in warning
# Safe query
is_emergency, warning = contacts.check_emergency_query("गेहूं में पानी कब डालना है")
assert is_emergency is False
assert warning is None
print("[PASS] Emergency safety keyword router passed!")
def test_ledger_parser():
print("[TEST] Testing ledger parser and JSON extraction...")
# We write a mock prompt runner since the user selected starting without models/RAG first
# This mock runner matches the expected mock JSON output inside ledger.py/llm.py
def mock_generate_fn(prompt, system="", stream=False):
return '{"date": "today", "item": "Wheat (गेहूं)", "qty": "40 kg", "price": 1200, "type": "sale"}'
parsed = ledger.parse_transaction("मैंने आज 1200 रुपये में 40 किलो गेहूं बेचा", mock_generate_fn)
assert parsed.get("date") == "today"
assert "Wheat" in parsed.get("item")
assert parsed.get("price") == 1200
assert parsed.get("type") == "sale"
print("[PASS] Ledger transaction parser passed!")
def test_onboarding():
print("[TEST] Testing profile onboarding...")
from app import save_user_profile, load_user_profile, PROFILE_PATH
# Clean old profile
if os.path.exists(PROFILE_PATH):
os.remove(PROFILE_PATH)
res = save_user_profile("Ramesh Dev", "Uttar Pradesh", "Kanpur Dehat")
assert res is True
profile = load_user_profile()
assert profile is not None
assert profile["name"] == "Ramesh Dev"
assert profile["state"] == "Uttar Pradesh"
assert profile["district"] == "Kanpur Dehat"
# Cleanup after test
if os.path.exists(PROFILE_PATH):
os.remove(PROFILE_PATH)
print("[PASS] Onboarding profile save/load passed!")
def test_proactive_nudge():
print("[TEST] Testing proactive nudge seasonal calculations...")
from app import get_proactive_nudge
nudge_hi = get_proactive_nudge("Wheat", "hi")
assert nudge_hi is not None
assert "Wheat" in nudge_hi or "गेहूं" in nudge_hi
assert "💡" in nudge_hi
nudge_en = get_proactive_nudge("Potato", "en")
assert nudge_en is not None
assert "Potato" in nudge_en or "आलू" in nudge_en
assert "💡" in nudge_en
print("[PASS] Proactive nudge calculations passed!")
def test_contacts_categorized():
print("[TEST] Testing categorized contacts listing...")
contacts_list = contacts.load_contacts()
assert len(contacts_list) > 0
categories = {c.get("category") for c in contacts_list}
assert "National (राष्ट्रीय)" in categories
assert "Local (Kanpur Dehat) / स्थानीय संपर्क" in categories
print("[PASS] Categorized contacts database integrity passed!")
def test_generate_mock_ledger():
print("[TEST] Testing generate_mock with ledger extraction query...")
stream = llm.generate_mock(
prompt="aaj maine 1200 rupay me 5 kg cotton khareeda",
system="json format precise data extractor"
)
result = "".join(list(stream))
import json
parsed = json.loads(result)
assert "cotton" in parsed["item"].lower()
assert parsed["price"] == 1200
assert "5 kg" in parsed["qty"]
assert parsed["type"] == "purchase"
assert parsed["date"] != "00 rupay"
print("[PASS] generate_mock ledger extraction verified!")
def test_generate_mock_history_recall():
print("[TEST] Testing generate_mock history recall (last questions query)...")
history = [
{"role": "user", "content": "गेहूं में पीलापन क्यों आता है?"},
{"role": "assistant", "content": "नाइट्रोजन की कमी से पीलापन होता है।"},
{"role": "user", "content": "सिंचाई कब करनी चाहिए?"},
{"role": "assistant", "content": "बुवाई के 21-25 दिन बाद CRI सिंचाई करें।"},
]
# English variant
stream = llm.generate_mock("what were my last questions?", history=history)
result = "".join(list(stream))
assert "पीलापन" in result or "सिंचाई" in result, f"Expected history questions in result, got: {result[:200]}"
# Hindi variant
stream = llm.generate_mock("मेरे पिछले सवाल क्या थे?", history=history)
result = "".join(list(stream))
assert "पीलापन" in result or "सिंचाई" in result, f"Expected history questions in result, got: {result[:200]}"
print("[PASS] History recall test passed!")
def test_generate_mock_context_aware_fallback():
print("[TEST] Testing generate_mock context-aware fallback (unrecognized topic with history)...")
history = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "नमस्ते! मैं किसान साथी हूँ।"},
]
# An unrecognized query with history should NOT return the welcome message
stream = llm.generate_mock("sugarcane ki kheti kaise karein?", history=history)
result = "".join(list(stream))
# Should NOT be the generic welcome message
assert "नमस्ते! मैं आपका किसान साथी हूँ।" not in result, (
f"Should not return generic welcome message when history is present, got: {result[:200]}"
)
# Should reference the previous conversation
assert "Hello" in result or "विवरण" in result or "समझ" in result, (
f"Expected context-aware response, got: {result[:200]}"
)
print("[PASS] Context-aware fallback test passed!")
if __name__ == "__main__":
print("--- Running Kisan-Sathi Core Verification ---")
try:
test_llm_mock()
test_emergency_router()
test_ledger_parser()
test_generate_mock_ledger()
test_generate_mock_history_recall()
test_generate_mock_context_aware_fallback()
test_onboarding()
test_proactive_nudge()
test_contacts_categorized()
print("[SUCCESS] ALL TESTS PASSED SUCCESSFULLY!")
except AssertionError as e:
print(f"[FAIL] TEST FAILED: {e}")
sys.exit(1)