mirror of
https://github.com/JamesTheGiblet/BuddAI.git
synced 2026-01-08 21:58:40 +00:00
- Added `ModelFineTuner` class for preparing training data and fine-tuning models based on user corrections. - Introduced `CodeValidator` class to validate generated code against various hardware and style rules, including safety checks and function naming conventions. - Developed skills for calculator operations, system information retrieval, weather fetching, and timer functionality. - Implemented a self-diagnostic skill to run unit tests and report results. - Created a dynamic skill loading mechanism to discover and register skills from the current directory. - Added unit tests for skills to ensure functionality and reliability.
115 lines
No EOL
4.9 KiB
Python
115 lines
No EOL
4.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Unit tests for BuddAI v3.2
|
|
Verifies type hints and core functionality including the new routing logic.
|
|
"""
|
|
|
|
import unittest
|
|
import sys
|
|
import importlib.util
|
|
from pathlib import Path
|
|
from typing import List, Dict, Optional
|
|
from unittest.mock import MagicMock, patch
|
|
from core.buddai_prompt_engine import PromptEngine
|
|
|
|
# Load buddai_v3.2.py dynamically due to version number in filename
|
|
REPO_ROOT = Path(__file__).parent.parent
|
|
MODULE_PATH = REPO_ROOT / "buddai_executive.py"
|
|
|
|
if not MODULE_PATH.exists():
|
|
print(f"Error: Could not find {MODULE_PATH}")
|
|
sys.exit(1)
|
|
|
|
spec = importlib.util.spec_from_file_location("buddai_executive", MODULE_PATH)
|
|
buddai_module = importlib.util.module_from_spec(spec)
|
|
sys.modules["buddai_executive"] = buddai_module
|
|
spec.loader.exec_module(buddai_module)
|
|
|
|
BuddAI = buddai_module.BuddAI
|
|
|
|
class TestBuddAITypesAndLogic(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
# Suppress print statements during tests
|
|
self.original_stdout = sys.stdout
|
|
sys.stdout = MagicMock()
|
|
|
|
# Initialize BuddAI in non-server mode, mocking DB interactions
|
|
with patch('sqlite3.connect') as mock_sql:
|
|
# Mock mkdir to prevent creating directories during tests
|
|
with patch('pathlib.Path.mkdir'):
|
|
self.buddai = BuddAI(server_mode=False)
|
|
self.mock_conn = mock_sql.return_value
|
|
self.mock_cursor = self.mock_conn.cursor.return_value
|
|
|
|
def tearDown(self):
|
|
sys.stdout = self.original_stdout
|
|
|
|
def test_method_annotations(self):
|
|
"""Verify type hints exist on key methods"""
|
|
# chat
|
|
chat_hints = BuddAI.chat.__annotations__
|
|
self.assertEqual(chat_hints['user_message'], str)
|
|
self.assertEqual(chat_hints['return'], str)
|
|
|
|
# is_complex
|
|
self.assertEqual(PromptEngine.is_complex.__annotations__['return'], bool)
|
|
|
|
# extract_modules
|
|
self.assertEqual(PromptEngine.extract_modules.__annotations__['return'], List[str])
|
|
|
|
# build_modular_plan
|
|
self.assertEqual(PromptEngine.build_modular_plan.__annotations__['return'], List[Dict[str, str]])
|
|
|
|
def test_routing_simple_question(self):
|
|
"""Test that simple questions route to the FAST model"""
|
|
with patch.object(self.buddai, 'call_model', return_value="Fast response") as mock_call:
|
|
response = self.buddai._route_request("What is a servo?", force_model=None, forge_mode="2")
|
|
|
|
mock_call.assert_called_with("fast", "What is a servo?", system_task=True)
|
|
self.assertEqual(response, "Fast response")
|
|
|
|
def test_routing_complex_request(self):
|
|
"""Test that complex requests route to modular build"""
|
|
complex_msg = "Build a complete robot with servo and motor"
|
|
|
|
with patch.object(self.buddai, 'execute_modular_build', return_value="Modular code") as mock_build:
|
|
# Mock is_complex to ensure it returns True for this test case
|
|
with patch.object(self.buddai.prompt_engine, 'is_complex', return_value=True):
|
|
response = self.buddai._route_request(complex_msg, force_model=None, forge_mode="2")
|
|
|
|
mock_build.assert_called()
|
|
self.assertEqual(response, "Modular code")
|
|
|
|
def test_routing_search_query(self):
|
|
"""Test that search queries route to repository search"""
|
|
search_msg = "Show me functions using applyForge"
|
|
|
|
with patch.object(self.buddai.repo_manager, 'search_repositories', return_value="Search results") as mock_search:
|
|
# Mock is_search_query to ensure True
|
|
with patch.object(self.buddai.repo_manager, 'is_search_query', return_value=True):
|
|
# Ensure is_complex is False so it doesn't preempt search
|
|
with patch.object(self.buddai.prompt_engine, 'is_complex', return_value=False):
|
|
response = self.buddai._route_request(search_msg, force_model=None, forge_mode="2")
|
|
|
|
mock_search.assert_called_with(search_msg)
|
|
self.assertEqual(response, "Search results")
|
|
|
|
def test_routing_forced_model(self):
|
|
"""Test that force_model overrides other logic"""
|
|
with patch.object(self.buddai, 'call_model', return_value="Forced response") as mock_call:
|
|
response = self.buddai._route_request("Complex build request", force_model="balanced", forge_mode="2")
|
|
|
|
mock_call.assert_called_with("balanced", "Complex build request")
|
|
self.assertEqual(response, "Forced response")
|
|
|
|
def test_extract_modules(self):
|
|
"""Verify module extraction logic"""
|
|
msg = "I need a robot with bluetooth and a flipper weapon"
|
|
modules = self.buddai.prompt_engine.extract_modules(msg)
|
|
self.assertIn("ble", modules)
|
|
self.assertIn("servo", modules)
|
|
self.assertNotIn("motor", modules)
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main() |