Kansho/backend/tests/harness.py
Lars 79e4fd0d4b
All checks were successful
Deploy Development / deploy (push) Successful in 56s
Test Suite / pytest-backend (push) Successful in 2m43s
Test Suite / smoke-dev (push) Successful in 0s
Test Suite / frontend-build (push) Successful in 15s
Load the test schema once and truncate data between files.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 15:07:33 +02:00

148 lines
4.7 KiB
Python

"""Postgres test engine on the existing Dev instance.
Two Compose Postgres instances exist: Dev and Prod. Tests use the Dev
instance, database `kansho_test` beside `kansho_dev`. That is not a third
server. The suite drops and recreates `public` on the test database only,
so personal Dev/Prod journals are not wiped.
"""
from __future__ import annotations
import os
import sys
LIVE_DB_NAMES = frozenset(
{
"kansho",
"kansho_dev",
"postgres",
"template0",
"template1",
}
)
def _backend() -> str:
return (os.environ.get("KANSHO_DB_BACKEND") or "").strip().lower()
def _db_name() -> str:
return (os.environ.get("DB_NAME") or "").strip()
def is_postgres_test_database() -> bool:
if _backend() not in {"postgres", "postgresql", "pg"}:
return False
name = _db_name().lower()
if not name or name in LIVE_DB_NAMES:
return False
return name.endswith("_test")
def prepare_test_env() -> None:
"""Fail-closed defaults. Do not keep Compose provider keys or leftover fakes."""
os.environ["KANSHO_PROVIDER_KEY"] = ""
os.environ["KANSHO_DETECT_PROVIDER_KEY"] = ""
os.environ.pop("KANSHO_DB_PATH", None)
os.environ.pop("KANSHO_FAKE_PROVIDER", None)
os.environ.pop("KANSHO_FAKE_DETECT", None)
def apply_module_env(source) -> None:
"""Restore per-file env so pytest does not leak fakes/keys across scripts."""
from pathlib import Path
prepare_test_env()
text = Path(source).read_text(encoding="utf-8")
if 'os.environ["KANSHO_FAKE_PROVIDER"] = "1"' in text or "os.environ['KANSHO_FAKE_PROVIDER'] = '1'" in text:
os.environ["KANSHO_FAKE_PROVIDER"] = "1"
if (
'os.environ["KANSHO_FAKE_DETECT"] = "1"' in text
or "os.environ['KANSHO_FAKE_DETECT'] = '1'" in text
or 'os.environ.setdefault("KANSHO_FAKE_DETECT", "1")' in text
):
os.environ["KANSHO_FAKE_DETECT"] = "1"
def _require_test_database() -> None:
if is_postgres_test_database():
return
backend = _backend()
if backend not in {"postgres", "postgresql", "pg"}:
raise SystemExit(
"Backend-Tests laufen gegen PostgreSQL (KANSHO_DB_BACKEND=postgres), "
"dieselbe Engine wie Dev und Prod. SQLite-Testdateien sind abgelöst. "
"Gitea nutzt auf der Dev-Postgres die Datenbank kansho_test "
"(neben kansho_dev, keine dritte Instanz)."
)
name = _db_name().lower()
if not name:
raise SystemExit(
"DB_NAME fehlt. Tests nutzen auf der Dev-Postgres die Datenbank kansho_test, "
"nicht kansho_dev."
)
raise SystemExit(
f"DB_NAME={_db_name()!r} ist für Tests gesperrt. "
"Die Suite setzt das Schema zurück und darf daher nicht kansho oder kansho_dev treffen."
)
def reset_postgres_schema() -> None:
import psycopg
from db_init import mark_schema_dirty
from sql_compat import postgres_connect_kwargs
kwargs = postgres_connect_kwargs()
if "conninfo" in kwargs:
conn = psycopg.connect(kwargs["conninfo"], autocommit=True)
else:
conn = psycopg.connect(autocommit=True, **kwargs)
try:
conn.execute("DROP SCHEMA IF EXISTS public CASCADE")
conn.execute("CREATE SCHEMA public")
conn.execute("GRANT ALL ON SCHEMA public TO PUBLIC")
conn.execute("GRANT ALL ON SCHEMA public TO CURRENT_USER")
finally:
conn.close()
mark_schema_dirty()
def reset_postgres_data() -> None:
"""Clear rows on kansho_test without reloading schema.sql."""
import psycopg
from sql_compat import postgres_connect_kwargs
kwargs = postgres_connect_kwargs()
if "conninfo" in kwargs:
conn = psycopg.connect(kwargs["conninfo"], autocommit=True)
else:
conn = psycopg.connect(autocommit=True, **kwargs)
try:
rows = conn.execute(
"""
SELECT tablename FROM pg_tables
WHERE schemaname = 'public' AND tablename <> 'schema_migrations'
"""
).fetchall()
names = [row[0] for row in rows]
if names:
joined = ", ".join('"' + name.replace('"', '""') + '"' for name in names)
conn.execute(f"TRUNCATE TABLE {joined} RESTART IDENTITY CASCADE")
finally:
conn.close()
from db import refresh_runtime_seed
refresh_runtime_seed()
def configure_test_engine() -> None:
"""Reset kansho_test. pytest uses the fixture in tests/conftest.py instead."""
prepare_test_env()
_require_test_database()
try:
reset_postgres_schema()
except Exception as exc: # noqa: BLE001 — fail before the suite touches a live DB
print(f"Postgres-Testschema konnte nicht zurückgesetzt werden: {exc}", file=sys.stderr)
raise SystemExit(1) from exc