Skip to content

test: fail db_session teardown when the outer transaction was closed - #44

Merged
lesnik512 merged 1 commit into
mainfrom
test/loud-teardown-on-closed-transaction
Oct 4, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
test/loud-teardown-on-closed-transaction

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Closes #23

What changed

db_session's teardown in tests/conftest.py used to roll back only if connection.in_transaction():. If something had committed the outer test transaction (for example a session built without join_transaction_mode="create_savepoint"), the rollback was skipped, the test's writes stayed in the database for later tests, and nothing said so.

Teardown now checks transaction.is_active on the outer transaction itself:

  • If it is still active, it is rolled back, same as before.
  • If it is not, pytest.fail reports that the outer transaction was committed instead of nesting a savepoint and points at join_transaction_mode="create_savepoint". The test shows up as an error in teardown.
  • Closing the connection, disposing the engine and resetting the DI override now sit in an inner finally, so they run on the failing path too.

I checked transaction.is_active instead of keeping connection.in_transaction() on purpose. After the outer transaction is committed, any later statement on that connection autobegins a new transaction, so in_transaction() would be true again even though the original writes were already committed. Looking at the transaction object covers that case as well.

create_session and the production code are unchanged.

Test

tests/test_db_session_fixture.py uses pytester (enabled through pytest_plugins = ["pytester"] in that module) to run an inner pytest session in-process. The inner file imports the real db_session, di_container and app fixtures from tests.conftest, so it runs against the same container database, and coverage of the teardown branch is attributed to tests/conftest.py. The inner session:

  1. commits the outer transaction through a join_transaction_mode="control_fully" session that runs a statement on db_session.bind;
  2. in a second test, asserts that the connection captured in step 1 is closed, which shows cleanup still ran after teardown failed.

The outer test expects 2 passed and 1 error, plus the failure message.

Test results

  • Before the fix (original conftest.py, new test): 1 failed. The inner run reported 2 passed, errors: 0 where 1 was expected, so teardown was silent.
  • After the fix: tests/test_db_session_fixture.py gives 1 passed.
  • Full just test: 111 passed in 37.53s, coverage 100.00%. No existing test trips the new check, which confirms that nothing in the suite closes the outer transaction.
  • just lint: eof-fixer and ruff format left all files unchanged, and ruff check and ty check both reported "All checks passed!".

The order-dependent isolation tests in tests/test_main.py are #19 and are not touched here.

@lesnik512
lesnik512 merged commit 0049001 into main Oct 4, 2026
4 checks passed
@lesnik512
lesnik512 deleted the test/loud-teardown-on-closed-transaction branch October 4, 2026 10:07
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.

Per-test rollback is fail-silent on an unexpected commit

1 participant