diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/invalid_models_tests/test_deprecated_fields.py | 3 | ||||
| -rw-r--r-- | tests/postgres_tests/test_app_installed_check.py | 142 | ||||
| -rwxr-xr-x | tests/runtests.py | 1 |
3 files changed, 145 insertions, 1 deletions
diff --git a/tests/invalid_models_tests/test_deprecated_fields.py b/tests/invalid_models_tests/test_deprecated_fields.py index 65f65e7528..e3c7d2e12f 100644 --- a/tests/invalid_models_tests/test_deprecated_fields.py +++ b/tests/invalid_models_tests/test_deprecated_fields.py @@ -3,7 +3,7 @@ from unittest import skipUnless from django.core import checks from django.db import connection, models from django.test import SimpleTestCase -from django.test.utils import isolate_apps +from django.test.utils import isolate_apps, modify_settings @isolate_apps("invalid_models_tests") @@ -87,6 +87,7 @@ class DeprecatedFieldsTests(SimpleTestCase): ) @skipUnless(connection.vendor == "postgresql", "PostgreSQL specific SQL") + @modify_settings(INSTALLED_APPS={"append": "django.contrib.postgres"}) def test_postgres_ci_fields_deprecated(self): from django.contrib.postgres.fields import ( ArrayField, diff --git a/tests/postgres_tests/test_app_installed_check.py b/tests/postgres_tests/test_app_installed_check.py new file mode 100644 index 0000000000..95315384e6 --- /dev/null +++ b/tests/postgres_tests/test_app_installed_check.py @@ -0,0 +1,142 @@ +from django.core import checks +from django.db import models +from django.test import modify_settings +from django.test.utils import isolate_apps + +from . import PostgreSQLTestCase +from .fields import ( + BigIntegerRangeField, + DateRangeField, + DateTimeRangeField, + DecimalRangeField, + HStoreField, + IntegerRangeField, + SearchVectorField, +) +from .models import IntegerArrayModel, NestedIntegerArrayModel, PostgreSQLModel + +try: + from django.contrib.postgres.constraints import ExclusionConstraint + from django.contrib.postgres.fields.ranges import RangeOperators + from django.contrib.postgres.indexes import GinIndex, PostgresIndex + from django.contrib.postgres.search import SearchQueryField +except ImportError: + pass + + +@isolate_apps("postgres_tests") +class TestPostgresAppInstalledCheck(PostgreSQLTestCase): + + def _make_error(self, obj, klass_name): + """Helper to create postgres.E005 error for specific objects.""" + return checks.Error( + "'django.contrib.postgres' must be in INSTALLED_APPS in order to " + f"use {klass_name}.", + obj=obj, + id="postgres.E005", + ) + + def assert_model_check_errors(self, model_class, expected_errors): + errors = model_class.check(databases=self.databases) + self.assertEqual(errors, []) + with modify_settings(INSTALLED_APPS={"remove": "django.contrib.postgres"}): + errors = model_class.check(databases=self.databases) + self.assertEqual(errors, expected_errors) + + def test_indexes(self): + class IndexModel(PostgreSQLModel): + field = models.IntegerField() + + class Meta: + indexes = [ + PostgresIndex(fields=["id"], name="postgres_index_test"), + GinIndex(fields=["field"], name="gin_index_test"), + ] + + self.assert_model_check_errors( + IndexModel, + [ + self._make_error(IndexModel, "PostgresIndex"), + self._make_error(IndexModel, "GinIndex"), + ], + ) + + def test_exclusion_constraint(self): + class ExclusionModel(PostgreSQLModel): + value = models.IntegerField() + + class Meta: + constraints = [ + ExclusionConstraint( + name="exclude_equal", + expressions=[("value", RangeOperators.EQUAL)], + ) + ] + + self.assert_model_check_errors( + ExclusionModel, [self._make_error(ExclusionModel, "ExclusionConstraint")] + ) + + def test_array_field(self): + field = IntegerArrayModel._meta.get_field("field") + self.assert_model_check_errors( + IntegerArrayModel, + [self._make_error(field, "ArrayField")], + ) + + def test_nested_array_field(self): + """Inner ArrayField does not cause a postgres.E001 error.""" + field = NestedIntegerArrayModel._meta.get_field("field") + self.assert_model_check_errors( + NestedIntegerArrayModel, + [ + self._make_error(field, "ArrayField"), + ], + ) + + def test_hstore_field(self): + class HStoreFieldModel(PostgreSQLModel): + field = HStoreField() + + field = HStoreFieldModel._meta.get_field("field") + self.assert_model_check_errors( + HStoreFieldModel, + [ + self._make_error(field, "HStoreField"), + ], + ) + + def test_range_fields(self): + class RangeFieldsModel(PostgreSQLModel): + int_range = IntegerRangeField() + bigint_range = BigIntegerRangeField() + decimal_range = DecimalRangeField() + datetime_range = DateTimeRangeField() + date_range = DateRangeField() + + expected_errors = [ + self._make_error(field, field.__class__.__name__) + for field in [ + RangeFieldsModel._meta.get_field("int_range"), + RangeFieldsModel._meta.get_field("bigint_range"), + RangeFieldsModel._meta.get_field("decimal_range"), + RangeFieldsModel._meta.get_field("datetime_range"), + RangeFieldsModel._meta.get_field("date_range"), + ] + ] + self.assert_model_check_errors(RangeFieldsModel, expected_errors) + + def test_search_vector_field(self): + class SearchModel(PostgreSQLModel): + search_vector = SearchVectorField() + search_query = SearchQueryField() + + vector_field = SearchModel._meta.get_field("search_vector") + query_field = SearchModel._meta.get_field("search_query") + self.assert_model_check_errors( + SearchModel, + [ + self._make_error(vector_field, "SearchVectorField"), + self._make_error(query_field, "SearchQueryField"), + ], + ) diff --git a/tests/runtests.py b/tests/runtests.py index e9052ca4a9..ceb88853b7 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -247,6 +247,7 @@ def setup_collect_tests(start_at, start_after, test_labels=None): settings.LOGGING = log_config settings.SILENCED_SYSTEM_CHECKS = [ "fields.W342", # ForeignKey(unique=True) -> OneToOneField + "postgres.E005", # django.contrib.postgres must be installed to use feature. ] # Load all the ALWAYS_INSTALLED_APPS. |
