Skip to content

Commit e011f7b

Browse files
committed
Add fixtures and tests for MemoryNote and AgenticMemorySystem
1 parent 28daa2c commit e011f7b

File tree

2 files changed

+238
-0
lines changed

2 files changed

+238
-0
lines changed

tests/conftest.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from pathlib import Path
55

66
from agentic_memory.retrievers import ChromaRetriever, PersistentChromaRetriever
7+
from agentic_memory.memory_system import AgenticMemorySystem
8+
from agentic_memory.memory_note import MemoryNote
79

810

911
@pytest.fixture
@@ -45,3 +47,48 @@ def existing_collection(temp_db_dir, sample_metadata):
4547
)
4648
retriever.add_document("Existing document", sample_metadata, "existing_doc")
4749
return temp_db_dir, "existing_collection"
50+
51+
52+
@pytest.fixture
53+
def memory_system(retriever):
54+
"""Fixture providing a clean AgenticMemorySystem instance."""
55+
system = AgenticMemorySystem(retriever=retriever)
56+
yield system
57+
# Cleanup handled by retriever fixture
58+
59+
60+
@pytest.fixture
61+
def sample_memory_note():
62+
"""Fixture providing a sample MemoryNote instance."""
63+
return MemoryNote(
64+
content="This is a test memory about machine learning",
65+
keywords=["machine learning", "AI", "test"],
66+
context="Testing",
67+
category="Technical",
68+
tags=["test", "ml"]
69+
)
70+
71+
72+
@pytest.fixture
73+
def populated_memory_system(memory_system):
74+
"""Fixture providing a memory system with pre-populated data."""
75+
# Add several test memories
76+
memory_system.add_note(
77+
content="Python is a programming language",
78+
keywords=["python", "programming"],
79+
context="Programming",
80+
tags=["language", "coding"]
81+
)
82+
memory_system.add_note(
83+
content="Machine learning is a subset of AI",
84+
keywords=["machine learning", "AI"],
85+
context="Technology",
86+
tags=["ml", "ai"]
87+
)
88+
memory_system.add_note(
89+
content="ChromaDB is a vector database",
90+
keywords=["chromadb", "database", "vector"],
91+
context="Technology",
92+
tags=["database", "vector"]
93+
)
94+
return memory_system

tests/test_memory_system.py

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import pytest
2+
import json
3+
4+
from agentic_memory.memory_note import MemoryNote
5+
from agentic_memory.memory_system import AgenticMemorySystem
6+
from agentic_memory.retrievers import ChromaRetriever
7+
8+
9+
class TestMemoryNote:
10+
"""Test suite for MemoryNote class."""
11+
12+
def test_memory_note_creation_with_defaults(self):
13+
"""Test creating a MemoryNote with minimal parameters."""
14+
note = MemoryNote(content="Test content")
15+
16+
assert note.content == "Test content"
17+
assert note.id is not None
18+
assert isinstance(note.id, str)
19+
assert note.keywords == []
20+
assert note.retrieval_count == 0
21+
assert note.context == "General"
22+
assert note.category == "Uncategorized"
23+
assert note.tags == []
24+
assert note.timestamp is not None
25+
assert note.last_accessed is not None
26+
27+
def test_memory_note_creation_with_all_fields(self):
28+
"""Test creating a MemoryNote with all parameters."""
29+
note = MemoryNote(
30+
content="Full content",
31+
id="custom-id",
32+
keywords=["key1", "key2"],
33+
retrieval_count=5,
34+
timestamp="202401010000",
35+
last_accessed="202401010100",
36+
context="Custom Context",
37+
category="Custom Category",
38+
tags=["tag1", "tag2"]
39+
)
40+
41+
assert note.content == "Full content"
42+
assert note.id == "custom-id"
43+
assert note.keywords == ["key1", "key2"]
44+
assert note.retrieval_count == 5
45+
assert note.timestamp == "202401010000"
46+
assert note.last_accessed == "202401010100"
47+
assert note.context == "Custom Context"
48+
assert note.category == "Custom Category"
49+
assert note.tags == ["tag1", "tag2"]
50+
51+
52+
class TestAgenticMemorySystemInit:
53+
"""Test suite for AgenticMemorySystem initialization."""
54+
55+
def test_init_with_default_retriever(self):
56+
"""Test initialization with default retriever."""
57+
system = AgenticMemorySystem(collection_name="test_init")
58+
59+
assert system.memories == {}
60+
assert isinstance(system.retriever, ChromaRetriever)
61+
assert system._llm_processor is None
62+
63+
# Cleanup
64+
system.retriever.client.reset()
65+
66+
def test_init_with_invalid_retriever(self):
67+
"""Test that invalid retriever raises TypeError."""
68+
with pytest.raises(TypeError):
69+
AgenticMemorySystem(retriever="invalid")
70+
71+
72+
class TestAgenticMemorySystemCRUD:
73+
"""Test suite for CRUD operations."""
74+
75+
def test_add_note_minimal(self, memory_system):
76+
"""Test adding a note with minimal parameters."""
77+
note_id = memory_system.add_note(content="Test content")
78+
79+
assert note_id is not None
80+
assert note_id in memory_system.memories
81+
assert memory_system.memories[note_id].content == "Test content"
82+
83+
def test_add_note_with_metadata(self, memory_system):
84+
"""Test adding a note with full metadata."""
85+
note_id = memory_system.add_note(
86+
content="Rich content",
87+
keywords=["key1", "key2"],
88+
context="Test Context",
89+
category="Test Category",
90+
tags=["tag1", "tag2"]
91+
)
92+
93+
note = memory_system.memories[note_id]
94+
assert note.content == "Rich content"
95+
assert note.keywords == ["key1", "key2"]
96+
assert note.context == "Test Context"
97+
assert note.category == "Test Category"
98+
assert note.tags == ["tag1", "tag2"]
99+
100+
def test_add_note_custom_timestamp(self, memory_system):
101+
"""Test adding a note with custom timestamp."""
102+
custom_time = "202401010000"
103+
note_id = memory_system.add_note(
104+
content="Timestamped content",
105+
timestamp=custom_time
106+
)
107+
108+
note = memory_system.memories[note_id]
109+
assert note.timestamp == custom_time
110+
111+
def test_update_existing_note(self, memory_system):
112+
"""Test updating an existing note."""
113+
note_id = memory_system.add_note(
114+
content="Original content",
115+
keywords=["old"],
116+
tags=["old_tag"]
117+
)
118+
119+
success = memory_system.update(
120+
note_id,
121+
content="Updated content",
122+
keywords=["new"],
123+
tags=["new_tag"]
124+
)
125+
126+
assert success is True
127+
note = memory_system.memories[note_id]
128+
assert note.content == "Updated content"
129+
assert note.keywords == ["new"]
130+
assert note.tags == ["new_tag"]
131+
132+
def test_update_nonexistent_note(self, memory_system):
133+
"""Test updating a non-existent note returns False."""
134+
success = memory_system.update(
135+
"nonexistent-id",
136+
content="New content"
137+
)
138+
assert success is False
139+
140+
141+
class TestAgenticMemorySystemSearch:
142+
"""Test suite for search functionality."""
143+
144+
def test_search_empty_system(self, memory_system):
145+
"""Test searching in an empty system."""
146+
results = memory_system.search("test query")
147+
assert results == []
148+
149+
def test_search_returns_results(self, populated_memory_system):
150+
"""Test that search returns relevant results."""
151+
results = populated_memory_system.search("python programming")
152+
153+
assert len(results) > 0
154+
assert isinstance(results, list)
155+
assert all(isinstance(r, dict) for r in results)
156+
157+
def test_search_result_structure(self, populated_memory_system):
158+
"""Test that search results have correct structure."""
159+
results = populated_memory_system.search("machine learning", k=1)
160+
161+
assert len(results) <= 1
162+
if results:
163+
result = results[0]
164+
assert "id" in result
165+
assert "content" in result
166+
167+
def test_search_respects_k_parameter(self, populated_memory_system):
168+
"""Test that search respects the k parameter."""
169+
results = populated_memory_system.search("technology", k=2)
170+
assert len(results) <= 2
171+
172+
173+
class TestAgenticMemorySystemHelpers:
174+
"""Test suite for helper methods."""
175+
176+
def test_serialize_metadata(self, memory_system, sample_memory_note):
177+
"""Test metadata serialization from MemoryNote."""
178+
metadata = memory_system._serialize_metadata(sample_memory_note)
179+
ref_metadata = sample_memory_note.model_dump()
180+
181+
assert isinstance(metadata, dict)
182+
183+
for key, ref_value in ref_metadata.items():
184+
assert key in metadata
185+
if ref_value is None:
186+
assert metadata[key] is None
187+
elif isinstance(ref_value, (dict, list)):
188+
assert metadata[key] == json.dumps(ref_value)
189+
assert json.loads(metadata[key]) == ref_value
190+
else:
191+
assert metadata[key] == ref_value

0 commit comments

Comments
 (0)