test: stabilize full test collection

This commit is contained in:
Vykos
2026-06-04 01:27:29 +02:00
committed by GitHub
parent 271489a10c
commit 5869106089
11 changed files with 125 additions and 7 deletions

View File

@@ -82,8 +82,7 @@ python -m uvicorn app:app --host 127.0.0.1 --port 7000
Requirements: Python 3.11+. Cookbook also needs `tmux` for background model
downloads and serves. The app itself is lightweight; local model serving is the
heavy part and depends on the model, runtime, GPU, and VRAM, so small hosts can
connect to API or remote model servers instead. Use `--host 0.0.0.0` only when
you intentionally want LAN/reverse-proxy access.
connect to API or remote model servers instead. Use `--host 0.0.0.0` only when you intentionally want LAN/reverse-proxy access.
### Apple Silicon
Docker on macOS cannot use the Metal GPU. For GPU-accelerated Cookbook on an

View File

@@ -6,6 +6,7 @@ calling do_manage_calendar with an rrule stores a single event carrying that RRU
"""
import json
import sys
import tempfile
import uuid
@@ -14,6 +15,21 @@ from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
def _drop_fake_core_database():
parent = sys.modules.get("core")
attr = getattr(parent, "database", None) if parent is not None else None
mod = sys.modules.get("core.database") or attr
if mod is None or isinstance(getattr(mod, "__file__", None), str):
return
sys.modules.pop("core.database", None)
sys.modules.pop("src.database", None)
if parent is not None and attr is mod:
delattr(parent, "database")
_drop_fake_core_database()
import core.database as cdb
from core.database import CalendarEvent
@@ -32,6 +48,10 @@ def _bind_temp_db(monkeypatch):
# do_manage_calendar does `from core.database import SessionLocal` at call
# time, so patch the module attribute to our temp DB — via monkeypatch so it
# is RESTORED after each test and can't leak into later tests in the process.
monkeypatch.setitem(sys.modules, "core.database", cdb)
parent = sys.modules.get("core")
if parent is not None:
monkeypatch.setattr(parent, "database", cdb, raising=False)
monkeypatch.setattr(cdb, "SessionLocal", _TS)
yield

View File

@@ -1,6 +1,13 @@
import json
import sys
from types import SimpleNamespace
_endpoint_resolver = sys.modules.get("src.endpoint_resolver")
if _endpoint_resolver is not None and not getattr(_endpoint_resolver, "__file__", None):
sys.modules.pop("src.endpoint_resolver", None)
sys.modules.pop("routes.model_routes", None)
sys.modules.pop("routes.chat_routes", None)
from routes import chat_routes

View File

@@ -78,7 +78,12 @@ from core.middleware import require_admin # noqa: E402
# --- token minting: shown once, hashed at rest -----------------------------
def test_mint_token_returns_raw_once_and_stores_only_a_hash():
def test_mint_token_returns_raw_once_and_stores_only_a_hash(monkeypatch):
monkeypatch.setitem(sys.modules, "core.database", _db)
parent = sys.modules.get("core")
if parent is not None:
monkeypatch.setattr(parent, "database", _db, raising=False)
token_id, raw = P.mint_token("alice")
assert raw.startswith("ody_")
# The persisted row stores a bcrypt hash + prefix, never the plaintext.

View File

@@ -22,7 +22,8 @@ def test_background_status_poll_reconciles_into_local_tasks():
assert "const statusById = new Map(tasks.map(t => [t.session_id, t]));" in source
assert "const nextStatus = live.status === 'completed'" in source
assert "? 'done'" in source
assert "live.status === 'error'" in source
assert ": (live.status === 'error'" in source
assert "? 'error'" in source
assert "_saveTasks(localTasks);" in source
assert "completedDeps.forEach(t => _refreshDepsAfterInstall(t));" in source

View File

@@ -13,6 +13,7 @@ while completing reliably everywhere.
"""
import tempfile
import sys
import uuid
from types import SimpleNamespace
@@ -21,6 +22,21 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
from unittest.mock import MagicMock
def _drop_fake_core_database():
parent = sys.modules.get("core")
attr = getattr(parent, "database", None) if parent is not None else None
mod = sys.modules.get("core.database") or attr
if mod is None or isinstance(getattr(mod, "__file__", None), str):
return
sys.modules.pop("core.database", None)
sys.modules.pop("src.database", None)
if parent is not None and attr is mod:
delattr(parent, "database")
_drop_fake_core_database()
import core.database as cdb
import routes.document_routes as droutes
from core.database import Document

View File

@@ -141,4 +141,3 @@ def test_build_anthropic_payload_alternating_roles():

View File

@@ -1,6 +1,23 @@
import pytest
import sys
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
def _drop_fake_core_database():
parent = sys.modules.get("core")
attr = getattr(parent, "database", None) if parent is not None else None
mod = sys.modules.get("core.database") or attr
if mod is None or isinstance(getattr(mod, "__file__", None), str):
return
sys.modules.pop("core.database", None)
sys.modules.pop("src.database", None)
if parent is not None and attr is mod:
delattr(parent, "database")
_drop_fake_core_database()
from core.database import Base, Session, ChatMessage
from datetime import datetime
@@ -35,4 +52,3 @@ def test_sqlite_foreign_keys_cascade():
assert db.query(ChatMessage).count() == 0
db.close()

View File

@@ -1,5 +1,6 @@
"""Regression tests for task-result delivery into chat sessions (issue #326)."""
import asyncio
import sys
import types as _types
import pytest
@@ -11,6 +12,22 @@ if not isinstance(sqlalchemy, _types.ModuleType):
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
def _drop_fake_core_database():
parent = sys.modules.get("core")
attr = getattr(parent, "database", None) if parent is not None else None
mod = sys.modules.get("core.database") or attr
if mod is None or isinstance(getattr(mod, "__file__", None), str):
return
sys.modules.pop("core.database", None)
sys.modules.pop("src.database", None)
if parent is not None and attr is mod:
delattr(parent, "database")
_drop_fake_core_database()
import core.database as cdb
from core.database import Base, Session as DbSession
from src.task_scheduler import TaskScheduler
@@ -46,10 +63,15 @@ def _make_task():
)
def test_session_delivery_survives_empty_database():
def test_session_delivery_survives_empty_database(monkeypatch):
"""On a fresh/wiped database there is no session to inherit endpoint/model
from, so _resolve_defaults returns None. The delivery must still persist a
session instead of crashing on the NOT NULL constraint (issue #326)."""
monkeypatch.setitem(sys.modules, "core.database", cdb)
parent = sys.modules.get("core")
if parent is not None:
monkeypatch.setattr(parent, "database", cdb, raising=False)
db = _make_db()
scheduler = TaskScheduler.__new__(TaskScheduler)
scheduler._session_manager = None

View File

@@ -1,8 +1,25 @@
"""Tests for topic keyword matching (src/topic_analyzer.py)."""
import sys
from types import SimpleNamespace
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
def _drop_fake_core_database():
parent = sys.modules.get("core")
attr = getattr(parent, "database", None) if parent is not None else None
mod = sys.modules.get("core.database") or attr
if mod is None or isinstance(getattr(mod, "__file__", None), str):
return
sys.modules.pop("core.database", None)
sys.modules.pop("src.database", None)
if parent is not None and attr is mod:
delattr(parent, "database")
_drop_fake_core_database()
from core.database import Base, Session as DbSession, ChatMessage as DbChatMessage
from core.session_manager import SessionManager
from src.topic_analyzer import analyze_topics

View File

@@ -6,6 +6,22 @@ from datetime import datetime
# from it, so drop the stub here to load the real module under test.
if "src.database" in sys.modules:
del sys.modules["src.database"]
_core_database = sys.modules.get("core.database")
_core_database_all = getattr(_core_database, "__all__", None) if _core_database is not None else None
if (
_core_database is not None
and (
not getattr(_core_database, "__file__", None)
or (
_core_database_all is not None
and (
not isinstance(_core_database_all, (list, tuple, set))
or not all(isinstance(name, str) for name in _core_database_all)
)
)
)
):
del sys.modules["core.database"]
import pytest
from src.webhook_manager import validate_webhook_url