All checks were successful
Smoke Test / smoke (pull_request) Successful in 8s
Implements #116 — hardware validation testing for edge crisis detector on Raspberry Pi 4 and other edge devices. Adds edge detector (keyword + optional Ollama model), crisis_resources.json, deployment docs, and two test files: - test_edge_detector.py: unit tests for keyword logic - test_edge_detector_hardware.py: hardware validation suite Hardware validation measures keyword detection (<1ms), model inference (<5s on Pi 4), offline operation, and provides reproducible benchmark via `python3 edge/detector.py --benchmark`. Re-implements the functionality from closed PR #111 with expanded tests.
90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests for edge crisis detector (logic-only unit tests)."""
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# The detector module lives in ../edge relative to tests/
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / "edge"))
|
|
|
|
from detector import keyword_check, detect, load_resources
|
|
|
|
|
|
def test_keyword_positive():
|
|
cases = [
|
|
"I want to kill myself",
|
|
"I want to die",
|
|
"thinking about suicide",
|
|
"I want to end it all",
|
|
"no reason to live anymore",
|
|
"better off dead",
|
|
"hurt myself badly",
|
|
]
|
|
for text in cases:
|
|
result = keyword_check(text)
|
|
assert result["crisis"], f"Failed to detect crisis in: {text}"
|
|
print(f" {len(cases)} keyword positive cases: PASS")
|
|
|
|
|
|
def test_keyword_negative():
|
|
cases = [
|
|
"I had a great day today",
|
|
"The weather is nice",
|
|
"Working on my project",
|
|
"Feeling a bit tired",
|
|
]
|
|
for text in cases:
|
|
result = keyword_check(text)
|
|
assert not result["crisis"], f"False positive for: {text}"
|
|
print(f" {len(cases)} keyword negative cases: PASS")
|
|
|
|
|
|
def test_detect_offline():
|
|
result = detect("I want to kill myself", use_model=False)
|
|
assert result["crisis"]
|
|
assert result["method"] == "keyword"
|
|
assert result["confidence"] > 0
|
|
print(" offline detection: PASS")
|
|
|
|
|
|
def test_detect_safe():
|
|
result = detect("The weather is beautiful today", use_model=False)
|
|
assert not result["crisis"]
|
|
print(" safe detection: PASS")
|
|
|
|
|
|
def test_resources_load():
|
|
rpath = Path(__file__).parent.parent / "edge" / "crisis_resources.json"
|
|
if not rpath.exists():
|
|
rpath = Path(__file__).parent.parent / "crisis_resources.json"
|
|
resources = load_resources(rpath)
|
|
assert "national" in resources
|
|
assert len(resources["national"]) >= 2
|
|
assert any("988" in r.get("phone", "") or r.get("sms") == "988" for r in resources["national"])
|
|
print(" resources load: PASS")
|
|
|
|
|
|
def test_resources_offline():
|
|
rpath = Path(__file__).parent.parent / "edge" / "crisis_resources.json"
|
|
if not rpath.exists():
|
|
rpath = Path(__file__).parent.parent / "crisis_resources.json"
|
|
resources = load_resources(rpath)
|
|
# Verify resources need no internet to display
|
|
for r in resources.get("national", []):
|
|
assert "name" in r
|
|
assert "description" in r
|
|
has_contact = "phone" in r or "sms" in r or "url" in r
|
|
assert has_contact, f"Resource {r['name']} has no contact method"
|
|
print(" resources offline: PASS")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("Running edge detector tests...")
|
|
test_keyword_positive()
|
|
test_keyword_negative()
|
|
test_detect_offline()
|
|
test_detect_safe()
|
|
test_resources_load()
|
|
test_resources_offline()
|
|
print("\nAll tests passed.")
|