Files
cleveragents-core/scripts/create_template_db.py
T
brent.edwards 6da625d509 perf(tests): reduce per-feature startup cost with shared fixtures and lazy imports
Replace per-scenario Alembic migration runs (~0.5-3s × 25 migrations)
with a pre-migrated template SQLite database copied in ~1ms:

- New scripts/create_template_db.py creates a fully-migrated SQLite file
  using Base.metadata.create_all() + alembic stamp (34 tables, ~5ms).
- noxfile.py unit_tests and coverage_report sessions generate the
  template before test execution, propagating CLEVERAGENTS_TEMPLATE_DB
  env var to all behave-parallel workers.
- features/environment.py before_all() installs a monkey-patch on
  MigrationRunner.init_or_upgrade that copies the template for fresh
  scenario temp DBs (cleveragents_* / cleveragents_test_* prefix),
  falling through to real migrations for :memory:, existing files,
  non-SQLite, and custom URLs used by migration-runner unit tests.

Quick wins:
- cli_streaming_steps.py: sleep(0.5) → sleep(0.05) in wait-for-completion
- cli_streaming.feature: remove redundant Background re-declaration in
  scenario 7 (already inherited from Feature-level Background)

Part of #478. Closes #483.
2026-03-01 03:39:30 +00:00

69 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""Create a pre-migrated template SQLite database for fast test setup.
Instead of running 25 Alembic migrations per scenario (~0.5-3s each),
tests can copy this template file (~1ms) and get an identical schema.
Usage:
python scripts/create_template_db.py [output_path]
Default output: build/.template-migrated.db
"""
import sys
from pathlib import Path
# Ensure src/ is importable
src_dir = Path(__file__).resolve().parent.parent / "src"
sys.path.insert(0, str(src_dir))
def create_template(output_path: str = "build/.template-migrated.db") -> None:
"""Create a fully-migrated template SQLite database.
Uses Base.metadata.create_all() to create all tables in a single DDL
batch (~5ms), then stamps the alembic_version table with the head
revision so MigrationRunner sees no pending migrations.
"""
from alembic import command
from alembic.config import Config
from alembic.script import ScriptDirectory
from sqlalchemy import create_engine
from cleveragents.infrastructure.database.models import Base
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
# Remove existing template so we always create fresh
if out.exists():
out.unlink()
db_url = f"sqlite:///{out.resolve()}"
engine = create_engine(db_url, connect_args={"check_same_thread": False})
# Create all 33 tables in one fast DDL batch
Base.metadata.create_all(engine)
# Stamp alembic_version with the head revision so MigrationRunner
# sees the database as fully migrated (no pending migrations).
alembic_ini = Path(__file__).resolve().parent.parent / "alembic.ini"
cfg = Config(str(alembic_ini))
sd = ScriptDirectory.from_config(cfg)
head = sd.get_current_head()
if head is None:
msg = "No Alembic revisions found — cannot stamp template database."
raise RuntimeError(msg)
with engine.connect() as conn:
cfg.attributes["connection"] = conn
command.stamp(cfg, head)
conn.commit()
engine.dispose()
if __name__ == "__main__":
path = sys.argv[1] if len(sys.argv) > 1 else "build/.template-migrated.db"
create_template(path)