diff --git a/docs/subsystems/schema-migrations.md b/docs/subsystems/schema-migrations.md index cb645c9ac0..831421b193 100644 --- a/docs/subsystems/schema-migrations.md +++ b/docs/subsystems/schema-migrations.md @@ -103,4 +103,24 @@ few properties: tables are done in large-scale systems, since it ensures that the system can continue running happily during the migration. +## Automated testing for migrations + +Zulip has support for writing automated tests for your database +migrations, using the `MigrationsTestCase` test class. This system is +inspired by [a great blog post][django-migration-test-blog-post] on +the subject. + +We have integrated this system with our test framework so that if you +use the `use_db_models` decorator, you can use some helper methods +from `test_classes.py` and friends from inside the tests (which is +normally not possible in Django's migrations framework). + +If you find yourself writing logic in a `RunPython` migration, we +highly recommend adding a test using this framework. We may end up +deleting the test later (they can get slow once they are many +migrations away from current), but it can help prevent disaster where +an incorrect migration messes up a database in a way that's impossible +to undo without going to backups. + +[django-migration-test-blog-post]: https://www.caktusgroup.com/blog/2016/02/02/writing-unit-tests-django-migrations/ [migrations-non-atomic]: https://docs.djangoproject.com/en/1.10/howto/writing-migrations/#non-atomic-migrations diff --git a/zerver/lib/test_classes.py b/zerver/lib/test_classes.py index 684f3114c5..244582442b 100644 --- a/zerver/lib/test_classes.py +++ b/zerver/lib/test_classes.py @@ -714,7 +714,11 @@ class WebhookTestCase(ZulipTestCase): self.assertEqual(msg.content, expected_message) class MigrationsTestCase(ZulipTestCase): - + """ + Test class for database migrations inspired by this blog post: + https://www.caktusgroup.com/blog/2016/02/02/writing-unit-tests-django-migrations/ + Documented at https://zulip.readthedocs.io/en/latest/subsystems/schema-migrations.html + """ @property def app(self) -> str: return apps.get_containing_app_config(type(self).__module__).name diff --git a/zerver/tests/test_migrations_0145.py b/zerver/tests/test_migrations.py similarity index 87% rename from zerver/tests/test_migrations_0145.py rename to zerver/tests/test_migrations.py index f018f978b3..25dc8d9f1c 100644 --- a/zerver/tests/test_migrations_0145.py +++ b/zerver/tests/test_migrations.py @@ -1,3 +1,10 @@ +# These are tests for Zulip's database migrations. System documented at: +# https://zulip.readthedocs.io/en/latest/subsystems/schema-migrations.html +# +# You can also read +# https://www.caktusgroup.com/blog/2016/02/02/writing-unit-tests-django-migrations/ +# to get a tutorial on the framework that inspired this feature. + from zerver.lib.test_classes import MigrationsTestCase from zerver.lib.test_helpers import use_db_models, make_client from django.utils.timezone import now as timezone_now @@ -45,6 +52,7 @@ class EmojiName2IdTestCase(MigrationsTestCase): self.assertEqual(realm_emoji_reactions_count, 1) def test_tags_migrated(self) -> None: + """Test runs after the migration, and verifies the data was migrated correctly""" Reaction = self.apps.get_model('zerver', 'Reaction') RealmEmoji = self.apps.get_model('zerver', 'RealmEmoji')