Skip to content

test: prove db_session rollback with one self-contained test - #45

Merged
lesnik512 merged 1 commit into
mainfrom
test/self-contained-rollback-proof
Oct 4, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
test/self-contained-rollback-proof

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Closes #19

What changed

  • tests/conftest.py: the body of the db_session fixture moved unchanged into an async context manager, rolled_back_db_session(di_container). db_session now just enters it and yields the session, so every other test gets the same setup and teardown as before. The if connection.in_transaction(): guard is untouched (that's Per-test rollback is fail-silent on an unexpected commit #23). The lines were moved without edits so the conflict with Per-test rollback is fail-silent on an unexpected commit #23 stays small.
  • tests/test_main.py: removed the order-dependent pair test_db_session_insert_is_visible_within_test and test_db_session_rolls_back_between_tests. They're replaced by one test, test_db_session_teardown_rolls_back_committed_writes. It writes a user through rolled_back_db_session and calls commit() (not just flush). It then checks the row is visible inside the block, so the test can't pass on a table nothing wrote to. After the context manager's teardown runs, it queries from a fresh engine and connection and expects no row.

Why

test_db_session_rolls_back_between_tests only proved anything when it ran after its partner. Run on its own with -k, it passed against an empty table that nothing had written to. The new test does the write, the teardown and the check itself, so it doesn't depend on test order.

About the acceptance criterion

The brief said the test must fail "if the teardown rollback is removed". As worded, no test can meet that. The next line of teardown, await connection.close(), rolls back any open transaction anyway, because SQLAlchemy resets the connection when it goes back to the pool. Deleting the explicit await transaction.rollback() therefore changes nothing a test can see. I tried it, and the new test still passes. What the criterion meant was: the test fails if teardown lets the outer transaction persist.

There's no red-before-green here either. The fixture already rolls back correctly, so the new test passes the moment it's written. The evidence that it can catch a leak comes from the mutations below.

Test results

All runs use just test. The subset runs add --no-cov, because the 100% coverage gate fails on any subset.

  • Old test_db_session_rolls_back_between_tests alone with -k: 1 passed, against a table nothing had written to.
  • New test alone (-k teardown_rolls_back): 1 passed.
  • Mutation, explicit rollback deleted: new test still passes, because close() rolls back.
  • Mutation, transaction.rollback() changed to transaction.commit(): new test fails alone with assert [1] == [].
  • Full just test: 109 passed, coverage 100.00%. That's 110 before, minus the 2 removed tests, plus the 1 new one.
  • just lint: eof-fixer, ruff format, ruff check and ty check all clean, no auto-fixes.

@lesnik512
lesnik512 force-pushed the test/self-contained-rollback-proof branch from 4281a20 to 391b2db Compare October 4, 2026 10:06
@lesnik512
lesnik512 merged commit dd2c3ba into main Oct 4, 2026
4 checks passed
@lesnik512
lesnik512 deleted the test/self-contained-rollback-proof branch October 4, 2026 10:08
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.

Isolation test pair is order-dependent

1 participant