ProjectMemory / backend /tests /test_devb.py
Amal Nimmy Lal
feat : Project Memory
35765b5
"""
Dev B Test Suite - Run with: .venv/Scripts/python test_devb.py
"""
import asyncio
import sys
sys.path.insert(0, '.')
from app.llm import generate_documentation, synthesize_answer, get_embedding
from app.vectorstore import init_vectorstore, add_embedding, search, count_embeddings, delete_by_project
# Test counters
passed = 0
failed = 0
def test(name, condition, details=""):
global passed, failed
if condition:
print(f" [PASS] {name}")
passed += 1
else:
print(f" [FAIL] {name} - {details}")
failed += 1
async def test_llm():
print("\n[1/4] Testing LLM Client (llm.py)")
print("-" * 40)
# Test 1: get_embedding
try:
emb = await get_embedding("test embedding")
test("get_embedding returns list", isinstance(emb, list))
test("get_embedding returns 768 dims", len(emb) == 768, f"got {len(emb)}")
test("get_embedding returns floats", isinstance(emb[0], float))
except Exception as e:
test("get_embedding", False, str(e))
# Test 2: generate_documentation
try:
doc = await generate_documentation(
task_title="Setup API",
what_i_did="Created REST endpoints",
code_snippet="@app.get('/api')"
)
test("generate_documentation returns dict", isinstance(doc, dict))
test("generate_documentation has summary", "summary" in doc)
test("generate_documentation has details", "details" in doc)
test("generate_documentation has tags", "tags" in doc and isinstance(doc["tags"], list))
except Exception as e:
test("generate_documentation", False, str(e))
# Test 3: synthesize_answer
try:
answer = await synthesize_answer(
context="Task completed: Built login system with JWT authentication",
query="What authentication was implemented?"
)
test("synthesize_answer returns string", isinstance(answer, str))
test("synthesize_answer not empty", len(answer) > 0)
except Exception as e:
test("synthesize_answer", False, str(e))
async def test_vectorstore():
print("\n[2/4] Testing Vector Store (vectorstore.py)")
print("-" * 40)
# Test 1: init_vectorstore
try:
init_vectorstore()
test("init_vectorstore succeeds", True)
except Exception as e:
test("init_vectorstore", False, str(e))
return # Can't continue without init
# Clean up test data first
try:
delete_by_project("test-project-xyz")
except:
pass
# Test 2: add_embedding
try:
emb = await get_embedding("Test document about Python programming")
add_embedding(
log_entry_id="test-entry-1",
text="Test document about Python programming",
embedding=emb,
metadata={
"project_id": "test-project-xyz",
"user_id": "test-user",
"task_id": "test-task",
"created_at": "2024-01-01T00:00:00"
}
)
test("add_embedding succeeds", True)
except Exception as e:
test("add_embedding", False, str(e))
# Test 3: count_embeddings
try:
count = count_embeddings("test-project-xyz")
test("count_embeddings returns int", isinstance(count, int))
test("count_embeddings >= 1", count >= 1, f"got {count}")
except Exception as e:
test("count_embeddings", False, str(e))
# Test 4: search
try:
query_emb = await get_embedding("Python")
results = search(query_emb, "test-project-xyz", n_results=5)
test("search returns list", isinstance(results, list))
test("search finds results", len(results) > 0, "no results found")
if results:
test("search result has id", "id" in results[0])
test("search result has metadata", "metadata" in results[0])
test("search result has distance", "distance" in results[0])
except Exception as e:
test("search", False, str(e))
# Test 5: delete_by_project
try:
delete_by_project("test-project-xyz")
count_after = count_embeddings("test-project-xyz")
test("delete_by_project removes data", count_after == 0, f"still has {count_after}")
except Exception as e:
test("delete_by_project", False, str(e))
async def test_full_pipeline():
print("\n[3/4] Testing Full Pipeline")
print("-" * 40)
project_id = "pipeline-test-proj"
# Clean up first
try:
delete_by_project(project_id)
except:
pass
try:
# Step 1: Generate documentation
doc = await generate_documentation(
task_title="Implement user registration",
what_i_did="Added signup endpoint with email validation and password hashing",
code_snippet="def register(email, password): ..."
)
test("Pipeline: doc generation", "summary" in doc and "details" in doc)
# Step 2: Create embedding from doc
text_to_embed = f"{doc['summary']} {doc['details']}"
embedding = await get_embedding(text_to_embed)
test("Pipeline: embedding created", len(embedding) == 768)
# Step 3: Store in vectorstore
add_embedding(
log_entry_id="pipeline-log-1",
text=text_to_embed,
embedding=embedding,
metadata={"project_id": project_id, "user_id": "dev1"}
)
test("Pipeline: stored in vectorstore", count_embeddings(project_id) == 1)
# Step 4: Search for it
query_emb = await get_embedding("user registration signup")
results = search(query_emb, project_id)
test("Pipeline: search finds it", len(results) > 0)
# Step 5: Synthesize answer
if results:
context = results[0]["metadata"]["text"]
answer = await synthesize_answer(context, "What was done for user registration?")
test("Pipeline: answer synthesized", len(answer) > 20)
# Cleanup
delete_by_project(project_id)
except Exception as e:
test("Pipeline", False, str(e))
async def test_edge_cases():
print("\n[4/4] Testing Edge Cases")
print("-" * 40)
# Test empty search
try:
init_vectorstore()
emb = await get_embedding("random query")
results = search(emb, "nonexistent-project-12345")
test("Empty search returns empty list", results == [])
except Exception as e:
test("Empty search", False, str(e))
# Test long text embedding
try:
long_text = "word " * 1000 # ~5000 chars
emb = await get_embedding(long_text)
test("Long text embedding works", len(emb) == 768)
except Exception as e:
test("Long text embedding", False, str(e))
# Test special characters
try:
special_text = "Code: `const x = 'hello';` // comment <script>alert('xss')</script>"
emb = await get_embedding(special_text)
test("Special chars embedding works", len(emb) == 768)
except Exception as e:
test("Special chars embedding", False, str(e))
async def main():
print("=" * 50)
print(" DEV B TEST SUITE - Intelligence Layer")
print("=" * 50)
await test_llm()
await test_vectorstore()
await test_full_pipeline()
await test_edge_cases()
print("\n" + "=" * 50)
print(f" RESULTS: {passed} passed, {failed} failed")
print("=" * 50)
if failed > 0:
sys.exit(1)
if __name__ == "__main__":
asyncio.run(main())