Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Jules/qa.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
## 2026-03-27 - Mocking File I/O for TranscriptCorrector | Pattern: Explicitly mock Path.exists and builtins.open when initializing utilities that read config files to avoid FileNotFoundError | Action: Use @patch('pathlib.Path.exists', return_value=True) and @patch('builtins.open', new_callable=mock_open) with a valid JSON string
## 2026-04-02 - Mocking Module-Level Variables for EmbeddingAgentService | Pattern: Patching module-level flags requires defensive mocking across multiple potential namespaces (e.g., `api.embedding_agent...` and `app.api.embedding_agent...` with `create=True`) depending on test runner execution path | Action: Apply `patch` directly to the module attribute path and add a fallback patch with `create=True` when testing behavior dependent on global flags.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This QA note recommends patching app.api.embedding_agent..., but the repository does not contain an app package, so this guidance is likely incorrect and may lead to brittle tests. Consider updating the note to recommend patching the real import path used in tests/runtime (e.g., api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE) and avoid suggesting fallback patches to non-importable module paths.

Suggested change
## 2026-04-02 - Mocking Module-Level Variables for EmbeddingAgentService | Pattern: Patching module-level flags requires defensive mocking across multiple potential namespaces (e.g., `api.embedding_agent...` and `app.api.embedding_agent...` with `create=True`) depending on test runner execution path | Action: Apply `patch` directly to the module attribute path and add a fallback patch with `create=True` when testing behavior dependent on global flags.
## 2026-04-02 - Mocking Module-Level Variables for EmbeddingAgentService | Pattern: Patching module-level flags should target the actual import path used at runtime (for example, `api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE`) rather than attempting to patch fallback or non-importable module namespaces | Action: Apply `patch` directly to the concrete module attribute path used by the code under test (e.g., `api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE`) when testing behavior dependent on global flags.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This QA note recommends a "fallback patch" with create=True targeting app.api.embedding_agent..., but create=True does not create missing modules — only missing attributes. Since no app package exists, following this guidance produces ModuleNotFoundError. Update the note to recommend patching only the real import path (api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .Jules/qa.md, line 2:

<comment>This QA note recommends a "fallback patch" with `create=True` targeting `app.api.embedding_agent...`, but `create=True` does not create missing modules — only missing attributes. Since no `app` package exists, following this guidance produces `ModuleNotFoundError`. Update the note to recommend patching only the real import path (`api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE`).</comment>

<file context>
@@ -1 +1,2 @@
 ## 2026-03-27 - Mocking File I/O for TranscriptCorrector | Pattern: Explicitly mock Path.exists and builtins.open when initializing utilities that read config files to avoid FileNotFoundError | Action: Use @patch('pathlib.Path.exists', return_value=True) and @patch('builtins.open', new_callable=mock_open) with a valid JSON string
+## 2026-04-02 - Mocking Module-Level Variables for EmbeddingAgentService | Pattern: Patching module-level flags requires defensive mocking across multiple potential namespaces (e.g., `api.embedding_agent...` and `app.api.embedding_agent...` with `create=True`) depending on test runner execution path | Action: Apply `patch` directly to the module attribute path and add a fallback patch with `create=True` when testing behavior dependent on global flags.
</file context>
Suggested change
## 2026-04-02 - Mocking Module-Level Variables for EmbeddingAgentService | Pattern: Patching module-level flags requires defensive mocking across multiple potential namespaces (e.g., `api.embedding_agent...` and `app.api.embedding_agent...` with `create=True`) depending on test runner execution path | Action: Apply `patch` directly to the module attribute path and add a fallback patch with `create=True` when testing behavior dependent on global flags.
## 2026-04-02 - Mocking Module-Level Variables for EmbeddingAgentService | Pattern: Patching module-level flags should target the actual import path used at runtime (for example, `api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE`) rather than attempting to patch fallback or non-importable module namespaces | Action: Apply `patch` directly to the concrete module attribute path used by the code under test (e.g., `api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE`) when testing behavior dependent on global flags.
Fix with Cubic

35 changes: 35 additions & 0 deletions api/embedding_agent/tests/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import pytest
from pathlib import Path
from unittest.mock import MagicMock, patch
import api.embedding_agent.service

from ..models import (
EmbeddingAgentConfig,
Expand Down Expand Up @@ -288,6 +290,39 @@ def test_empty_batch(self, service: EmbeddingAgentService):
BatchEmbeddingRequest(texts=[])


class TestKnowledgeBase:
"""Tests for knowledge base loading."""

def test_load_knowledge_base_not_available(self, config: EmbeddingAgentConfig):
"""Test loading when clinical embedder is not available."""
with patch.object(api.embedding_agent.service, 'CLINICAL_EMBEDDER_AVAILABLE', False):
service = EmbeddingAgentService(config)
assert service.load_knowledge_base() == 0

def test_load_knowledge_base_available(self, config: EmbeddingAgentConfig):
"""Test loading when clinical embedder is available."""
with patch('app.api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True, create=True):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Patch a real module path for clinical embedder flag

The target app.api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE is not importable in this repository, and patch(..., create=True) does not create missing modules—it only allows missing attributes. As a result, this test raises ModuleNotFoundError: No module named 'app' before reaching the assertions, so the new knowledge-base coverage fails in the default test environment. Patch only the importable module (api.embedding_agent.service...) or guard the alternate namespace without importing a nonexistent package.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This patch target points to a non-existent module path (app.api...) and can fail the test with ModuleNotFoundError.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At api/embedding_agent/tests/test_service.py, line 304:

<comment>This patch target points to a non-existent module path (`app.api...`) and can fail the test with `ModuleNotFoundError`.</comment>

<file context>
@@ -288,6 +290,39 @@ def test_empty_batch(self, service: EmbeddingAgentService):
+
+    def test_load_knowledge_base_available(self, config: EmbeddingAgentConfig):
+        """Test loading when clinical embedder is available."""
+        with patch('app.api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True, create=True):
+            with patch('api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True):
+                with patch.object(EmbeddingAgentService, '_initialize_clinical_embedder'):
</file context>
Suggested change
with patch('app.api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True, create=True):
with patch('api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True):
Fix with Cubic

with patch('api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True):
with patch.object(EmbeddingAgentService, '_initialize_clinical_embedder'):
service = EmbeddingAgentService(config)
service._clinical_embedder = MagicMock()
service._clinical_embedder.process_all_knowledge.return_value = (["item1", "item2"], None)

assert service.load_knowledge_base() == 2
assert service._knowledge_items == ["item1", "item2"]

def test_load_knowledge_base_exception(self, config: EmbeddingAgentConfig):
"""Test exception handling during knowledge base loading."""
with patch('app.api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True, create=True):
with patch('api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True):
with patch.object(EmbeddingAgentService, '_initialize_clinical_embedder'):
service = EmbeddingAgentService(config)
service._clinical_embedder = MagicMock()
service._clinical_embedder.process_all_knowledge.side_effect = Exception("Test error")

assert service.load_knowledge_base() == 0
Comment on lines +304 to +323
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

patch('app.api.embedding_agent.service...') will raise ModuleNotFoundError unless an app package is importable. The repo doesn't contain an app/ package, so this makes the tests environment-dependent/flaky. Patch only the module actually used by EmbeddingAgentService (e.g., api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE, ideally via patch.object(api.embedding_agent.service, ...)) and drop the app.api... patch (or create an explicit alias in sys.modules if you truly need both).

Suggested change
with patch('app.api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True, create=True):
with patch('api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True):
with patch.object(EmbeddingAgentService, '_initialize_clinical_embedder'):
service = EmbeddingAgentService(config)
service._clinical_embedder = MagicMock()
service._clinical_embedder.process_all_knowledge.return_value = (["item1", "item2"], None)
assert service.load_knowledge_base() == 2
assert service._knowledge_items == ["item1", "item2"]
def test_load_knowledge_base_exception(self, config: EmbeddingAgentConfig):
"""Test exception handling during knowledge base loading."""
with patch('app.api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True, create=True):
with patch('api.embedding_agent.service.CLINICAL_EMBEDDER_AVAILABLE', True):
with patch.object(EmbeddingAgentService, '_initialize_clinical_embedder'):
service = EmbeddingAgentService(config)
service._clinical_embedder = MagicMock()
service._clinical_embedder.process_all_knowledge.side_effect = Exception("Test error")
assert service.load_knowledge_base() == 0
with patch.object(api.embedding_agent.service, "CLINICAL_EMBEDDER_AVAILABLE", True):
with patch.object(EmbeddingAgentService, '_initialize_clinical_embedder'):
service = EmbeddingAgentService(config)
service._clinical_embedder = MagicMock()
service._clinical_embedder.process_all_knowledge.return_value = (["item1", "item2"], None)
assert service.load_knowledge_base() == 2
assert service._knowledge_items == ["item1", "item2"]
def test_load_knowledge_base_exception(self, config: EmbeddingAgentConfig):
"""Test exception handling during knowledge base loading."""
with patch.object(api.embedding_agent.service, "CLINICAL_EMBEDDER_AVAILABLE", True):
with patch.object(EmbeddingAgentService, '_initialize_clinical_embedder'):
service = EmbeddingAgentService(config)
service._clinical_embedder = MagicMock()
service._clinical_embedder.process_all_knowledge.side_effect = Exception("Test error")
assert service.load_knowledge_base() == 0

Copilot uses AI. Check for mistakes.


if __name__ == "__main__":
pytest.main([__file__, "-v"])

Loading