Skip to content

Commit d310828

Browse files
drknowhowclaude
andcommitted
fix(tests): make CI-environment-independent
Two test fixes that were silently passing locally because of dev-machine artifacts but failing on clean CI runners: 1. tests/test_project_manager.py used a hardcoded "/tmp/proj" path. On clean Linux/macOS/Windows CI runners this path doesn't exist, so `Path("/tmp/proj").is_dir()` returned False and the live-session and last-session-derivation code paths in `list_projects` were silently skipped, causing the assertions to compare against the wrong values. Locally the path happened to exist (e.g. U:\tmp\proj on the dev box) making the test pass for the wrong reason. Fixed by using a real `tempfile.TemporaryDirectory()` in setUp / tearDown. 2. test_ollama_embedding_path_used_when_available depends on numpy, which oracle/services/federated_graph.py lazy-imports. numpy was in the [vector] extra but not in [dev], so CI couldn't exercise the embedding similarity path. Added numpy + scikit-learn to [dev] so the CI matrix tests the production code paths end-to-end. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1377606 commit d310828

2 files changed

Lines changed: 21 additions & 6 deletions

File tree

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ dev = [
6868
"ruff>=0.6.0",
6969
"build>=1.0.0",
7070
"twine>=5.0.0",
71+
# Vector deps so CI exercises the embedding/similarity code paths
72+
# (federated_graph lazy-imports numpy; tests for that path need it).
73+
"numpy>=1.24.0",
74+
"scikit-learn>=1.3.0",
7175
]
7276

7377
[project.urls]

tests/test_project_manager.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import tempfile
12
import unittest
23
from datetime import datetime, timedelta, timezone
34
from unittest.mock import patch
@@ -22,6 +23,16 @@ def get_recent(self, limit=1, event_type=None, since=None):
2223
class TestProjectManager(unittest.TestCase):
2324
def setUp(self):
2425
self.pm = ProjectManager()
26+
# Use a real existing dir so Path(p["path"]).is_dir() is True. The
27+
# previous hardcoded self.proj_path was accidentally truthy on dev
28+
# machines where the path happened to exist (e.g. U:\tmp\proj on
29+
# Windows) but False on clean CI runners — making the live-session
30+
# and last-session-derivation paths silently skip.
31+
self._tmp = tempfile.TemporaryDirectory()
32+
self.proj_path = self._tmp.name
33+
34+
def tearDown(self):
35+
self._tmp.cleanup()
2536

2637
def test_live_session_info_ignores_stale_activity(self):
2738
old = (datetime.now(timezone.utc) - timedelta(hours=2)).isoformat()
@@ -47,8 +58,8 @@ def test_live_session_info_keeps_recent_activity(self):
4758

4859
def test_list_projects_does_not_mark_null_port_project_active_without_recent_session(self):
4960
now = datetime.now(timezone.utc).isoformat()
50-
with patch.object(self.pm, "_read_projects", return_value=[{"name": "Proj", "path": "/tmp/proj", "added_at": now}]), \
51-
patch.object(self.pm, "_read_registry", return_value=[{"project_path": "/tmp/proj", "port": None, "started_at": now}]), \
61+
with patch.object(self.pm, "_read_projects", return_value=[{"name": "Proj", "path": self.proj_path, "added_at": now}]), \
62+
patch.object(self.pm, "_read_registry", return_value=[{"project_path": self.proj_path, "port": None, "started_at": now}]), \
5263
patch.object(self.pm, "_port_alive", return_value=False), \
5364
patch.object(self.pm, "_get_live_session_info", return_value=None), \
5465
patch.object(self.pm, "_read_project_config", return_value={}):
@@ -64,7 +75,7 @@ def test_list_projects_derives_last_session_from_activity_log(self):
6475
recent = (datetime.now(timezone.utc) - timedelta(hours=6)).isoformat()
6576
with patch.object(self.pm, "_read_projects", return_value=[{
6677
"name": "Proj",
67-
"path": "/tmp/proj",
78+
"path": self.proj_path,
6879
"added_at": old,
6980
"last_session": old,
7081
}]), \
@@ -86,7 +97,7 @@ def test_list_projects_marks_live_session_active_without_ui_port(self):
8697
"last_activity": now,
8798
"description": "recent",
8899
}
89-
with patch.object(self.pm, "_read_projects", return_value=[{"name": "Proj", "path": "/tmp/proj", "added_at": now}]), \
100+
with patch.object(self.pm, "_read_projects", return_value=[{"name": "Proj", "path": self.proj_path, "added_at": now}]), \
90101
patch.object(self.pm, "_read_registry", return_value=[]), \
91102
patch.object(self.pm, "_get_live_session_info", return_value=live_session), \
92103
patch.object(self.pm, "_read_project_config", return_value={}), \
@@ -103,15 +114,15 @@ def test_get_active_sessions_includes_live_session_without_ui_port(self):
103114
with patch.object(self.pm, "_read_registry", return_value=[]), \
104115
patch.object(self.pm, "list_projects", return_value=[{
105116
"name": "Proj",
106-
"path": "/tmp/proj",
117+
"path": self.proj_path,
107118
"session_active": True,
108119
"ui_active": False,
109120
"started_at": now,
110121
"live_session_id": "sess-2",
111122
}]):
112123
sessions = self.pm.get_active_sessions()
113124
self.assertEqual(sessions, [{
114-
"project_path": "/tmp/proj",
125+
"project_path": self.proj_path,
115126
"project_name": "Proj",
116127
"port": None,
117128
"started_at": now,

0 commit comments

Comments
 (0)