Add tests for the makemigrations override
This commit is contained in:
1 parent
34a6d9d47e
commit
c2c26ae106
11 files changed
+273
No files matched your search
@@ -0,0 +1,195 @@
|
||||
import io
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from contextlib import contextmanager
|
||||
from importlib import import_module
|
||||
|
||||
if sys.version_info >= (3, 3):
|
||||
import unittest.mock as mock
|
||||
else:
|
||||
import mock
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.core.management import call_command
|
||||
from django.test import TransactionTestCase
|
||||
from django.test.utils import extend_sys_path, override_settings
|
||||
from django.utils.module_loading import module_dir
|
||||
|
||||
MAKEMIGRATIONS_INSTALLED_APPS = settings.INSTALLED_APPS + [
|
||||
"tests.test_project.makemigrations_correct_migration_missing",
|
||||
"tests.test_project.makemigrations_backward_incompatible_migration_missing",
|
||||
]
|
||||
|
||||
|
||||
@override_settings(INSTALLED_APPS=MAKEMIGRATIONS_INSTALLED_APPS)
|
||||
class BaseMakeMigrationsTestCase(TransactionTestCase):
|
||||
@contextmanager
|
||||
def temporary_migration_module(self, app_label="migrations", module=None):
|
||||
"""
|
||||
Shamelessly copied from Django.
|
||||
See django.tests.migrations.test_base.MigrationTestBase.temporary_migration_module
|
||||
|
||||
Allows testing management commands in a temporary migrations module.
|
||||
|
||||
Wrap all invocations to makemigrations and squashmigrations with this
|
||||
context manager in order to avoid creating migration files in your
|
||||
source tree inadvertently.
|
||||
"""
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
target_dir = tempfile.mkdtemp(dir=temp_dir)
|
||||
with open(os.path.join(target_dir, "__init__.py"), "w"):
|
||||
pass
|
||||
target_migrations_dir = os.path.join(target_dir, "migrations")
|
||||
|
||||
if module is None:
|
||||
module = apps.get_app_config(app_label).name + ".migrations"
|
||||
|
||||
try:
|
||||
source_migrations_dir = module_dir(import_module(module))
|
||||
except (ImportError, ValueError):
|
||||
pass
|
||||
else:
|
||||
shutil.copytree(source_migrations_dir, target_migrations_dir)
|
||||
|
||||
with extend_sys_path(temp_dir):
|
||||
new_module = os.path.basename(target_dir) + ".migrations"
|
||||
with self.settings(MIGRATION_MODULES={app_label: new_module}):
|
||||
yield target_migrations_dir
|
||||
|
||||
|
||||
class MakeMigrationsCorrectTestCase(BaseMakeMigrationsTestCase):
|
||||
available_apps = [
|
||||
"django_migration_linter",
|
||||
"tests.test_project.makemigrations_correct_migration_missing",
|
||||
]
|
||||
databases = {"default", "postgresql"}
|
||||
|
||||
def test_correct_linted_makemigrations(self):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_correct_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command("makemigrations", lint=True, database="postgresql", stdout=out)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertTrue(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertIn("Linting for 'makemigrations_correct_migration_missing':", output)
|
||||
|
||||
@override_settings(MIGRATION_LINTER_OVERRIDE_MAKEMIGRATIONS=True)
|
||||
def test_correct_linted_makemigrations_using_settings(self):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_correct_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command("makemigrations", database="postgresql", stdout=out)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertTrue(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertIn("Linting for 'makemigrations_correct_migration_missing':", output)
|
||||
|
||||
def test_no_linting_when_no_option(self):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_correct_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command("makemigrations", database="postgresql", stdout=out)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertTrue(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertNotIn("Linting", output)
|
||||
|
||||
def test_correct_linted_makemigrations_dry_run(self):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_correct_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command(
|
||||
"makemigrations",
|
||||
lint=True,
|
||||
database="postgresql",
|
||||
dry_run=True,
|
||||
stdout=out,
|
||||
)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertFalse(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertNotIn("Linting", output)
|
||||
|
||||
|
||||
@override_settings(MIGRATION_LINTER_OVERRIDE_MAKEMIGRATIONS=True)
|
||||
class MakeMigrationsBackwardIncompatibleTestCase(BaseMakeMigrationsTestCase):
|
||||
available_apps = [
|
||||
"django_migration_linter",
|
||||
"tests.test_project.makemigrations_backward_incompatible_migration_missing",
|
||||
]
|
||||
databases = {"default", "sqlite", "mysql", "postgresql"}
|
||||
|
||||
def test_backward_incompatible_migration_postgresql(self):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_backward_incompatible_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command(
|
||||
"makemigrations", interactive=False, database="postgresql", stdout=out
|
||||
)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertFalse(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertIn("Deleted", output)
|
||||
|
||||
def test_backward_incompatible_migration_mysql(self):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_backward_incompatible_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command(
|
||||
"makemigrations", interactive=False, database="mysql", stdout=out
|
||||
)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertFalse(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertIn("Deleted", output)
|
||||
|
||||
def test_backward_incompatible_migration_sqlite(self):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_backward_incompatible_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command(
|
||||
"makemigrations", interactive=False, database="sqlite", stdout=out
|
||||
)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertFalse(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertIn("Deleted", output)
|
||||
|
||||
@mock.patch("builtins.input", return_value="yes")
|
||||
def test_backward_incompatible_migration_interactive_keep_migration(self, *args):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_backward_incompatible_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command(
|
||||
"makemigrations", interactive=True, database="postgresql", stdout=out
|
||||
)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertTrue(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertNotIn("Deleted", output)
|
||||
|
||||
@mock.patch("builtins.input", return_value="no")
|
||||
def test_backward_incompatible_migration_interactive_delete_migration(self, *args):
|
||||
out = io.StringIO()
|
||||
with self.temporary_migration_module(
|
||||
app_label="makemigrations_backward_incompatible_migration_missing"
|
||||
) as migration_dir:
|
||||
call_command(
|
||||
"makemigrations", interactive=True, database="postgresql", stdout=out
|
||||
)
|
||||
new_migration_file = os.path.join(migration_dir, "0002_a_new_field.py")
|
||||
self.assertFalse(os.path.exists(new_migration_file))
|
||||
output = out.getvalue()
|
||||
self.assertIn("Deleted", output)
|
||||
Whitespace-only changes.
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MakemigrationsBackwardIncompatibleMigrationMissingConfig(AppConfig):
|
||||
name = "tests.test_project.makemigrations_backward_incompatible_migration_missing"
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 2.2 on 2020-06-26 17:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="A",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("x", models.IntegerField()),
|
||||
],
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,6 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class A(models.Model):
|
||||
x = models.IntegerField()
|
||||
new_field = models.CharField(null=False, default="empty", max_length=255)
|
||||
Whitespace-only changes.
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MakemigrationsCorrectMigrationMissingConfig(AppConfig):
|
||||
name = "tests.test_project.makemigrations_correct_migration_missing"
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 2.2 on 2020-06-26 15:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="A",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("x", models.IntegerField()),
|
||||
],
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,6 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class A(models.Model):
|
||||
x = models.IntegerField()
|
||||
new_field = models.CharField(null=True, max_length=255)
|
||||
Reference in new issue
Block a user