-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tearDown does not delete the test data before to migrate back to latest #33
Comments
tearDown
does not delete the test data before to migrate back to latest
tearDown
does not delete the test data before to migrate back to latest
That's true, and it's definitely a shame that this situation would upset all future tests. However - in principle, at least - clearing the data could also be considered a "bad state" for some future migrations if they assume certain things do exist from previous migrations. (I wouldn't describe doing that as "best practice" necessarily, but I'm sure it will happen.) So if So I think I'm inclined to say that it would be more surprising (and harder to workaround) if You can probably just do something like: class MigrationFailTestCase(MigrationTest):
def test_fail_hard(self):
# put data in bad state
MyModel.objects.create(state='bad')
with self.assertRaises(Exception):
self.run_migration()
# put data back into sane state, eg:
MyModel.objects.all().delete() or maybe even class MigrationFailTestCase(MigrationTest)
def tearDown(self):
call_command('flush')
super().tearDown() would work for your case. See what Hope that's helpful. |
The workaround you propose is fine when you expect a migration to fail, but if someone did not do that and something goes wrong in a migration test the failure has potentially catastrophic side effects on other tests. It is pretty hard to debug, the call stack does not relates to "tearDown" since the migration is called from "call_command". Good tests should revert the state of any resources they use so I am sure rollbacking automatically the test data should be a good thing. Don't you think? |
If there was a way of saying "restore DB state such that it will pass all future migrations", then absolutely. But I am not convinced that such a thing exists. And we're using As for debugging, it might help if tearDown did a try-except around the
Absolutely. But we're already through the proverbial looking-glass here. MigrationTest is really abusing Django's TestCase. If we really want guaranteed restoration, then the safest way of getting the db back on track would be to drop it and rebuild which I would love, but then the tests would take a stupidly long time. Relatedly, Django's docs mention something similar in the warning in this section and suggests using So I think the options are:
|
I like Option 1 but could it be this option instead of 2/3?: Run a |
So you mean make the savepoint just after we run the migrations down in Or make the savepoint just before we run the migrations down in The second option has the benefit that removes the tearDown migration completely, but has the problem that it will not work at all on mysql. But the first option may well work, and I'd be interested to know if it works for the situation you encountered if you can try it out. |
I run tests with I did some tests with rollback and it does work inside a transaction block. See documentation So I made this decorator that actually works pretty well.
When I decorate my test function with it the issue in the |
Of course this decorator is only "safe" when testing a custom migrations that does not change the schema. I suppose the Django migration table is also rolled back but the schema remain changed. This could leave the DB in a pretty bad state. |
Here's a test for the
|
@plumdog I was thinking to create a PR(with tests) for this decorator. Does that make sense to you? |
Yeah, it looks like a neat solution to me. |
@plumdog, I created the pull request. However I couldn't make it to work with django < 1.7. |
PR merged. Version 0.0.13 now on PyPI. Thanks for contributing! |
Let assume we want a migration to rather fail when the data is not correct (Ex: require human intervention to fix the data) and we want to test that.
self.run_migration()
The teardown of
MigrationTest
will run the migration again to restore the previous state of the migration which will fail since the test data will be still there.The workaround is to do the teardown of the data ourself but it is impractical, I would assume
MigrationTest
would clear the test data before to roll the migrations.The text was updated successfully, but these errors were encountered: