Skip to content

Don't run _pre_setup() twice for transactional tests - #1293

Open
vokracko wants to merge 2 commits into
pytest-dev:mainfrom
vokracko:fix-repeated-pre-setup
Open

Don't run _pre_setup() twice for transactional tests#1293
vokracko wants to merge 2 commits into
pytest-dev:mainfrom
vokracko:fix-repeated-pre-setup

Conversation

@vokracko

@vokracko vokracko commented Aug 1, 2026

Copy link
Copy Markdown

Since Django 5.2, TransactionTestCase.setUpClass() calls cls._pre_setup() eagerly and sets _pre_setup_ran_eagerly so that whoever drives the test case can skip its own call, the way unittest.TestCase.run() does. _django_db_helper() calls setUpClass() and then test_case._pre_setup() unconditionally, so every django_db(transaction=True) test has its fixtures set up twice: the serialized_rollback restore, the fixtures load and the sequence reset all run again. On a suite of 121 transactional tests that was 567s against 445s, roughly 1s per test.

The first commit adds a test recording which frames call _pre_setup(). It passes on current main and asserts the duplicate: a plain django_db test records one call, a transactional one records setUpClass and then a second call from _django_db_helper().

The second commit consumes _pre_setup_ran_eagerly in _django_db_helper() and flips that assertion to the single call. Verified against Django 5.2; the eager call is unchanged on 6.0 and main.

vokracko added 2 commits July 30, 2026 16:34
Records who calls _pre_setup(). A plain django_db test is set up once, by us. A
django_db(transaction=True) test is set up twice: TransactionTestCase.setUpClass()
runs _pre_setup() eagerly and we then run it again.
TransactionTestCase.setUpClass() runs _pre_setup() eagerly and flags it in
_pre_setup_ran_eagerly, which unittest.TestCase.run() clears instead of setting
the test up again. We drive the test case ourselves, so do the same.

Repeating _pre_setup() redid the whole fixture setup - serialized rollback
restore, fixtures, sequence reset - on every transactional test. With
available_apps it also sent setting_changed(enter=True) and post_migrate twice
against the single exit in _post_teardown.
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