CodeBase-Agent / test_runner.py
armaanalam's picture
Upload 10 files
e9b3659 verified
Raw History Blame Contribute Delete
5.98 kB
"""
Manual test runner for the Codebase Assistant.
Run with: .venv\Scripts\python.exe test_runner.py [test_name]
Available tests:
mcp - Test GitHub MCP connection & list tools
embed - Test embedding a small text snippet
ingest - Index this repo into the local vector store
query - Run a RAG query against the vector store
bugs - Detect bugs in a given file
complexity - Analyse cyclomatic complexity of a file
all - Run embed -> ingest -> query -> bugs -> complexity (no MCP)
"""
import asyncio
import sys
import os
# ── helpers ──────────────────────────────────────────────────────────────────
def header(title: str):
print(f"\n{'='*60}")
print(f" {title}")
print(f"{'='*60}")
def ok(msg: str): print(f" OK {msg}")
def fail(msg: str): print(f" FAIL {msg}")
ROOT = os.path.dirname(__file__)
# ── individual tests ──────────────────────────────────────────────────────────
async def test_mcp():
"""Connect to GitHub MCP and list available tools."""
header("Test: GitHub MCP Connection")
from mcp_client import get_github_mcp_client
client = get_github_mcp_client()
try:
await client.connect()
tools = await client.list_tools()
ok(f"Connected. {len(tools)} tools found:")
for t in tools[:5]:
print(f" - {t['name']}: {t['description'][:60]}")
if len(tools) > 5:
print(f" ... and {len(tools)-5} more")
except Exception as e:
fail(f"MCP connection failed: {e}")
finally:
await client.disconnect()
def test_embed():
"""Embed a small text snippet and verify the vector shape."""
header("Test: Embedding")
from rag.embedding import embed_query, embed_document
try:
vec = embed_query("def hello(): pass")
assert isinstance(vec, list) and len(vec) > 0, "embed_query returned empty"
ok(f"embed_query -> vector of {len(vec)} dims")
fake_chunks = [{"content": "def add(a, b): return a+b"}]
chunks = embed_document(fake_chunks)
assert "embedding" in chunks[0], "embed_document did not add 'embedding' key"
ok(f"embed_document -> chunk embedding of {len(chunks[0]['embedding'])} dims")
except Exception as e:
fail(f"Embedding failed: {e}")
def test_ingest():
"""Load and index this repository into the local ChromaDB."""
header("Test: Repository Ingest")
from rag.repository_loader import load_repository
from rag.splitter import split_code
from rag.embedding import embed_document
from rag.retriever import build_vector_store
try:
docs = load_repository(ROOT)
ok(f"Loaded {len(docs)} files from repo")
all_chunks = []
for doc in docs:
all_chunks.extend(split_code(doc))
ok(f"Split into {len(all_chunks)} chunks")
embedded = embed_document(all_chunks)
ok(f"Embedded {len(embedded)} chunks")
build_vector_store(embedded)
ok("Vector store built / updated (ChromaDB)")
except Exception as e:
fail(f"Ingest failed: {e}")
def test_query():
"""Run a RAG query. Requires the vector store to be populated first."""
header("Test: RAG Query")
from rag.rag_chain import run_rag_query
try:
result = run_rag_query("How does the embedding module work?", k=3)
ok(f"Answer received ({len(result['answer'])} chars)")
ok(f"Sources returned: {len(result['sources'])}")
for s in result["sources"]:
print(f" - {s.get('file_path','?')} lines {s.get('start_line')}-{s.get('end_line')}")
print(f"\n Answer preview:\n {result['answer'][:300]}...")
except Exception as e:
fail(f"RAG query failed: {e}")
def test_bugs():
"""Run bug detection on llm.py."""
header("Test: Bug Detection")
from services.code_analysis import detect_bugs
target = os.path.join(ROOT, "llm.py")
try:
bugs = detect_bugs(target)
ok(f"Bug detection returned {len(bugs)} item(s) for llm.py")
for b in bugs[:3]:
print(f" Line {b.get('line','?')}: [{b.get('severity','?')}] {b.get('issue','?')}")
except Exception as e:
fail(f"Bug detection failed: {e}")
def test_complexity():
"""Analyse cyclomatic complexity of llm.py."""
header("Test: Complexity Analysis")
from services.code_analysis import analyze_complexity
target = os.path.join(ROOT, "llm.py")
try:
result = analyze_complexity(target)
ok(f"Complexity analysis returned {len(result['functions'])} function(s):")
for fn in result["functions"]:
print(f" {fn['name']}: complexity={fn['complexity']}, rank={fn['rank']}")
except Exception as e:
fail(f"Complexity analysis failed: {e}")
# ── entry point ───────────────────────────────────────────────────────────────
TESTS = {
"mcp": lambda: asyncio.run(test_mcp()),
"embed": test_embed,
"ingest": test_ingest,
"query": test_query,
"bugs": test_bugs,
"complexity": test_complexity,
}
def run_all_non_mcp():
"""Run embed -> ingest -> query -> bugs -> complexity in sequence."""
test_embed()
test_ingest()
test_query()
test_bugs()
test_complexity()
if __name__ == "__main__":
arg = sys.argv[1] if len(sys.argv) > 1 else "all"
if arg == "all":
run_all_non_mcp()
elif arg in TESTS:
TESTS[arg]()
else:
print(f"Unknown test '{arg}'. Choose from: {', '.join(TESTS)} or 'all'")
sys.exit(1)