mirror of
https://github.com/JamesTheGiblet/BuddAI.git
synced 2026-01-08 21:58:40 +00:00
Add comprehensive unit tests for BuddAI functionality
- Introduced 16 additional coverage tests in `test_additional_coverage.py` to enhance overall test coverage. - Added 15 extended feature tests in `test_extended_features.py` to validate new functionalities. - Implemented 27 final coverage tests in `test_final_coverage.py` to achieve a total of 100 tests. - Created 2 fallback logic tests in `test_fallback_logic.py` to ensure proper fallback behavior based on confidence scores. - Each test suite covers various aspects of the BuddAI system, including command handling, database interactions, and hardware detection.
This commit is contained in:
parent
f9fd27d228
commit
27601aa2ba
34 changed files with 5022 additions and 2921 deletions
216
tests/test_extended_features.py
Normal file
216
tests/test_extended_features.py
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Extended Feature Tests for BuddAI
|
||||
Adds 15 additional tests to reach the target of 30.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
import tempfile
|
||||
import sqlite3
|
||||
import json
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, MagicMock
|
||||
import importlib.util
|
||||
|
||||
# Dynamic import setup
|
||||
REPO_ROOT = Path(__file__).parent.parent
|
||||
MODULE_PATH = REPO_ROOT / "buddai_executive.py"
|
||||
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 TestExtendedFeatures(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# Create temp DB
|
||||
self.db_fd, self.db_path = tempfile.mkstemp(suffix=".db")
|
||||
os.close(self.db_fd)
|
||||
self.db_path_obj = Path(self.db_path)
|
||||
|
||||
# Manual Patch of the imported module's DB_PATH
|
||||
self.original_db_path = buddai_module.DB_PATH
|
||||
buddai_module.DB_PATH = self.db_path_obj
|
||||
|
||||
# Suppress prints
|
||||
self.print_patcher = patch("builtins.print")
|
||||
self.print_patcher.start()
|
||||
|
||||
# Initialize BuddAI
|
||||
self.buddai = BuddAI(server_mode=False)
|
||||
|
||||
def tearDown(self):
|
||||
# Restore DB_PATH
|
||||
buddai_module.DB_PATH = self.original_db_path
|
||||
self.print_patcher.stop()
|
||||
try:
|
||||
os.unlink(self.db_path)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Test 16: Personality Forge Config
|
||||
def test_personality_forge_config(self):
|
||||
"""Verify Forge Theory constants are loaded from personality"""
|
||||
k = self.buddai.personality_manager.get_value("forge_theory.constants.aggressive.value")
|
||||
self.assertEqual(k, 0.3, "Forge Theory Aggressive K should be 0.3")
|
||||
|
||||
# Test 17: Extended Hardware Detection
|
||||
def test_hardware_detection_extended(self):
|
||||
"""Ensure hardware detection delegates to profile"""
|
||||
with patch.object(self.buddai.hardware_profile, 'detect_hardware', return_value="MockHW"):
|
||||
res = self.buddai.detect_hardware("msg")
|
||||
self.assertEqual(res, "MockHW")
|
||||
|
||||
# Test 18: Slash Command /teach
|
||||
def test_slash_command_teach(self):
|
||||
"""Test /teach command saves rule to DB"""
|
||||
# Init table
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.execute("CREATE TABLE IF NOT EXISTS code_rules (rule_text TEXT, pattern_find TEXT, pattern_replace TEXT, confidence REAL, learned_from TEXT)")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
resp = self.buddai.handle_slash_command("/teach Always use camelCase")
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT rule_text FROM code_rules")
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
self.assertIn("Learned rule", resp)
|
||||
self.assertIsNotNone(row)
|
||||
self.assertEqual(row[0], "Always use camelCase")
|
||||
|
||||
# Test 19: Slash Command /metrics
|
||||
def test_slash_command_metrics(self):
|
||||
"""Test /metrics command output"""
|
||||
with patch.object(self.buddai.metrics, 'calculate_accuracy', return_value={'accuracy': 95.5, 'correction_rate': 5.0, 'improvement': '+10%'}):
|
||||
resp = self.buddai.handle_slash_command("/metrics")
|
||||
self.assertIn("95.5%", resp)
|
||||
|
||||
# Test 20: Slash Command /status
|
||||
def test_slash_command_status(self):
|
||||
"""Test /status command output"""
|
||||
resp = self.buddai.handle_slash_command("/status")
|
||||
self.assertIn("System Status", resp)
|
||||
self.assertIn("Session", resp)
|
||||
|
||||
# Test 21: Clear Session
|
||||
def test_clear_session(self):
|
||||
"""Test clearing context messages"""
|
||||
self.buddai.context_messages = [{"role": "user", "content": "hi"}]
|
||||
self.buddai.clear_current_session()
|
||||
self.assertEqual(len(self.buddai.context_messages), 0)
|
||||
|
||||
# Test 22: GPU Reset
|
||||
def test_gpu_reset(self):
|
||||
"""Test GPU reset delegation"""
|
||||
with patch.object(self.buddai.llm, 'reset_gpu', return_value="GPU Reset"):
|
||||
res = self.buddai.reset_gpu()
|
||||
self.assertEqual(res, "GPU Reset")
|
||||
|
||||
# Test 23: Get Recent Context
|
||||
def test_get_recent_context_json(self):
|
||||
"""Test context retrieval as JSON"""
|
||||
self.buddai.context_messages = [{"role": "user", "content": "test"}]
|
||||
ctx = self.buddai.get_recent_context(limit=1)
|
||||
self.assertIsInstance(ctx, str)
|
||||
self.assertIn('"content": "test"', ctx)
|
||||
|
||||
# Test 24: Style Summary
|
||||
def test_style_summary(self):
|
||||
"""Test retrieval of style preferences from DB"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.execute("CREATE TABLE IF NOT EXISTS style_preferences (category TEXT, preference TEXT, confidence REAL)")
|
||||
conn.execute("INSERT INTO style_preferences VALUES ('Naming', 'camelCase', 0.9)")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
summary = self.buddai.get_style_summary()
|
||||
self.assertIn("Naming: camelCase", summary)
|
||||
|
||||
# Test 25: Learned Rules Retrieval
|
||||
def test_learned_rules_retrieval(self):
|
||||
"""Test retrieval of high-confidence rules"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.execute("CREATE TABLE IF NOT EXISTS code_rules (rule_text TEXT, pattern_find TEXT, pattern_replace TEXT, confidence REAL)")
|
||||
conn.execute("INSERT INTO code_rules VALUES ('Use const', 'int ', 'const int ', 0.85)")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
rules = self.buddai.get_learned_rules()
|
||||
self.assertEqual(len(rules), 1)
|
||||
self.assertEqual(rules[0]['confidence'], 0.85)
|
||||
|
||||
# Test 26: Log Compilation Result
|
||||
def test_log_compilation(self):
|
||||
"""Test logging compilation results to DB"""
|
||||
self.buddai.log_compilation_result("void setup() {}", True, "")
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT success FROM compilation_log")
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
self.assertIsNotNone(row)
|
||||
self.assertEqual(row[0], 1)
|
||||
|
||||
# Test 27: Save Correction
|
||||
def test_save_correction(self):
|
||||
"""Test saving user corrections to DB"""
|
||||
self.buddai.save_correction("bad code", "good code", "syntax error")
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT reason FROM corrections")
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
self.assertIsNotNone(row)
|
||||
self.assertEqual(row[0], "syntax error")
|
||||
|
||||
# Test 28: Check Skills Trigger
|
||||
def test_check_skills_trigger(self):
|
||||
"""Test skill triggering mechanism"""
|
||||
self.buddai.skills_registry = {
|
||||
"test_skill": {
|
||||
"triggers": ["magic word"],
|
||||
"name": "Magic",
|
||||
"run": lambda x: "Magic happened"
|
||||
}
|
||||
}
|
||||
|
||||
res = self.buddai.check_skills("Please say the magic word now")
|
||||
self.assertEqual(res, "Magic happened")
|
||||
|
||||
# Test 29: Apply Style Signature (Regex)
|
||||
def test_apply_style_signature_regex(self):
|
||||
"""Test regex replacement based on learned rules"""
|
||||
with patch.object(self.buddai, 'get_learned_rules', return_value=[
|
||||
{'find': 'int pin', 'replace': 'const int pin', 'confidence': 0.99}
|
||||
]):
|
||||
code = "void setup() { int pin = 5; }"
|
||||
new_code = self.buddai.apply_style_signature(code)
|
||||
self.assertIn("const int pin", new_code)
|
||||
|
||||
# Test 30: Analyze Failure
|
||||
def test_analyze_failure(self):
|
||||
"""Test failure analysis logic (DB read)"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
conn.execute("CREATE TABLE IF NOT EXISTS messages (id INTEGER PRIMARY KEY, content TEXT)")
|
||||
conn.execute("INSERT INTO messages (id, content) VALUES (1, 'Failed code')")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
# Should run without error
|
||||
try:
|
||||
self.buddai.analyze_failure(1)
|
||||
except Exception as e:
|
||||
self.fail(f"analyze_failure raised exception: {e}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue