Files
EzVibe/ui/test_pet_window.py
e2hang 2a844e83a8 Initial commit: EzVibe AI 桌宠系统
- EmotionEngine: 5状态马尔可夫情绪机 + 蒙特卡洛转移
- VectorMemory: TF-IDF向量记忆 + SQLite持久化 + RAG检索
- AgentBrain: Ollama/OpenAI/Dummy三后端LLM
- BehaviorScheduler: 优先级/冷却/活跃度调度
- FastAPI服务器 + WebSocket实时推送
- perception: 键鼠监控 + 屏幕截图
- ui/pet_window: PySide6桌宠窗口 + 像素动画
- assets/pet: 5情绪各2帧像素艺术资源
2026-05-01 23:26:43 +08:00

169 lines
5.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
test_pet_window.py
==================
ui/pet_window 模块单元测试(使用 DummyPetWindowheadless 无 Qt 依赖)。
运行
----
cd /Users/e2hang/hermes/code/ezvibe
python -m ui.test_pet_window
"""
import sys
from pathlib import Path
_ROOT = Path(__file__).parent.parent.resolve()
sys.path.insert(0, str(_ROOT))
import unittest
# ============================================================================
# DummyPetWindow Tests
# ============================================================================
class TestDummyPetWindow(unittest.TestCase):
"""DummyPetWindow API 契约测试。"""
def test_init_does_not_crash(self):
"""初始化不崩溃。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
self.assertIsInstance(w, DummyPetWindow)
def test_show_hide(self):
"""show/hide 控制可见性。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
w.show()
self.assertTrue(w.is_visible())
w.hide()
self.assertFalse(w.is_visible())
def test_close(self):
"""close 停止窗口。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
w.close()
self.assertFalse(w.is_visible())
def test_update_emotion_valid(self):
"""update_emotion 接受有效情绪。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
w.update_emotion("happy")
self.assertEqual(w.get_current_emotion(), "happy")
w.update_emotion("sleepy")
self.assertEqual(w.get_current_emotion(), "sleepy")
def test_update_emotion_invalid_defaults_to_idle(self):
"""update_emotion 忽略无效情绪,保持 idle。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
w.update_emotion("unknown_emotion")
self.assertEqual(w.get_current_emotion(), "idle")
def test_show_reminder_stores_message(self):
"""show_reminder 存储提醒消息。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
w.show_reminder("该喝水了!", priority=0)
w.show_reminder("站起来伸展一下!", priority=1)
self.assertEqual(len(w._reminders), 2)
self.assertIn("该喝水了!", w._reminders)
def test_position_get_set(self):
"""位置 get/set。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
w.set_position(200, 300)
x, y = w.get_position()
self.assertEqual((x, y), (200, 300))
def test_play_animation_no_exception(self):
"""play_animation 不抛异常。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
w.play_animation("bounce")
w.play_animation("wave")
w.play_animation("spin")
# 无断言——只要不崩溃即可
def test_repr(self):
"""repr 包含状态信息。"""
from ui.pet_window import DummyPetWindow
w = DummyPetWindow()
r = repr(w)
self.assertIn("DummyPetWindow", r)
self.assertIn("idle", r)
# ============================================================================
# create_pet_window Factory Tests
# ============================================================================
class TestCreatePetWindow(unittest.TestCase):
"""create_pet_window 工厂函数测试。"""
def test_force_dummy_returns_dummy(self):
"""force_dummy=True 强制返回 DummyPetWindow。"""
from ui.pet_window import create_pet_window, DummyPetWindow
w = create_pet_window(force_dummy=True)
self.assertIsInstance(w, DummyPetWindow)
def test_default_returns_pet_window_or_dummy(self):
"""默认情况下返回 PetWindow 或 DummyPetWindow。"""
from ui.pet_window import create_pet_window, DummyPetWindow
w = create_pet_window()
# force_dummy 模式必定返回 DummyPetWindow
w2 = create_pet_window(force_dummy=True)
self.assertIsInstance(w2, DummyPetWindow)
def test_emotion_engine_wired(self):
"""emotion_engine 被正确传入。"""
from ui.pet_window import create_pet_window
mock_engine = object()
w = create_pet_window(emotion_engine=mock_engine)
self.assertIs(w._emotion, mock_engine)
def test_brain_wired(self):
"""brain 被正确传入。"""
from ui.pet_window import create_pet_window
mock_brain = object()
w = create_pet_window(brain=mock_brain)
self.assertIs(w._brain, mock_brain)
def test_scheduler_wired(self):
"""scheduler 被正确传入。"""
from ui.pet_window import create_pet_window
mock_scheduler = object()
w = create_pet_window(scheduler=mock_scheduler)
self.assertIs(w._scheduler, mock_scheduler)
# ============================================================================
# Emotion Emojis Mapping Tests
# ============================================================================
class TestEmotionEmojis(unittest.TestCase):
"""PetWindow.EMOTION_EMOJIS 完整性测试(通过 DummyPetWindow 访问)。"""
def test_all_emotions_have_emoji(self):
"""所有标准情绪都有 emoji 映射。"""
from ui.pet_window import DummyPetWindow
emotions = DummyPetWindow.EMOTIONS
emojis = DummyPetWindow.EMOTION_EMOJIS
for e in emotions:
self.assertIn(e, emojis, f"{e} 缺少 emoji 映射")
self.assertIsInstance(emojis[e], str)
self.assertGreater(len(emojis[e]), 0)
# ============================================================================
# Main
# ============================================================================
if __name__ == "__main__":
print("Running pet_window tests (headless, no Qt required) ...")
unittest.main(verbosity=2)