Skip to content

refactor: extract test-transaction seam from production session#28

Merged
lesnik512 merged 1 commit into
mainfrom
extract-test-transaction-seam
Jun 26, 2026
Merged

refactor: extract test-transaction seam from production session#28
lesnik512 merged 1 commit into
mainfrom
extract-test-transaction-seam

Conversation

@lesnik512

Copy link
Copy Markdown
Member

What

CustomAsyncSession existed for one reason: so the per-test rollback worked. Its close() became a no-op (expunge_all) when the session was bound to a connection — i.e. a test concern leaking into the production data-access module (app/resources/db.py).

This removes it. Test-transaction ownership now lives where it belongs (the db_session fixture), using SQLAlchemy 2.0's native join_transaction_mode="create_savepoint".

How

With create_savepoint, each session owns its own savepoint. Advanced-alchemy's auto_commit releases that savepoint while the fixture's outer real transaction survives and is rolled back at the end of each test. This obsoletes both the close() override and the begin_nested() that the old conditional_savepoint default required.

The kwarg is inert in production: it only takes effect when the session is bound to a connection already in a transaction, which production never does (it binds to an engine).

Changes

  • app/resources/db.py — delete CustomAsyncSession; create_session returns a plain AsyncSession(..., join_transaction_mode="create_savepoint") (commented to explain the prod-inert rationale).
  • tests/conftest.py — drop connection.begin_nested(); the fixture's polyfactory session takes the same mode.

Production session has no test branch any more; per-request-session fidelity is preserved (the fixture still overrides database_engine → connection, so each request builds its own session).

Verification

  • just test → 19 passed, 100% coverage. Isolation is exercised: test_get_decks_empty / test_get_cards_empty assert emptiness and would fail if a prior test's writes leaked.
  • ruff format / ruff check / ty check clean.

🤖 Generated with Claude Code

CustomAsyncSession existed only so the per-test rollback worked: its
close() became a no-op when bound to a connection. That is a test
concern living in the production data-access module.

Replace the hack with SQLAlchemy 2.0's join_transaction_mode="create_savepoint".
Each session owns its savepoint, so auto_commit releases a savepoint while
the fixture's outer transaction survives and is rolled back per test. The
kwarg is inert in production (the session binds to an engine, never an
in-transaction connection).

Production session is now a plain AsyncSession with no test branch; the
conftest fixture drops begin_nested() and owns the savepoint lifecycle via
the same mode.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lesnik512 lesnik512 merged commit b97078e into main Jun 26, 2026
2 checks passed
@lesnik512 lesnik512 deleted the extract-test-transaction-seam branch June 26, 2026 09:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant