summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHasan Ramezani <hasan.r67@gmail.com>2020-12-10 18:00:57 +0100
committerGitHub <noreply@github.com>2020-12-10 18:00:57 +0100
commit275dd4ebbabbbe758c7219a3d666953d5a7b072f (patch)
treed0534f7047f9ba43525368eda2c121df54801d4c
parent5ce31d6a7142ca8c76d6b52fa42b3406b9a8ff48 (diff)
Fixed #32178 -- Allowed database backends to skip tests and mark expected failures.
Co-authored-by: Tim Graham <timograham@gmail.com>
-rw-r--r--django/contrib/gis/db/backends/mysql/features.py14
-rw-r--r--django/contrib/gis/db/backends/spatialite/features.py10
-rw-r--r--django/db/backends/base/creation.py28
-rw-r--r--django/db/backends/base/features.py7
-rw-r--r--django/db/backends/mysql/features.py46
-rw-r--r--django/db/backends/oracle/features.py22
-rw-r--r--django/db/backends/postgresql/features.py6
-rw-r--r--django/db/backends/sqlite3/features.py31
-rw-r--r--docs/releases/3.2.txt8
-rw-r--r--tests/aggregation/tests.py5
-rw-r--r--tests/annotations/tests.py21
-rw-r--r--tests/backends/base/test_creation.py62
-rw-r--r--tests/db_functions/comparison/test_greatest.py3
-rw-r--r--tests/db_functions/comparison/test_least.py3
-rw-r--r--tests/db_functions/text/test_sha224.py2
-rw-r--r--tests/expressions/tests.py2
-rw-r--r--tests/expressions_window/tests.py7
-rw-r--r--tests/gis_tests/geoapp/tests.py3
-rw-r--r--tests/gis_tests/geogapp/tests.py3
-rw-r--r--tests/indexes/tests.py3
-rw-r--r--tests/model_fields/test_charfield.py5
-rw-r--r--tests/model_fields/test_decimalfield.py4
-rw-r--r--tests/model_fields/test_integerfield.py3
-rw-r--r--tests/model_fields/test_jsonfield.py6
-rw-r--r--tests/model_fields/test_textfield.py5
-rw-r--r--tests/queries/test_explain.py3
-rwxr-xr-xtests/runtests.py5
-rw-r--r--tests/schema/tests.py16
-rw-r--r--tests/servers/test_liveserverthread.py2
29 files changed, 248 insertions, 87 deletions
diff --git a/django/contrib/gis/db/backends/mysql/features.py b/django/contrib/gis/db/backends/mysql/features.py
index 63e2fa1dd3..72e59d2278 100644
--- a/django/contrib/gis/db/backends/mysql/features.py
+++ b/django/contrib/gis/db/backends/mysql/features.py
@@ -24,3 +24,17 @@ class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
def supports_geometry_field_unique_index(self):
# Not supported in MySQL since https://dev.mysql.com/worklog/task/?id=11808
return self.connection.mysql_is_mariadb
+
+ @cached_property
+ def django_test_skips(self):
+ skips = super().django_test_skips
+ if (
+ not self.connection.mysql_is_mariadb and
+ self.connection.mysql_version < (8, 0, 0)
+ ):
+ skips.update({
+ 'MySQL < 8 gives different results.': {
+ 'gis_tests.geoapp.tests.GeoLookupTest.test_disjoint_lookup',
+ },
+ })
+ return skips
diff --git a/django/contrib/gis/db/backends/spatialite/features.py b/django/contrib/gis/db/backends/spatialite/features.py
index 6e5bd95179..947d874b30 100644
--- a/django/contrib/gis/db/backends/spatialite/features.py
+++ b/django/contrib/gis/db/backends/spatialite/features.py
@@ -12,3 +12,13 @@ class DatabaseFeatures(BaseSpatialFeatures, SQLiteDatabaseFeatures):
@cached_property
def supports_area_geodetic(self):
return bool(self.connection.ops.lwgeom_version())
+
+ @cached_property
+ def django_test_skips(self):
+ skips = super().django_test_skips
+ skips.update({
+ "SpatiaLite doesn't support distance lookups with Distance objects.": {
+ 'gis_tests.geogapp.tests.GeographyTest.test02_distance_lookup',
+ },
+ })
+ return skips
diff --git a/django/db/backends/base/creation.py b/django/db/backends/base/creation.py
index 0099dd18bb..81cb34bd9f 100644
--- a/django/db/backends/base/creation.py
+++ b/django/db/backends/base/creation.py
@@ -1,12 +1,14 @@
import os
import sys
from io import StringIO
+from unittest import expectedFailure, skip
from django.apps import apps
from django.conf import settings
from django.core import serializers
from django.db import router
from django.db.transaction import atomic
+from django.utils.module_loading import import_string
# The prefix to put on the default database name when creating
# the test database.
@@ -92,6 +94,9 @@ class BaseDatabaseCreation:
# Ensure a connection for the side effect of initializing the test database.
self.connection.ensure_connection()
+ if os.environ.get('RUNNING_DJANGOS_TEST_SUITE') == 'true':
+ self.mark_expected_failures_and_skips()
+
return test_database_name
def set_as_test_mirror(self, primary_settings_dict):
@@ -293,6 +298,29 @@ class BaseDatabaseCreation:
cursor.execute("DROP DATABASE %s"
% self.connection.ops.quote_name(test_database_name))
+ def mark_expected_failures_and_skips(self):
+ """
+ Mark tests in Django's test suite which are expected failures on this
+ database and test which should be skipped on this database.
+ """
+ for test_name in self.connection.features.django_test_expected_failures:
+ test_case_name, _, test_method_name = test_name.rpartition('.')
+ test_app = test_name.split('.')[0]
+ # Importing a test app that isn't installed raises RuntimeError.
+ if test_app in settings.INSTALLED_APPS:
+ test_case = import_string(test_case_name)
+ test_method = getattr(test_case, test_method_name)
+ setattr(test_case, test_method_name, expectedFailure(test_method))
+ for reason, tests in self.connection.features.django_test_skips.items():
+ for test_name in tests:
+ test_case_name, _, test_method_name = test_name.rpartition('.')
+ test_app = test_name.split('.')[0]
+ # Importing a test app that isn't installed raises RuntimeError.
+ if test_app in settings.INSTALLED_APPS:
+ test_case = import_string(test_case_name)
+ test_method = getattr(test_case, test_method_name)
+ setattr(test_case, test_method_name, skip(reason)(test_method))
+
def sql_table_creation_suffix(self):
"""
SQL to append to the end of the test table creation statements.
diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py
index 125d52a21f..885033361a 100644
--- a/django/db/backends/base/features.py
+++ b/django/db/backends/base/features.py
@@ -323,6 +323,13 @@ class BaseDatabaseFeatures:
'swedish_ci': None # Swedish case-insensitive.
}
+ # A set of dotted paths to tests in Django's test suite that are expected
+ # to fail on this database.
+ django_test_expected_failures = {}
+ # A map of reasons to sets of dotted paths to tests in Django's test suite
+ # that should be skipped for this database.
+ django_test_skips = {}
+
def __init__(self, connection):
self.connection = connection
diff --git a/django/db/backends/mysql/features.py b/django/db/backends/mysql/features.py
index 3713df549b..72fff72648 100644
--- a/django/db/backends/mysql/features.py
+++ b/django/db/backends/mysql/features.py
@@ -51,6 +51,52 @@ class DatabaseFeatures(BaseDatabaseFeatures):
}
@cached_property
+ def django_test_skips(self):
+ skips = {
+ "This doesn't work on MySQL.": {
+ 'db_functions.comparison.test_greatest.GreatestTests.test_coalesce_workaround',
+ 'db_functions.comparison.test_least.LeastTests.test_coalesce_workaround',
+ },
+ 'Running on MySQL requires utf8mb4 encoding (#18392).': {
+ 'model_fields.test_textfield.TextFieldTests.test_emoji',
+ 'model_fields.test_charfield.TestCharField.test_emoji',
+ },
+ }
+ if 'ONLY_FULL_GROUP_BY' in self.connection.sql_mode:
+ skips.update({
+ 'GROUP BY optimization does not work properly when '
+ 'ONLY_FULL_GROUP_BY mode is enabled on MySQL, see #31331.': {
+ 'aggregation.tests.AggregateTestCase.test_aggregation_subquery_annotation_multivalued',
+ 'annotations.tests.NonAggregateAnnotationTestCase.test_annotation_aggregate_with_m2o',
+ },
+ })
+ if (
+ self.connection.mysql_is_mariadb and
+ (10, 4, 3) < self.connection.mysql_version < (10, 5, 2)
+ ):
+ skips.update({
+ 'https://jira.mariadb.org/browse/MDEV-19598': {
+ 'schema.tests.SchemaTests.test_alter_not_unique_field_to_primary_key',
+ },
+ })
+ if (
+ self.connection.mysql_is_mariadb and
+ (10, 4, 12) < self.connection.mysql_version < (10, 5)
+ ):
+ skips.update({
+ 'https://jira.mariadb.org/browse/MDEV-22775': {
+ 'schema.tests.SchemaTests.test_alter_pk_with_self_referential_field',
+ },
+ })
+ if not self.supports_explain_analyze:
+ skips.update({
+ 'MariaDB and MySQL >= 8.0.18 specific.': {
+ 'queries.test_explain.ExplainTests.test_mysql_analyze',
+ },
+ })
+ return skips
+
+ @cached_property
def _mysql_storage_engine(self):
"Internal method used in Django tests. Don't rely on this from your code"
return self.connection.mysql_server_data['default_storage_engine']
diff --git a/django/db/backends/oracle/features.py b/django/db/backends/oracle/features.py
index e66c5da09f..2570675809 100644
--- a/django/db/backends/oracle/features.py
+++ b/django/db/backends/oracle/features.py
@@ -72,6 +72,28 @@ class DatabaseFeatures(BaseDatabaseFeatures):
'swedish_ci': 'SWEDISH_CI',
}
+ django_test_skips = {
+ "Oracle doesn't support SHA224.": {
+ 'db_functions.text.test_sha224.SHA224Tests.test_basic',
+ 'db_functions.text.test_sha224.SHA224Tests.test_transform',
+ },
+ "Oracle doesn't support bitwise XOR.": {
+ 'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor',
+ 'expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null',
+ },
+ "Oracle requires ORDER BY in row_number, ANSI:SQL doesn't.": {
+ 'expressions_window.tests.WindowFunctionTests.test_row_number_no_ordering',
+ },
+ 'Raises ORA-00600: internal error code on Oracle 18.': {
+ 'model_fields.test_jsonfield.TestQuerying.test_usage_in_subquery',
+ },
+ }
+ django_test_expected_failures = {
+ # A bug in Django/cx_Oracle with respect to string handling (#23843).
+ 'annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions',
+ 'annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions_can_ref_other_functions',
+ }
+
@cached_property
def introspected_field_types(self):
return {
diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py
index f5f844ca42..84259c0c19 100644
--- a/django/db/backends/postgresql/features.py
+++ b/django/db/backends/postgresql/features.py
@@ -59,6 +59,12 @@ class DatabaseFeatures(BaseDatabaseFeatures):
has_json_operators = True
json_key_contains_list_matching_requires_list = True
+ django_test_skips = {
+ 'opclasses are PostgreSQL only.': {
+ 'indexes.tests.SchemaIndexesNotPostgreSQLTests.test_create_index_ignores_opclasses',
+ },
+ }
+
@cached_property
def test_collations(self):
# PostgreSQL < 10 doesn't support ICU collations.
diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py
index 880d2e50dd..3348256c74 100644
--- a/django/db/backends/sqlite3/features.py
+++ b/django/db/backends/sqlite3/features.py
@@ -51,6 +51,37 @@ class DatabaseFeatures(BaseDatabaseFeatures):
}
@cached_property
+ def django_test_skips(self):
+ skips = {
+ 'SQLite stores values rounded to 15 significant digits.': {
+ 'model_fields.test_decimalfield.DecimalFieldTests.test_fetch_from_db_without_float_rounding',
+ },
+ 'SQLite naively remakes the table on field alteration.': {
+ 'schema.tests.SchemaTests.test_unique_no_unnecessary_fk_drops',
+ 'schema.tests.SchemaTests.test_unique_and_reverse_m2m',
+ 'schema.tests.SchemaTests.test_alter_field_default_doesnt_perform_queries',
+ 'schema.tests.SchemaTests.test_rename_column_renames_deferred_sql_references',
+ },
+ "SQLite doesn't have a constraint.": {
+ 'model_fields.test_integerfield.PositiveIntegerFieldTests.test_negative_values',
+ },
+ }
+ if Database.sqlite_version_info < (3, 27):
+ skips.update({
+ 'Nondeterministic failure on SQLite < 3.27.': {
+ 'expressions_window.tests.WindowFunctionTests.test_subquery_row_range_rank',
+ },
+ })
+ if self.connection.is_in_memory_db():
+ skips.update({
+ "the sqlite backend's close() method is a no-op when using an "
+ "in-memory database": {
+ 'servers.test_liveserverthread.LiveServerThreadTest.test_closes_connections',
+ },
+ })
+ return skips
+
+ @cached_property
def supports_atomic_references_rename(self):
# SQLite 3.28.0 bundled with MacOS 10.15 does not support renaming
# references atomically.
diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt
index d5047dfe60..b155f37e00 100644
--- a/docs/releases/3.2.txt
+++ b/docs/releases/3.2.txt
@@ -197,6 +197,14 @@ CSRF
* ...
+Database backends
+~~~~~~~~~~~~~~~~~
+
+* Third-party database backends can now skip or mark as expected failures
+ tests in Django's test suite using the new
+ ``DatabaseFeatures.django_test_skips`` and
+ ``django_test_expected_failures`` attributes.
+
Decorators
~~~~~~~~~~
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py
index ad4b94a7f9..0bced06ce9 100644
--- a/tests/aggregation/tests.py
+++ b/tests/aggregation/tests.py
@@ -1218,11 +1218,6 @@ class AggregateTestCase(TestCase):
Subquery annotations must be included in the GROUP BY if they use
potentially multivalued relations (contain the LOOKUP_SEP).
"""
- if connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode:
- self.skipTest(
- 'GROUP BY optimization does not work properly when '
- 'ONLY_FULL_GROUP_BY mode is enabled on MySQL, see #31331.'
- )
subquery_qs = Author.objects.filter(
pk=OuterRef('pk'),
book__name=OuterRef('book__name'),
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index cc9bd82656..8337f344ed 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -2,7 +2,6 @@ import datetime
from decimal import Decimal
from django.core.exceptions import FieldDoesNotExist, FieldError
-from django.db import connection
from django.db.models import (
BooleanField, Case, CharField, Count, DateTimeField, DecimalField, Exists,
ExpressionWrapper, F, FloatField, Func, IntegerField, Max,
@@ -20,19 +19,6 @@ from .models import (
)
-def cxOracle_py3_bug(func):
- """
- There's a bug in Django/cx_Oracle with respect to string handling under
- Python 3 (essentially, they treat Python 3 strings as Python 2 strings
- rather than unicode). This makes some tests here fail under Python 3, so
- we mark them as expected failures until someone fixes them in #23843.
- """
- from unittest import expectedFailure
-
- from django.db import connection
- return expectedFailure(func) if connection.vendor == 'oracle' else func
-
-
class NonAggregateAnnotationTestCase(TestCase):
@classmethod
@@ -590,7 +576,6 @@ class NonAggregateAnnotationTestCase(TestCase):
e.id, e.first_name, e.manager, e.random_value, e.last_name, e.age,
e.salary, e.store.name, e.annotated_value))
- @cxOracle_py3_bug
def test_custom_functions(self):
Company(name='Apple', motto=None, ticker_name='APPL', description='Beautiful Devices').save()
Company(name='Django Software Foundation', motto=None, ticker_name=None, description=None).save()
@@ -617,7 +602,6 @@ class NonAggregateAnnotationTestCase(TestCase):
lambda c: (c.name, c.tagline)
)
- @cxOracle_py3_bug
def test_custom_functions_can_ref_other_functions(self):
Company(name='Apple', motto=None, ticker_name='APPL', description='Beautiful Devices').save()
Company(name='Django Software Foundation', motto=None, ticker_name=None, description=None).save()
@@ -770,11 +754,6 @@ class NonAggregateAnnotationTestCase(TestCase):
])
def test_annotation_aggregate_with_m2o(self):
- if connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode:
- self.skipTest(
- 'GROUP BY optimization does not work properly when '
- 'ONLY_FULL_GROUP_BY mode is enabled on MySQL, see #31331.'
- )
qs = Author.objects.filter(age__lt=30).annotate(
max_pages=Case(
When(book_contact_set__isnull=True, then=Value(0)),
diff --git a/tests/backends/base/test_creation.py b/tests/backends/base/test_creation.py
index 3e29961d21..6c98556f1e 100644
--- a/tests/backends/base/test_creation.py
+++ b/tests/backends/base/test_creation.py
@@ -1,5 +1,6 @@
import copy
import datetime
+import os
from unittest import mock
from django.db import DEFAULT_DB_ALIAS, connection, connections
@@ -107,6 +108,22 @@ class TestDbCreationTests(SimpleTestCase):
with mock.patch.object(creation, '_destroy_test_db'):
creation.destroy_test_db(old_database_name, verbosity=0)
+ @mock.patch.dict(os.environ, {'RUNNING_DJANGOS_TEST_SUITE': ''})
+ @mock.patch.object(BaseDatabaseCreation, 'mark_expected_failures_and_skips')
+ def test_mark_expected_failures_and_skips_call(self, mark_expected_failures_and_skips, *mocked_objects):
+ """
+ mark_expected_failures_and_skips() isn't called unless
+ RUNNING_DJANGOS_TEST_SUITE is 'true'.
+ """
+ test_connection = get_connection_copy()
+ creation = test_connection.creation_class(test_connection)
+ if connection.vendor == 'oracle':
+ # Don't close connection on Oracle.
+ creation.connection.close = mock.Mock()
+ with mock.patch.object(creation, '_create_test_db'):
+ creation.create_test_db(verbosity=0, autoclobber=True, serialize=False)
+ self.assertIs(mark_expected_failures_and_skips.called, False)
+
class TestDeserializeDbFromString(TransactionTestCase):
available_apps = ['backends']
@@ -188,3 +205,48 @@ class TestDeserializeDbFromString(TransactionTestCase):
data = connection.creation.serialize_db_to_string()
self.assertIn('"model": "backends.schoolclass"', data)
self.assertIn('"year": 1000', data)
+
+
+class SkipTestClass:
+ def skip_function(self):
+ pass
+
+
+def skip_test_function():
+ pass
+
+
+def expected_failure_test_function():
+ pass
+
+
+class TestMarkTests(SimpleTestCase):
+ def test_mark_expected_failures_and_skips(self):
+ test_connection = get_connection_copy()
+ creation = BaseDatabaseCreation(test_connection)
+ creation.connection.features.django_test_expected_failures = {
+ 'backends.base.test_creation.expected_failure_test_function',
+ }
+ creation.connection.features.django_test_skips = {
+ 'skip test class': {
+ 'backends.base.test_creation.SkipTestClass',
+ },
+ 'skip test function': {
+ 'backends.base.test_creation.skip_test_function',
+ },
+ }
+ creation.mark_expected_failures_and_skips()
+ self.assertIs(
+ expected_failure_test_function.__unittest_expecting_failure__,
+ True,
+ )
+ self.assertIs(SkipTestClass.__unittest_skip__, True)
+ self.assertEqual(
+ SkipTestClass.__unittest_skip_why__,
+ 'skip test class',
+ )
+ self.assertIs(skip_test_function.__unittest_skip__, True)
+ self.assertEqual(
+ skip_test_function.__unittest_skip_why__,
+ 'skip test function',
+ )
diff --git a/tests/db_functions/comparison/test_greatest.py b/tests/db_functions/comparison/test_greatest.py
index ef93d808c2..f11e7b824c 100644
--- a/tests/db_functions/comparison/test_greatest.py
+++ b/tests/db_functions/comparison/test_greatest.py
@@ -1,6 +1,6 @@
from datetime import datetime, timedelta
from decimal import Decimal
-from unittest import skipIf, skipUnless
+from unittest import skipUnless
from django.db import connection
from django.db.models.expressions import RawSQL
@@ -33,7 +33,6 @@ class GreatestTests(TestCase):
articles = Article.objects.annotate(last_updated=Greatest('written', 'published'))
self.assertIsNone(articles.first().last_updated)
- @skipIf(connection.vendor == 'mysql', "This doesn't work on MySQL")
def test_coalesce_workaround(self):
past = datetime(1900, 1, 1)
now = timezone.now()
diff --git a/tests/db_functions/comparison/test_least.py b/tests/db_functions/comparison/test_least.py
index de2c543f0b..e0318e25c6 100644
--- a/tests/db_functions/comparison/test_least.py
+++ b/tests/db_functions/comparison/test_least.py
@@ -1,6 +1,6 @@
from datetime import datetime, timedelta
from decimal import Decimal
-from unittest import skipIf, skipUnless
+from unittest import skipUnless
from django.db import connection
from django.db.models.expressions import RawSQL
@@ -35,7 +35,6 @@ class LeastTests(TestCase):
articles = Article.objects.annotate(first_updated=Least('written', 'published'))
self.assertIsNone(articles.first().first_updated)
- @skipIf(connection.vendor == 'mysql', "This doesn't work on MySQL")
def test_coalesce_workaround(self):
future = datetime(2100, 1, 1)
now = timezone.now()
diff --git a/tests/db_functions/text/test_sha224.py b/tests/db_functions/text/test_sha224.py
index a8291d416c..d2f1d538dc 100644
--- a/tests/db_functions/text/test_sha224.py
+++ b/tests/db_functions/text/test_sha224.py
@@ -20,7 +20,6 @@ class SHA224Tests(TestCase):
Author(alias=None),
])
- @unittest.skipIf(connection.vendor == 'oracle', "Oracle doesn't support SHA224.")
def test_basic(self):
authors = Author.objects.annotate(
sha224_alias=SHA224('alias'),
@@ -37,7 +36,6 @@ class SHA224Tests(TestCase):
],
)
- @unittest.skipIf(connection.vendor == 'oracle', "Oracle doesn't support SHA224.")
def test_transform(self):
with register_lookup(CharField, SHA224):
authors = Author.objects.filter(
diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py
index d8d8370cb3..463150f8a1 100644
--- a/tests/expressions/tests.py
+++ b/tests/expressions/tests.py
@@ -1230,13 +1230,11 @@ class ExpressionOperatorTests(TestCase):
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 1764)
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(61.02, places=2))
- @unittest.skipIf(connection.vendor == 'oracle', "Oracle doesn't support bitwise XOR.")
def test_lefthand_bitwise_xor(self):
Number.objects.update(integer=F('integer').bitxor(48))
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 26)
self.assertEqual(Number.objects.get(pk=self.n1.pk).integer, -26)
- @unittest.skipIf(connection.vendor == 'oracle', "Oracle doesn't support bitwise XOR.")
def test_lefthand_bitwise_xor_null(self):
employee = Employee.objects.create(firstname='John', lastname='Doe')
Employee.objects.update(salary=F('salary').bitxor(48))
diff --git a/tests/expressions_window/tests.py b/tests/expressions_window/tests.py
index 08f215215b..8b1b4a8a3f 100644
--- a/tests/expressions_window/tests.py
+++ b/tests/expressions_window/tests.py
@@ -1,6 +1,6 @@
import datetime
from decimal import Decimal
-from unittest import mock, skipIf
+from unittest import mock
from django.core.exceptions import FieldError
from django.db import NotSupportedError, connection
@@ -150,7 +150,6 @@ class WindowFunctionTests(TestCase):
('Johnson', 'Management', 12),
], lambda entry: (entry.name, entry.department, entry.row_number))
- @skipIf(connection.vendor == 'oracle', "Oracle requires ORDER BY in row_number, ANSI:SQL doesn't")
def test_row_number_no_ordering(self):
"""
The row number window function computes the number based on the order
@@ -633,10 +632,6 @@ class WindowFunctionTests(TestCase):
('Brown', 'Sales', 53000, datetime.date(2009, 9, 1), 148000)
], transform=lambda row: (row.name, row.department, row.salary, row.hire_date, row.sum))
- @skipIf(
- connection.vendor == 'sqlite' and connection.Database.sqlite_version_info < (3, 27),
- 'Nondeterministic failure on SQLite < 3.27.'
- )
def test_subquery_row_range_rank(self):
qs = Employee.objects.annotate(
highest_avg_salary_date=Subquery(
diff --git a/tests/gis_tests/geoapp/tests.py b/tests/gis_tests/geoapp/tests.py
index 350bd04629..94cb4b10de 100644
--- a/tests/gis_tests/geoapp/tests.py
+++ b/tests/gis_tests/geoapp/tests.py
@@ -1,5 +1,4 @@
import tempfile
-import unittest
from io import StringIO
from django.contrib.gis import gdal
@@ -229,8 +228,6 @@ class GeoLookupTest(TestCase):
def test_disjoint_lookup(self):
"Testing the `disjoint` lookup type."
- if mysql and not mariadb and connection.mysql_version < (8, 0, 0):
- raise unittest.SkipTest('MySQL < 8 gives different results.')
ptown = City.objects.get(name='Pueblo')
qs1 = City.objects.filter(point__disjoint=ptown.point)
self.assertEqual(7, qs1.count())
diff --git a/tests/gis_tests/geogapp/tests.py b/tests/gis_tests/geogapp/tests.py
index 507d8a970e..0faf749e14 100644
--- a/tests/gis_tests/geogapp/tests.py
+++ b/tests/gis_tests/geogapp/tests.py
@@ -2,7 +2,7 @@
Tests for geography support in PostGIS
"""
import os
-from unittest import skipIf, skipUnless
+from unittest import skipUnless
from django.contrib.gis.db import models
from django.contrib.gis.db.models.functions import Area, Distance
@@ -22,7 +22,6 @@ class GeographyTest(TestCase):
"Ensure geography features loaded properly."
self.assertEqual(8, City.objects.count())
- @skipIf(spatialite, "SpatiaLite doesn't support distance lookups with Distance objects.")
@skipUnlessDBFeature("supports_distances_lookups", "supports_distance_geodetic")
def test02_distance_lookup(self):
"Testing distance lookup support on non-point geography fields."
diff --git a/tests/indexes/tests.py b/tests/indexes/tests.py
index 3c4541f684..6d01e3b52f 100644
--- a/tests/indexes/tests.py
+++ b/tests/indexes/tests.py
@@ -1,5 +1,5 @@
import datetime
-from unittest import skipIf, skipUnless
+from unittest import skipUnless
from django.db import connection
from django.db.models import CASCADE, ForeignKey, Index, Q
@@ -89,7 +89,6 @@ class SchemaIndexesTests(TestCase):
)
-@skipIf(connection.vendor == 'postgresql', 'opclasses are PostgreSQL only')
class SchemaIndexesNotPostgreSQLTests(TransactionTestCase):
available_apps = ['indexes']
diff --git a/tests/model_fields/test_charfield.py b/tests/model_fields/test_charfield.py
index 0e6109c860..17c230c776 100644
--- a/tests/model_fields/test_charfield.py
+++ b/tests/model_fields/test_charfield.py
@@ -1,7 +1,5 @@
-from unittest import skipIf
-
from django.core.exceptions import ValidationError
-from django.db import connection, models
+from django.db import models
from django.test import SimpleTestCase, TestCase
from .models import Post
@@ -22,7 +20,6 @@ class TestCharField(TestCase):
def test_lookup_integer_in_charfield(self):
self.assertEqual(Post.objects.filter(title=9).count(), 0)
- @skipIf(connection.vendor == 'mysql', 'Running on MySQL requires utf8mb4 encoding (#18392)')
def test_emoji(self):
p = Post.objects.create(title='Smile 😀', body='Whatever.')
p.refresh_from_db()
diff --git a/tests/model_fields/test_decimalfield.py b/tests/model_fields/test_decimalfield.py
index 729b5e570a..2d96cfd437 100644
--- a/tests/model_fields/test_decimalfield.py
+++ b/tests/model_fields/test_decimalfield.py
@@ -1,9 +1,8 @@
-import unittest
from decimal import Decimal
from django.core import validators
from django.core.exceptions import ValidationError
-from django.db import connection, models
+from django.db import models
from django.test import TestCase
from .models import BigD, Foo
@@ -66,7 +65,6 @@ class DecimalFieldTests(TestCase):
bd = BigD.objects.get(pk=bd.pk)
self.assertEqual(bd.d, Decimal('12.9'))
- @unittest.skipIf(connection.vendor == 'sqlite', 'SQLite stores values rounded to 15 significant digits.')
def test_fetch_from_db_without_float_rounding(self):
big_decimal = BigD.objects.create(d=Decimal('.100000000000000000000000000005'))
big_decimal.refresh_from_db()
diff --git a/tests/model_fields/test_integerfield.py b/tests/model_fields/test_integerfield.py
index 13b18d967c..af5a9f2e35 100644
--- a/tests/model_fields/test_integerfield.py
+++ b/tests/model_fields/test_integerfield.py
@@ -1,5 +1,3 @@
-import unittest
-
from django.core import validators
from django.core.exceptions import ValidationError
from django.db import IntegrityError, connection, models
@@ -192,7 +190,6 @@ class PositiveIntegerFieldTests(IntegerFieldTests):
else models.IntegerField
)
- @unittest.skipIf(connection.vendor == 'sqlite', "SQLite doesn't have a constraint.")
def test_negative_values(self):
p = PositiveIntegerModel.objects.create(value=0)
p.value = models.F('value') - 1
diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py
index 321826814b..f71efcff61 100644
--- a/tests/model_fields/test_jsonfield.py
+++ b/tests/model_fields/test_jsonfield.py
@@ -1,6 +1,6 @@
import operator
import uuid
-from unittest import mock, skipIf
+from unittest import mock
from django import forms
from django.core import serializers
@@ -719,10 +719,6 @@ class TestQuerying(TestCase):
objs_with_value,
)
- @skipIf(
- connection.vendor == 'oracle',
- 'Raises ORA-00600: internal error code on Oracle 18.',
- )
def test_usage_in_subquery(self):
self.assertSequenceEqual(
NullableJSONModel.objects.filter(
diff --git a/tests/model_fields/test_textfield.py b/tests/model_fields/test_textfield.py
index f0bce822a4..dd5f5a5280 100644
--- a/tests/model_fields/test_textfield.py
+++ b/tests/model_fields/test_textfield.py
@@ -1,7 +1,5 @@
-from unittest import skipIf
-
from django import forms
-from django.db import connection, models
+from django.db import models
from django.test import SimpleTestCase, TestCase
from .models import Post
@@ -32,7 +30,6 @@ class TextFieldTests(TestCase):
def test_lookup_integer_in_textfield(self):
self.assertEqual(Post.objects.filter(body=24).count(), 0)
- @skipIf(connection.vendor == 'mysql', 'Running on MySQL requires utf8mb4 encoding (#18392)')
def test_emoji(self):
p = Post.objects.create(title='Whatever', body='Smile 😀.')
p.refresh_from_db()
diff --git a/tests/queries/test_explain.py b/tests/queries/test_explain.py
index a8ecd752cd..ba835afb74 100644
--- a/tests/queries/test_explain.py
+++ b/tests/queries/test_explain.py
@@ -80,9 +80,6 @@ class ExplainTests(TestCase):
@unittest.skipUnless(connection.vendor == 'mysql', 'MariaDB and MySQL >= 8.0.18 specific.')
def test_mysql_analyze(self):
- # Inner skip to avoid module level query for MySQL version.
- if not connection.features.supports_explain_analyze:
- raise unittest.SkipTest('MariaDB and MySQL >= 8.0.18 specific.')
qs = Tag.objects.filter(name='test')
with CaptureQueriesContext(connection) as captured_queries:
qs.explain(analyze=True)
diff --git a/tests/runtests.py b/tests/runtests.py
index ad282ce782..ba7c163bf6 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -254,6 +254,10 @@ def setup(verbosity, test_labels, parallel, start_at, start_after):
apps.set_installed_apps(settings.INSTALLED_APPS)
+ # Set an environment variable that other code may consult to see if
+ # Django's own test suite is running.
+ os.environ['RUNNING_DJANGOS_TEST_SUITE'] = 'true'
+
return state
@@ -267,6 +271,7 @@ def teardown(state):
# FileNotFoundError at the end of a test run (#27890).
from multiprocessing.util import _finalizer_registry
_finalizer_registry.pop((-100, 0), None)
+ del os.environ['RUNNING_DJANGOS_TEST_SUITE']
def actual_test_processes(parallel):
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index 9b8e27e207..7740065d31 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -729,12 +729,6 @@ class SchemaTests(TransactionTestCase):
Foo.objects.create()
def test_alter_not_unique_field_to_primary_key(self):
- if (
- connection.vendor == 'mysql' and
- connection.mysql_is_mariadb and
- (10, 4, 3) < connection.mysql_version < (10, 5, 2)
- ):
- self.skipTest('https://jira.mariadb.org/browse/MDEV-19598')
# Create the table.
with connection.schema_editor() as editor:
editor.create_model(Author)
@@ -1957,7 +1951,6 @@ class SchemaTests(TransactionTestCase):
TagUniqueRename._meta.db_table = old_table_name
@isolate_apps('schema')
- @unittest.skipIf(connection.vendor == 'sqlite', 'SQLite naively remakes the table on field alteration.')
@skipUnlessDBFeature('supports_foreign_keys')
def test_unique_no_unnecessary_fk_drops(self):
"""
@@ -1991,7 +1984,6 @@ class SchemaTests(TransactionTestCase):
self.assertEqual(len(cm.records), 1)
@isolate_apps('schema')
- @unittest.skipIf(connection.vendor == 'sqlite', 'SQLite remakes the table on field alteration.')
def test_unique_and_reverse_m2m(self):
"""
AlterField can modify a unique field when there's a reverse M2M
@@ -2759,7 +2751,6 @@ class SchemaTests(TransactionTestCase):
if connection.features.can_introspect_default:
self.assertIsNone(field.default)
- @unittest.skipIf(connection.vendor == 'sqlite', 'SQLite naively remakes the table on field alteration.')
def test_alter_field_default_doesnt_perform_queries(self):
"""
No queries are performed if a field default changes and the field's
@@ -3041,12 +3032,6 @@ class SchemaTests(TransactionTestCase):
Changing the primary key field name of a model with a self-referential
foreign key (#26384).
"""
- if (
- connection.vendor == 'mysql' and
- connection.mysql_is_mariadb and
- (10, 4, 12) < connection.mysql_version < (10, 5)
- ):
- self.skipTest('https://jira.mariadb.org/browse/MDEV-22775')
with connection.schema_editor() as editor:
editor.create_model(Node)
old_field = Node._meta.get_field('node_id')
@@ -3203,7 +3188,6 @@ class SchemaTests(TransactionTestCase):
self.assertIs(statement.references_table('schema_author'), False)
self.assertIs(statement.references_table('schema_book'), False)
- @unittest.skipIf(connection.vendor == 'sqlite', 'SQLite naively remakes the table on field alteration.')
def test_rename_column_renames_deferred_sql_references(self):
with connection.schema_editor() as editor:
editor.create_model(Author)
diff --git a/tests/servers/test_liveserverthread.py b/tests/servers/test_liveserverthread.py
index 9762b53791..a2af459edc 100644
--- a/tests/servers/test_liveserverthread.py
+++ b/tests/servers/test_liveserverthread.py
@@ -13,8 +13,6 @@ class LiveServerThreadTest(TestCase):
def test_closes_connections(self):
conn = connections[DEFAULT_DB_ALIAS]
- if conn.vendor == 'sqlite' and conn.is_in_memory_db():
- self.skipTest("the sqlite backend's close() method is a no-op when using an in-memory database")
# Pass a connection to the thread to check they are being closed.
connections_override = {DEFAULT_DB_ALIAS: conn}