From ff0b619d1f57c2b2e66adeec247d890db387e817 Mon Sep 17 00:00:00 2001 From: phernandez Date: Fri, 3 Jan 2025 12:08:41 -0600 Subject: [PATCH] break up sync tests between documents/knowledge --- tests/conftest.py | 23 +++- tests/services/sync/test_sync_documents.py | 41 +++++++ tests/services/sync/test_sync_knowledge.py | 72 +++++++++++ tests/services/sync/test_sync_service.py | 131 ++------------------- 4 files changed, 143 insertions(+), 124 deletions(-) create mode 100644 tests/services/sync/test_sync_documents.py create mode 100644 tests/services/sync/test_sync_knowledge.py diff --git a/tests/conftest.py b/tests/conftest.py index e65e4b4e..858f76bf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -29,6 +29,7 @@ from basic_memory.services.activity_service import ActivityService from basic_memory.services.file_service import FileService from basic_memory.services import KnowledgeService from basic_memory.services.sync.knowledge_sync_service import KnowledgeSyncService +from basic_memory.services.sync.sync_service import SyncService @pytest_asyncio.fixture @@ -37,12 +38,15 @@ def anyio_backend(): @pytest_asyncio.fixture -def test_config(tmp_path): +def test_config(tmp_path) -> ProjectConfig: """Test configuration using in-memory DB.""" config = ProjectConfig( name="test", ) config.home = tmp_path + + (tmp_path / config.documents_dir.name).mkdir(parents=True, exist_ok=True) + (tmp_path / config.knowledge_dir.name).mkdir(parents=True, exist_ok=True) return config @@ -188,6 +192,23 @@ async def knowledge_sync_service( return KnowledgeSyncService(entity_service, observation_service, relation_service) +@pytest_asyncio.fixture +async def sync_service( + document_service: DocumentService, + knowledge_sync_service: KnowledgeSyncService, + file_change_scanner: FileChangeScanner, + knowledge_parser: KnowledgeParser, +) -> SyncService: + """Create sync service for testing.""" + return SyncService( + scanner=file_change_scanner, + document_service=document_service, + knowledge_sync_service=knowledge_sync_service, + knowledge_parser=knowledge_parser, + ) + + + @pytest_asyncio.fixture(scope="function") async def sample_entity(entity_repository: EntityRepository) -> Entity: """Create a sample entity for testing.""" diff --git a/tests/services/sync/test_sync_documents.py b/tests/services/sync/test_sync_documents.py new file mode 100644 index 00000000..a82aa738 --- /dev/null +++ b/tests/services/sync/test_sync_documents.py @@ -0,0 +1,41 @@ +"""Test sync service.""" + +from pathlib import Path +import pytest + +from basic_memory.config import ProjectConfig +from basic_memory.services import DocumentService +from basic_memory.services.sync.sync_service import SyncService +from basic_memory.models import Document + + +async def create_test_file(path: Path, content: str = "test content") -> None: + """Create a test file with given content.""" + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content) + + +@pytest.mark.asyncio +async def test_sync_documents( + sync_service: SyncService, test_config: ProjectConfig, document_service: DocumentService +): + """Test syncing document files.""" + # Create test files + docs_dir = test_config.documents_dir + await create_test_file(docs_dir / "new.md", "new document") + await create_test_file(docs_dir / "modified.md", "modified document") + + # Add existing doc to DB + doc = Document(path_id="modified.md", file_path="modified.md", checksum="12345678") + added = await document_service.repository.add(doc) + + # Run sync + await sync_service.sync(test_config.home) + + # Verify results + documents = await document_service.repository.find_all() + assert len(documents) == 2 + + paths = {d.path_id for d in documents} + assert "new.md" in paths + assert "modified.md" in paths diff --git a/tests/services/sync/test_sync_knowledge.py b/tests/services/sync/test_sync_knowledge.py new file mode 100644 index 00000000..3914a7c4 --- /dev/null +++ b/tests/services/sync/test_sync_knowledge.py @@ -0,0 +1,72 @@ +"""Test sync service.""" + +from pathlib import Path +import pytest + +from basic_memory.config import ProjectConfig +from basic_memory.services import EntityService +from basic_memory.services.sync.sync_service import SyncService +from basic_memory.models import Entity + + +async def create_test_file(path: Path, content: str = "test content") -> None: + """Create a test file with given content.""" + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content) + + +@pytest.mark.asyncio +async def test_sync_knowledge( + sync_service: SyncService, test_config: ProjectConfig, entity_service: EntityService +): + """Test syncing knowledge files.""" + # Create test files + knowledge_dir = test_config.knowledge_dir + + # New entity with relation + new_content = """ +--- +type: concept +id: concept/test_concept +created: 2023-01-01 +modified: 2023-01-01 +--- +# Test Concept + +A test concept. + +## Observations +- [design] Core feature + +## Relations +- depends_on [[concept/other]] +""" + await create_test_file(knowledge_dir / "concept/test_concept.md", new_content) + + # Create related entity in DB + # will be categorized as deleted + other = Entity( + path_id="concept/other", + name="Other", + entity_type="concept", + file_path="concept/other.md", + checksum="12345678", + ) + await entity_service.repository.add(other) + + # Run sync + await sync_service.sync(test_config.home) + + # Verify results + entities = await entity_service.repository.find_all() + assert len(entities) == 1 + + # Find new entity + test_concept: Entity = next(e for e in entities if e.path_id == "concept/test_concept") + assert test_concept.entity_type == "concept" + + # Verify relation was not created + # because file for related entity was not found + entity = await entity_service.get_by_path_id(test_concept.path_id) + relations = entity.relations + assert len(relations) == 0 diff --git a/tests/services/sync/test_sync_service.py b/tests/services/sync/test_sync_service.py index 20c964fa..6cf6f5d3 100644 --- a/tests/services/sync/test_sync_service.py +++ b/tests/services/sync/test_sync_service.py @@ -4,6 +4,7 @@ from pathlib import Path import pytest import pytest_asyncio +from basic_memory.config import ProjectConfig from basic_memory.services import DocumentService, EntityService, FileChangeScanner from basic_memory.services.sync.knowledge_sync_service import KnowledgeSyncService from basic_memory.services.sync.sync_service import SyncService @@ -11,30 +12,6 @@ from basic_memory.markdown import KnowledgeParser, EntityMarkdown from basic_memory.models import Document, Entity, Observation -@pytest_asyncio.fixture -async def sync_service( - document_service: DocumentService, - knowledge_sync_service: KnowledgeSyncService, - file_change_scanner: FileChangeScanner, - knowledge_parser: KnowledgeParser, -) -> SyncService: - """Create sync service for testing.""" - return SyncService( - scanner=file_change_scanner, - document_service=document_service, - knowledge_sync_service=knowledge_sync_service, - knowledge_parser=knowledge_parser, - ) - - -@pytest.fixture -def root_dir(tmp_path: Path) -> Path: - """Create temp directory structure.""" - (tmp_path / "documents").mkdir() - (tmp_path / "knowledge").mkdir() - return tmp_path - - async def create_test_file(path: Path, content: str = "test content") -> None: """Create a test file with given content.""" path.parent.mkdir(parents=True, exist_ok=True) @@ -42,111 +19,19 @@ async def create_test_file(path: Path, content: str = "test content") -> None: @pytest.mark.asyncio -async def test_sync_empty_directories(sync_service: SyncService, root_dir: Path): +async def test_sync_empty_directories(sync_service: SyncService, test_config: ProjectConfig): """Test syncing empty directories.""" - await sync_service.sync(root_dir) + await sync_service.sync(test_config.home) # Should not raise exceptions for empty dirs - assert (root_dir / "documents").exists() - assert (root_dir / "knowledge").exists() - - -@pytest.mark.asyncio -async def test_sync_documents( - sync_service: SyncService, - root_dir: Path, - document_service: DocumentService -): - """Test syncing document files.""" - # Create test files - docs_dir = root_dir / "documents" - await create_test_file(docs_dir / "new.md", "new document") - await create_test_file(docs_dir / "modified.md", "modified document") - - # Add existing doc to DB - doc = Document( - path_id="modified.md", - file_path="modified.md", - checksum="12345678" - ) - added = await document_service.repository.add(doc) - - # Run sync - await sync_service.sync(root_dir) - - # Verify results - documents = await document_service.repository.find_all() - assert len(documents) == 2 - - paths = {d.path_id for d in documents} - assert "new.md" in paths - assert "modified.md" in paths - - - - -@pytest.mark.asyncio -async def test_sync_knowledge( - sync_service: SyncService, - root_dir: Path, - entity_service: EntityService -): - """Test syncing knowledge files.""" - # Create test files - knowledge_dir = root_dir / "knowledge" - - # New entity with relation - new_content = """ ---- -type: concept -id: concept/test_concept -created: 2023-01-01 -modified: 2023-01-01 ---- -# Test Concept - -A test concept. - -## Observations -- [design] Core feature - -## Relations -- depends_on [[concept/other]] -""" - await create_test_file(knowledge_dir / "concept/test_concept.md", new_content) - - # Create related entity in DB - # will be categorized as deleted - other = Entity( - path_id="concept/other", - name="Other", - entity_type="concept", - file_path="concept/other.md", - checksum = "12345678" - ) - await entity_service.repository.add(other) - - # Run sync - await sync_service.sync(root_dir) - - # Verify results - entities = await entity_service.repository.find_all() - assert len(entities) == 1 - - # Find new entity - test_concept: Entity = next(e for e in entities if e.path_id == "concept/test_concept") - assert test_concept.entity_type == "concept" - - # Verify relation was not created - entity = await entity_service.get_by_path_id(test_concept.path_id) - relations = entity.relations - assert len(relations) == 0 - + assert (test_config.documents_dir).exists() + assert (test_config.knowledge_dir).exists() + @pytest.mark.asyncio async def test_sync_deletes( sync_service: SyncService, - root_dir: Path, + test_config: ProjectConfig, document_service: DocumentService, entity_service: EntityService ): @@ -169,7 +54,7 @@ async def test_sync_deletes( await entity_service.repository.add(entity) # Run sync - await sync_service.sync(root_dir) + await sync_service.sync(test_config.home) # Verify deletions docs = await document_service.repository.find_all()