properly reset databases on tests teardown
See original GitHub issueCurrently multiple databases are supported by creating instance of Migrator
for each database, but only default database is cleaned at the end of test - https://github.com/wemake-services/django-test-migrations/blob/master/django_test_migrations/migrator.py#L77
Also using migrate
management command is not the best idea when it comes to performance, because there is no need to apply all unapplied migrations just before the next test, which should start with clean state.
Django’s TestCase
uses flush
management command to clean databases after test.
We need to reuse Django’s code responsible for cleaning database on test teardown (or establish our own way to do that) and fix Migrator.reset()
method to clean Migrator.database
instead of default one.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:22 (9 by maintainers)
Top GitHub Comments
@asfaltboy I have digged into Django’s migrations deeper and had some answers for your problem, but also many new concerns that I’d like to discuss.
This issue is related to how Django built migrations’ plan. In 0.2.0 migration’s test setup/assert/teardown flow looks like below:
(NOTE: in both cases, before running tests, django calls
migrate
command to migrate all forwards).migrate_from
- migrating backward tomigrate_from
unapplies only migrations that are higher in migrations plan thanmigrate_from
migrate_to
on themmigrate_to
migrate
command to migrate all forwardsFlow implemented in #46 looks like below:
django_migrations
tablemigrate_from
- here migrations are applied on clean database and everything goes forward, so only migrations that are dependencies ofmigrate_from
will be appliedmigrate_to
on themmigrate_to
migrate
command to migrate all forwardsLet’s imagine we have 2 apps:
some_app
andother_app
.some_app
has following migrations:0009_do_some_stuff
- all migrations from initial to this one are not dependent in anyway onother_app
0010_do_some_stuff_dependent_on_other_app
- this is the first migration that depends onother_app
other_app
is self-sufficient when it comes to migrations (like e.g.django.contrib.sites
) and it’s much lower in migrations plan thansome_app
.Then let’s imagine we are testing migration 0010, so
migrate_from
is 0009 andmigrate_to
is 0010. Let’s focus on preparation step where some testing db models instances are created.In
0.2.0
we will have access to models fromother_app
, because we are migrating backward and only migrations higher in the plan thanmigrate_before
will be unapplied But in #46 we won’t be able to accessother_app
models, because we are migrating only forward tomigrate_from
which is not dependent onother_app
.The problem is more trickier than I thought 😦 Solution from
0.2.0
is not ideal because it’s not similar to how we apply migrations on production, however it’s hard to implement production like solution for migration’s test flow.Yesterday I was experimenting with creating migrations plan manually starting from one of:
migrate_to
targetsand then truncating such plan on
migrate_before
migrations, to make it more like on production (avoid migrating backwards) and preserve behaviour from0.2.0
. It’s quite “magical”/complicated solution, however I can clean it and push (but give me few days) so we can discuss it.Hi @skarzi thanks for investing much time into this, this is indeed a tough issue to solve.
I was thinking about this a bit more, and it seems that, typically, the reason data migrations fail to be re-applied in teardown is due to “primary key sequence” mismatch. I see that in your PR #46 you implement
get_django_migrations_table_sequences
to keep track of the ids … do you think it’s possible to simplify this by using django.test.TransactionTestCase.reset_sequences (also supported in pytest-django)?Note that I tried testing #46 locally and I’m having issues with dependency migrations not being applied (while they are being applied in current 0.2.0 ). I was not able to overcome this by specifying all the related apps migrations (I gave up mid-way), but even if I did it would not be ideal. How come this is not the same behavior as on 0.2.0, I thought #46 only fixes the teardown?