Files
django-migration-linter/tests/functional/test_data_migrations.py
T

314 lines
11 KiB
Python

import os
import unittest
from django.conf import settings
from django.db import migrations
from django_migration_linter import MigrationLinter
from tests import fixtures
class DataMigrationDetectionTestCase(unittest.TestCase):
def setUp(self, *args, **kwargs):
self.test_project_path = os.path.dirname(settings.BASE_DIR)
self.linter = MigrationLinter(
self.test_project_path,
include_apps=fixtures.DATA_MIGRATIONS,
)
def test_reverse_data_migration(self):
self.assertEqual(0, self.linter.nb_warnings)
reverse_migration = self.linter.migration_loader.disk_migrations[
("app_data_migrations", "0002_missing_reverse")
]
self.linter.lint_migration(reverse_migration)
self.assertEqual(1, self.linter.nb_warnings)
self.assertFalse(self.linter.has_errors)
def test_reverse_data_migration_ignore(self):
reverse_migration = self.linter.migration_loader.disk_migrations[
("app_data_migrations", "0003_incorrect_arguments")
]
self.linter.lint_migration(reverse_migration)
self.assertEqual(1, self.linter.nb_warnings)
self.assertFalse(self.linter.has_errors)
def test_exclude_warning_from_test(self):
self.linter = MigrationLinter(
self.test_project_path,
include_apps=fixtures.DATA_MIGRATIONS,
exclude_migration_tests=("RUNPYTHON_REVERSIBLE",),
)
reverse_migration = self.linter.migration_loader.disk_migrations[
("app_data_migrations", "0002_missing_reverse")
]
self.linter.lint_migration(reverse_migration)
self.assertEqual(0, self.linter.nb_warnings)
self.assertEqual(1, self.linter.nb_valid)
self.assertFalse(self.linter.has_errors)
def test_all_warnings_as_errors(self):
self.linter = MigrationLinter(
self.test_project_path,
include_apps=fixtures.DATA_MIGRATIONS,
all_warnings_as_errors=True,
)
reverse_migration = self.linter.migration_loader.disk_migrations[
("app_data_migrations", "0003_incorrect_arguments")
]
self.linter.lint_migration(reverse_migration)
self.assertEqual(0, self.linter.nb_warnings)
self.assertEqual(1, self.linter.nb_erroneous)
self.assertTrue(self.linter.has_errors)
def test_warnings_as_errors_tests_matches(self):
self.linter = MigrationLinter(
self.test_project_path,
include_apps=fixtures.DATA_MIGRATIONS,
warnings_as_errors_tests=["RUNPYTHON_ARGS_NAMING_CONVENTION"],
)
reverse_migration = self.linter.migration_loader.disk_migrations[
("app_data_migrations", "0003_incorrect_arguments")
]
self.linter.lint_migration(reverse_migration)
self.assertEqual(0, self.linter.nb_warnings)
self.assertEqual(1, self.linter.nb_erroneous)
self.assertTrue(self.linter.has_errors)
def test_warnings_as_errors_tests_no_match(self):
self.linter = MigrationLinter(
self.test_project_path,
include_apps=fixtures.DATA_MIGRATIONS,
warnings_as_errors_tests=[
"RUNPYTHON_MODEL_IMPORT",
"RUNPYTHON_MODEL_VARIABLE_NAME",
],
)
reverse_migration = self.linter.migration_loader.disk_migrations[
("app_data_migrations", "0003_incorrect_arguments")
]
self.linter.lint_migration(reverse_migration)
self.assertEqual(1, self.linter.nb_warnings)
self.assertEqual(0, self.linter.nb_erroneous)
self.assertFalse(self.linter.has_errors)
class DataMigrationModelImportTestCase(unittest.TestCase):
def test_missing_get_model_import(self):
def incorrect_importing_model_forward(apps, schema_editor):
from tests.test_project.app_data_migrations.models import MyModel
MyModel.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_import_issues(
incorrect_importing_model_forward
)
self.assertEqual(1, len(issues))
def test_correct_get_model_import(self):
def correct_importing_model_forward(apps, schema_editor):
MyModel = apps.get_model("app_data_migrations", "MyModel")
MyVeryLongLongLongModel = apps.get_model(
"app_data_migrations", "MyVeryLongLongLongModel"
)
MultiLineModel = apps.get_model(
"app_data_migrations",
"MultiLineModel",
)
MyModel.objects.filter(id=1).first()
MyVeryLongLongLongModel.objects.filter(id=1).first()
MultiLineModel.objects.all()
issues = MigrationLinter.get_runpython_model_import_issues(
correct_importing_model_forward
)
self.assertEqual(0, len(issues))
def test_not_overlapping_model_name(self):
"""
Correct for the import error, but should raise a warning
"""
def forward_method(apps, schema_editor):
User = apps.get_model("auth", "CustomUserModel")
User.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_import_issues(forward_method)
self.assertEqual(0, len(issues))
def test_correct_one_param_get_model_import(self):
def forward_method(apps, schema_editor):
User = apps.get_model("auth.User")
User.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_import_issues(forward_method)
self.assertEqual(0, len(issues))
def test_not_overlapping_one_param(self):
"""
Not an error, but should raise a warning
"""
def forward_method(apps, schema_editor):
User = apps.get_model("auth.CustomUserModel")
User.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_import_issues(forward_method)
self.assertEqual(0, len(issues))
class DataMigrationModelVariableNamingTestCase(unittest.TestCase):
def test_same_variable_name(self):
def forward_op(apps, schema_editor):
MyModel = apps.get_model("app", "MyModel")
MyModel.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(0, len(issues))
def test_same_variable_name_multiline(self):
def forward_op(apps, schema_editor):
MyModelVeryLongLongLongLongLong = apps.get_model(
"app", "MyModelVeryLongLongLongLongLong"
)
MyModelVeryLongLongLongLongLong.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(0, len(issues))
def test_same_variable_name_multiline2(self):
def forward_op(apps, schema_editor):
MyModelVeryLongLongLongLongLong = apps.get_model(
"app_name_longlonglonglongapp",
"MyModelVeryLongLongLongLongLong",
)
MyModelVeryLongLongLongLongLong.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(0, len(issues))
def test_different_variable_name(self):
def forward_op(apps, schema_editor):
some_model = apps.get_model("app", "MyModel")
some_model.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(1, len(issues))
def test_diff_variable_name_multiline(self):
def forward_op(apps, schema_editor):
MyModelVeryLongLongLongLongLongNot = apps.get_model(
"app", "MyModelVeryLongLongLongLongLong"
)
MyModelVeryLongLongLongLongLongNot.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(1, len(issues))
def test_diff_variable_name_multiline2(self):
def forward_op(apps, schema_editor):
MyModelVeryLongLongLongLongLongNot = apps.get_model(
"app_name_longlonglonglongapp",
"MyModelVeryLongLongLongLongLong",
)
MyModelVeryLongLongLongLongLongNot.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(1, len(issues))
def test_same_variable_name_one_param(self):
def forward_op(apps, schema_editor):
MyModel = apps.get_model("app.MyModel")
MyModel.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(0, len(issues))
def test_different_variable_name_one_param(self):
def forward_op(apps, schema_editor):
mymodel = apps.get_model("app.MyModel")
mymodel.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(1, len(issues))
def test_correct_variable_name_one_param_multiline(self):
def forward_op(apps, schema_editor):
AVeryLongModelName = apps.get_model(
"quite_long_app_name.AVeryLongModelName"
)
AVeryLongModelName.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(0, len(issues))
def test_different_variable_name_one_param_multiline(self):
def forward_op(apps, schema_editor):
m = apps.get_model(
"quite_long_app_name_name_name.AVeryLongModelNameNameName"
)
m.objects.filter(id=1).first()
issues = MigrationLinter.get_runpython_model_variable_naming_issues(forward_op)
self.assertEqual(1, len(issues))
class RunSQLMigrationTestCase(unittest.TestCase):
def setUp(self):
test_project_path = os.path.dirname(settings.BASE_DIR)
self.linter = MigrationLinter(
test_project_path,
include_apps=fixtures.DATA_MIGRATIONS,
)
def test_missing_reserve_migration(self):
runsql = migrations.RunSQL("sql;")
error, ignored, warning = self.linter.lint_runsql(runsql)
self.assertEqual("RUNSQL_REVERSIBLE", warning[0]["code"])
def test_sql_linting_error(self):
runsql = migrations.RunSQL("ALTER TABLE t DROP COLUMN t;")
error, ignored, warning = self.linter.lint_runsql(runsql)
self.assertEqual("DROP_COLUMN", error[0]["code"])
def test_sql_linting_error_array(self):
runsql = migrations.RunSQL(
["ALTER TABLE t DROP COLUMN c;", "ALTER TABLE t RENAME COLUMN c;"]
)
error, ignored, warning = self.linter.lint_runsql(runsql)
self.assertEqual("DROP_COLUMN", error[0]["code"])
self.assertEqual("RENAME_COLUMN", error[1]["code"])
def test_sql_linting_error_args(self):
runsql = migrations.RunSQL([("ALTER TABLE %s DROP COLUMN %s;", ("t", "c"))])
error, ignored, warning = self.linter.lint_runsql(runsql)
self.assertEqual("DROP_COLUMN", error[0]["code"])