AISE1_Project_Irina_Livio/tests/test_chat_manager.py
Livio Meuli 6f9be8a6c4 Implement ChatManager with API integration, SystemPrompter, and comprehensive test suite
- Add ChatManager class for OpenAI-compatible API communication (silicon.fhgr.ch:7080)
- Add SystemPrompter for intelligent prompt generation with file context
- Integrate ChatManager into frontend chat component
- Add comprehensive pytest tests (40+ tests covering unit and integration scenarios)
- Implement error handling for API failures, timeouts, and connection issues
- Add environment variable-based configuration for API credentials
- Update frontend state initialization to include ChatManager
- All tests passing with mock/patch isolation for API calls
2026-04-09 14:19:57 +02:00

243 lines
8.8 KiB
Python

"""Test script for ChatManager - Pytest compatible tests"""
import sys
from pathlib import Path
import pytest
from unittest.mock import patch, MagicMock
# Add project root to Python path
sys.path.insert(0, str(Path(__file__).parent.parent))
from backend.managers.chat_manager import ChatManager
class TestChatManager:
"""Test suite for ChatManager functionality."""
@pytest.fixture
def chat_manager(self):
return ChatManager()
def test_initialization(self, chat_manager):
"""Test that ChatManager initializes correctly."""
assert chat_manager.api_url is not None
assert chat_manager.model is not None
assert chat_manager.chat_history == []
def test_add_message(self, chat_manager):
"""Test adding messages to chat history."""
chat_manager.add_message("user", "Hello")
assert len(chat_manager.chat_history) == 1
assert chat_manager.chat_history[0]["role"] == "user"
assert chat_manager.chat_history[0]["content"] == "Hello"
def test_get_history(self, chat_manager):
"""Test retrieving chat history."""
chat_manager.add_message("user", "Hello")
chat_manager.add_message("assistant", "Hi there!")
history = chat_manager.get_history()
assert len(history) == 2
assert history[0]["role"] == "user"
assert history[1]["role"] == "assistant"
def test_clear_history(self, chat_manager):
"""Test clearing chat history."""
chat_manager.add_message("user", "Hello")
assert len(chat_manager.chat_history) == 1
chat_manager.clear_history()
assert len(chat_manager.chat_history) == 0
def test_send_message_integration(self, chat_manager):
"""
Integration test for sending message to AI.
This test actually communicates with the API.
"""
try:
# Send a simple test message
response = chat_manager.send_message("Hello, what is 2+2?")
# Verify response is not empty
assert isinstance(response, str)
assert len(response) > 0
# Verify message was added to history
assert len(chat_manager.chat_history) == 2 # user + assistant
assert chat_manager.chat_history[0]["role"] == "user"
assert chat_manager.chat_history[1]["role"] == "assistant"
print(f"API Test Passed")
print(f"Response: {response}")
except Exception as e:
# If API is not reachable, mark as skipped
pytest.skip(f"API not reachable: {str(e)}")
def test_multiple_messages(self, chat_manager):
"""Test sending multiple messages in a conversation."""
try:
# Send first message
response1 = chat_manager.send_message("What is your name?")
assert len(response1) > 0
# Send follow-up message
response2 = chat_manager.send_message("Tell me more")
assert len(response2) > 0
# Verify full conversation is in history
assert len(chat_manager.chat_history) == 4 # 2 user + 2 assistant
print(f"Conversation Test Passed")
print(f"Messages: {len(chat_manager.chat_history)}")
except Exception as e:
pytest.skip(f"API not reachable: {str(e)}")
class TestChatManagerSendMessage:
"""Unit tests for send_message using mocked HTTP requests."""
@pytest.fixture
def chat_manager(self):
return ChatManager()
def _mock_response(self, content="AI reply", status_code=200):
mock = MagicMock()
mock.status_code = status_code
mock.json.return_value = {
"choices": [{"message": {"role": "assistant", "content": content}}]
}
mock.text = "error text"
return mock
def test_send_message_adds_user_message_to_history(self, chat_manager):
with patch("requests.post", return_value=self._mock_response()):
chat_manager.send_message("Hello")
assert chat_manager.chat_history[0] == {"role": "user", "content": "Hello"}
def test_send_message_adds_assistant_response_to_history(self, chat_manager):
with patch("requests.post", return_value=self._mock_response("Hi there")):
chat_manager.send_message("Hello")
assert chat_manager.chat_history[1] == {"role": "assistant", "content": "Hi there"}
def test_send_message_returns_ai_content(self, chat_manager):
with patch("requests.post", return_value=self._mock_response("Answer")):
response = chat_manager.send_message("Question")
assert response == "Answer"
def test_send_message_history_grows_with_each_call(self, chat_manager):
with patch("requests.post", return_value=self._mock_response()):
chat_manager.send_message("First")
chat_manager.send_message("Second")
assert len(chat_manager.chat_history) == 4 # 2 user + 2 assistant
def test_send_message_connection_error_raises(self, chat_manager):
import requests
with patch("requests.post", side_effect=requests.exceptions.ConnectionError("refused")):
with pytest.raises(Exception, match="Connection Error"):
chat_manager.send_message("Hello")
def test_send_message_api_error_status_raises(self, chat_manager):
mock = self._mock_response(status_code=500)
with patch("requests.post", return_value=mock):
with pytest.raises(Exception, match="API Error 500"):
chat_manager.send_message("Hello")
def test_send_message_empty_choices_raises(self, chat_manager):
mock = MagicMock()
mock.status_code = 200
mock.json.return_value = {"choices": []}
with patch("requests.post", return_value=mock):
with pytest.raises(Exception, match="Invalid API response format"):
chat_manager.send_message("Hello")
def test_send_message_missing_choices_key_raises(self, chat_manager):
mock = MagicMock()
mock.status_code = 200
mock.json.return_value = {}
with patch("requests.post", return_value=mock):
with pytest.raises(Exception):
chat_manager.send_message("Hello")
def test_send_message_timeout_raises(self, chat_manager):
import requests
with patch("requests.post", side_effect=requests.exceptions.Timeout()):
with pytest.raises(Exception):
chat_manager.send_message("Hello")
class TestChatManagerGetChatDisplay:
"""Tests for get_chat_display()."""
@pytest.fixture
def chat_manager(self):
return ChatManager()
def test_empty_history_returns_empty_list(self, chat_manager):
assert chat_manager.get_chat_display() == []
def test_display_contains_role_and_content_keys(self, chat_manager):
chat_manager.add_message("user", "Hello")
display = chat_manager.get_chat_display()
assert "role" in display[0]
assert "content" in display[0]
def test_display_preserves_message_order(self, chat_manager):
chat_manager.add_message("user", "First")
chat_manager.add_message("assistant", "Second")
display = chat_manager.get_chat_display()
assert display[0]["role"] == "user"
assert display[1]["role"] == "assistant"
def test_display_matches_history(self, chat_manager):
chat_manager.add_message("user", "Hi")
chat_manager.add_message("assistant", "Hello!")
assert chat_manager.get_chat_display() == chat_manager.get_history()
def test_system_message_included_in_display(self, chat_manager):
chat_manager.add_message("system", "You are a helper.")
display = chat_manager.get_chat_display()
assert display[0]["role"] == "system"
def test_chat_manager_demo():
"""Demo test - Shows interactive chat (can be run manually)."""
print("\n" + "=" * 60)
print("ChatManager Demo - Interactive Test")
print("=" * 60 + "\n")
chat_manager = ChatManager()
print(f"Connected to API: {chat_manager.api_url}")
print(f"Model: {chat_manager.model}\n")
# Demo conversation
test_messages = ["Hello! What can you do?", "Tell me a joke", "What is Python?"]
print("Starting conversation...\n")
for message in test_messages:
print(f"User: {message}")
try:
response = chat_manager.send_message(message)
print(f"Assistant: {response}\n")
except Exception as e:
print(f"Error: {str(e)}\n")
pytest.skip(f"API not reachable: {str(e)}")
# Display full chat history
print("=" * 60)
print("Chat History:")
print("=" * 60)
for msg in chat_manager.get_history():
print(f"{msg['role'].upper()}: {msg['content']}\n")
if __name__ == "__main__":
# Run with: pytest tests/test_chat_manager.py -v -s
pytest.main([__file__, "-v", "-s"])