diff --git a/pyproject.toml b/pyproject.toml index d6c8b870eb..530346c6d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -115,7 +115,7 @@ max_supported_python = "3.14" keep_full_version = true [tool.pytest.ini_options] -addopts = "--tb=short --strict-markers -ra" +addopts = "--tb=short --strict-markers -ra --no-migrations" testpaths = [ "tests" ] markers = [ "requires_postgres: marks tests as requiring a PostgreSQL database backend", diff --git a/rest_framework/test.py b/rest_framework/test.py index ae347ec002..675f789068 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -1,11 +1,14 @@ # Note that we import as `DjangoRequestFactory` and `DjangoClient` in order # to make it harder for the user to import the wrong thing without realizing. import io +from contextlib import contextmanager from importlib import import_module from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.handlers.wsgi import WSGIHandler +from django.core.signals import request_finished, request_started +from django.db import close_old_connections from django.test import override_settings, testcases from django.test.client import Client as DjangoClient from django.test.client import ClientHandler @@ -22,6 +25,21 @@ def force_authenticate(request, user=None, token=None): request._force_auth_token = token +@contextmanager +def _keep_connections_open(): + """ + Prevent Django from closing the database connection while a request + is dispatched, matching the behavior of Django's ClientHandler. + """ + request_started.disconnect(close_old_connections) + request_finished.disconnect(close_old_connections) + try: + yield + finally: + request_started.connect(close_old_connections) + request_finished.connect(close_old_connections) + + if requests is not None: class HeaderDict(requests.packages.urllib3._collections.HTTPHeaderDict): def get_all(self, key, default): @@ -90,7 +108,8 @@ def start_response(wsgi_status, wsgi_headers, exc_info=None): # Make the outgoing request via WSGI. environ = self.get_environ(request) - wsgi_response = self.app(environ, start_response) + with _keep_connections_open(): + wsgi_response = self.app(environ, start_response) # Build the underlying urllib3.HTTPResponse raw_kwargs['body'] = io.BytesIO(b''.join(wsgi_response)) diff --git a/tests/conftest.py b/tests/conftest.py index db1b79254e..9257fb05de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,36 @@ import dj_database_url import django import pytest +from django.apps import apps from django.core import management +from django.core.management.color import no_style +from django.db import connection +from django.test import TestCase, TransactionTestCase + + +@pytest.fixture(autouse=True) +def _reset_sequences(request): + """Reset all database sequences so PKs start from 1 in each test. + + PostgreSQL sequences are non-transactional and persist across + TestCase's transaction rollbacks. This fixture ensures every test + gets predictable PKs starting from 1 regardless of execution order. + No-op on SQLite and skipped for tests that don't use the database. + """ + if connection.vendor != 'postgresql': + return + # Only run for tests that actually have database access. + if not (request.cls and issubclass(request.cls, (TestCase, TransactionTestCase))): + if 'db' not in request.fixturenames and 'transactional_db' not in request.fixturenames: + return + + table_names = set(connection.introspection.table_names()) + models = [m for m in apps.get_models() if m._meta.db_table in table_names] + sql_list = connection.ops.sequence_reset_sql(no_style(), models) + if sql_list: + with connection.cursor() as cursor: + for sql in sql_list: + cursor.execute(sql) def pytest_addoption(parser): diff --git a/tests/test_filters.py b/tests/test_filters.py index f797a01eb7..36ffc08aea 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -45,7 +45,7 @@ def test_filter_queryset_raises_error(self): class SearchFilterModel(models.Model): - title = models.CharField(max_length=20) + title = models.CharField(max_length=25) text = models.CharField(max_length=100) diff --git a/tests/test_relations_hyperlink.py b/tests/test_relations_hyperlink.py index f48bb98af8..4be0b41bdc 100644 --- a/tests/test_relations_hyperlink.py +++ b/tests/test_relations_hyperlink.py @@ -81,7 +81,7 @@ def setUp(self): source.targets.add(target) def test_relative_hyperlinks(self): - queryset = ManyToManySource.objects.all() + queryset = ManyToManySource.objects.order_by('pk') serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': None}) expected = [ {'url': '/manytomanysource/1/', 'name': 'source-1', 'targets': ['/manytomanytarget/1/']}, @@ -92,7 +92,7 @@ def test_relative_hyperlinks(self): assert serializer.data == expected def test_many_to_many_retrieve(self): - queryset = ManyToManySource.objects.all() + queryset = ManyToManySource.objects.order_by('pk') serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']}, @@ -109,7 +109,7 @@ def test_many_to_many_retrieve_prefetch_related(self): serializer.data def test_reverse_many_to_many_retrieve(self): - queryset = ManyToManyTarget.objects.all() + queryset = ManyToManyTarget.objects.order_by('pk') serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']}, @@ -128,7 +128,7 @@ def test_many_to_many_update(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = ManyToManySource.objects.all() + queryset = ManyToManySource.objects.order_by('pk') serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}, @@ -145,7 +145,7 @@ def test_reverse_many_to_many_update(self): serializer.save() assert serializer.data == data # Ensure target 1 is updated, and everything else is as expected - queryset = ManyToManyTarget.objects.all() + queryset = ManyToManyTarget.objects.order_by('pk') serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/']}, @@ -164,7 +164,7 @@ def test_many_to_many_create(self): assert obj.name == 'source-4' # Ensure source 4 is added, and everything else is as expected - queryset = ManyToManySource.objects.all() + queryset = ManyToManySource.objects.order_by('pk') serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']}, @@ -183,7 +183,7 @@ def test_reverse_many_to_many_create(self): assert obj.name == 'target-4' # Ensure target 4 is added, and everything else is as expected - queryset = ManyToManyTarget.objects.all() + queryset = ManyToManyTarget.objects.order_by('pk') serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']}, @@ -215,7 +215,7 @@ def setUp(self): source.save() def test_foreign_key_retrieve(self): - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'}, @@ -226,7 +226,7 @@ def test_foreign_key_retrieve(self): assert serializer.data == expected def test_reverse_foreign_key_retrieve(self): - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']}, @@ -244,7 +244,7 @@ def test_foreign_key_update(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/2/'}, @@ -267,7 +267,7 @@ def test_reverse_foreign_key_update(self): assert serializer.is_valid() # We shouldn't have saved anything to the db yet since save # hasn't been called. - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') new_serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']}, @@ -279,7 +279,7 @@ def test_reverse_foreign_key_update(self): assert serializer.data == data # Ensure target 2 is update, and everything else is as expected - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']}, @@ -296,7 +296,7 @@ def test_foreign_key_create(self): assert obj.name == 'source-4' # Ensure source 1 is updated, and everything else is as expected - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'}, @@ -315,7 +315,7 @@ def test_reverse_foreign_key_create(self): assert obj.name == 'target-3' # Ensure target 4 is added, and everything else is as expected - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']}, @@ -344,7 +344,7 @@ def setUp(self): source.save() def test_foreign_key_retrieve_with_null(self): - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'}, @@ -362,7 +362,7 @@ def test_foreign_key_create_with_valid_null(self): assert obj.name == 'source-4' # Ensure source 4 is created, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'}, @@ -386,7 +386,7 @@ def test_foreign_key_create_with_valid_emptystring(self): assert obj.name == 'source-4' # Ensure source 4 is created, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'}, @@ -405,7 +405,7 @@ def test_foreign_key_update_with_valid_null(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}, @@ -428,7 +428,7 @@ def test_foreign_key_update_with_valid_emptystring(self): assert serializer.data == expected_data # Ensure source 1 is updated, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}, @@ -449,7 +449,7 @@ def setUp(self): source.save() def test_reverse_foreign_key_retrieve_with_null(self): - queryset = OneToOneTarget.objects.all() + queryset = OneToOneTarget.objects.order_by('pk') serializer = NullableOneToOneTargetSerializer(queryset, many=True, context={'request': request}) expected = [ {'url': 'http://testserver/onetoonetarget/1/', 'name': 'target-1', 'nullable_source': 'http://testserver/nullableonetoonesource/1/'}, diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py index 3ca3726e24..a7af8ffd1d 100644 --- a/tests/test_relations_pk.py +++ b/tests/test_relations_pk.py @@ -106,7 +106,7 @@ def setUp(self): source.targets.add(target) def test_many_to_many_retrieve(self): - queryset = ManyToManySource.objects.all() + queryset = ManyToManySource.objects.order_by('pk') serializer = ManyToManySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'targets': [1]}, @@ -123,7 +123,7 @@ def test_many_to_many_retrieve_prefetch_related(self): serializer.data def test_reverse_many_to_many_retrieve(self): - queryset = ManyToManyTarget.objects.all() + queryset = ManyToManyTarget.objects.order_by('pk') serializer = ManyToManyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]}, @@ -142,7 +142,7 @@ def test_many_to_many_update(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = ManyToManySource.objects.all() + queryset = ManyToManySource.objects.order_by('pk') serializer = ManyToManySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]}, @@ -160,7 +160,7 @@ def test_reverse_many_to_many_update(self): assert serializer.data == data # Ensure target 1 is updated, and everything else is as expected - queryset = ManyToManyTarget.objects.all() + queryset = ManyToManyTarget.objects.order_by('pk') serializer = ManyToManyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': [1]}, @@ -178,7 +178,7 @@ def test_many_to_many_create(self): assert obj.name == 'source-4' # Ensure source 4 is added, and everything else is as expected - queryset = ManyToManySource.objects.all() + queryset = ManyToManySource.objects.order_by('pk') serializer = ManyToManySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'targets': [1]}, @@ -207,7 +207,7 @@ def test_reverse_many_to_many_create(self): assert obj.name == 'target-4' # Ensure target 4 is added, and everything else is as expected - queryset = ManyToManyTarget.objects.all() + queryset = ManyToManyTarget.objects.order_by('pk') serializer = ManyToManyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]}, @@ -237,7 +237,7 @@ def setUp(self): source.save() def test_foreign_key_retrieve(self): - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 1}, @@ -248,7 +248,7 @@ def test_foreign_key_retrieve(self): assert serializer.data == expected def test_reverse_foreign_key_retrieve(self): - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]}, @@ -272,7 +272,7 @@ def test_foreign_key_update(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 2}, @@ -295,7 +295,7 @@ def test_reverse_foreign_key_update(self): assert serializer.is_valid() # We shouldn't have saved anything to the db yet since save # hasn't been called. - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') new_serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]}, @@ -307,7 +307,7 @@ def test_reverse_foreign_key_update(self): assert serializer.data == data # Ensure target 2 is update, and everything else is as expected - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': [2]}, @@ -324,7 +324,7 @@ def test_foreign_key_create(self): assert obj.name == 'source-4' # Ensure source 4 is added, and everything else is as expected - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 1}, @@ -343,7 +343,7 @@ def test_reverse_foreign_key_create(self): assert obj.name == 'target-3' # Ensure target 3 is added, and everything else is as expected - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': [2]}, @@ -454,7 +454,7 @@ def setUp(self): source.save() def test_foreign_key_retrieve_with_null(self): - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 1}, @@ -472,7 +472,7 @@ def test_foreign_key_create_with_valid_null(self): assert obj.name == 'source-4' # Ensure source 4 is created, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 1}, @@ -496,7 +496,7 @@ def test_foreign_key_create_with_valid_emptystring(self): assert obj.name == 'source-4' # Ensure source 4 is created, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 1}, @@ -515,7 +515,7 @@ def test_foreign_key_update_with_valid_null(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': None}, @@ -538,7 +538,7 @@ def test_foreign_key_update_with_valid_emptystring(self): assert serializer.data == expected_data # Ensure source 1 is updated, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': None}, @@ -569,7 +569,7 @@ def setUp(self): source.save() def test_reverse_foreign_key_retrieve_with_null(self): - queryset = OneToOneTarget.objects.all() + queryset = OneToOneTarget.objects.order_by('pk') serializer = NullableOneToOneTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'nullable_source': None}, diff --git a/tests/test_relations_slug.py b/tests/test_relations_slug.py index 0b9ca79d3d..03f60d46b5 100644 --- a/tests/test_relations_slug.py +++ b/tests/test_relations_slug.py @@ -53,7 +53,7 @@ def setUp(self): source.save() def test_foreign_key_retrieve(self): - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 'target-1'}, @@ -64,13 +64,13 @@ def test_foreign_key_retrieve(self): assert serializer.data == expected def test_foreign_key_retrieve_select_related(self): - queryset = ForeignKeySource.objects.all().select_related('target') + queryset = ForeignKeySource.objects.order_by('pk').select_related('target') serializer = ForeignKeySourceSerializer(queryset, many=True) with self.assertNumQueries(1): serializer.data def test_reverse_foreign_key_retrieve(self): - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']}, @@ -79,7 +79,7 @@ def test_reverse_foreign_key_retrieve(self): assert serializer.data == expected def test_reverse_foreign_key_retrieve_prefetch_related(self): - queryset = ForeignKeyTarget.objects.all().prefetch_related('sources') + queryset = ForeignKeyTarget.objects.order_by('pk').prefetch_related('sources') serializer = ForeignKeyTargetSerializer(queryset, many=True) with self.assertNumQueries(2): serializer.data @@ -93,7 +93,7 @@ def test_foreign_key_update(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 'target-2'}, @@ -116,7 +116,7 @@ def test_reverse_foreign_key_update(self): assert serializer.is_valid() # We shouldn't have saved anything to the db yet since save # hasn't been called. - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') new_serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']}, @@ -128,7 +128,7 @@ def test_reverse_foreign_key_update(self): assert serializer.data == data # Ensure target 2 is update, and everything else is as expected - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': ['source-2']}, @@ -146,7 +146,7 @@ def test_foreign_key_create(self): assert obj.name == 'source-4' # Ensure source 4 is added, and everything else is as expected - queryset = ForeignKeySource.objects.all() + queryset = ForeignKeySource.objects.order_by('pk') serializer = ForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 'target-1'}, @@ -165,7 +165,7 @@ def test_reverse_foreign_key_create(self): assert obj.name == 'target-3' # Ensure target 3 is added, and everything else is as expected - queryset = ForeignKeyTarget.objects.all() + queryset = ForeignKeyTarget.objects.order_by('pk') serializer = ForeignKeyTargetSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'target-1', 'sources': ['source-2']}, @@ -193,7 +193,7 @@ def setUp(self): source.save() def test_foreign_key_retrieve_with_null(self): - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 'target-1'}, @@ -211,7 +211,7 @@ def test_foreign_key_create_with_valid_null(self): assert obj.name == 'source-4' # Ensure source 4 is created, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 'target-1'}, @@ -235,7 +235,7 @@ def test_foreign_key_create_with_valid_emptystring(self): assert obj.name == 'source-4' # Ensure source 4 is created, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': 'target-1'}, @@ -254,7 +254,7 @@ def test_foreign_key_update_with_valid_null(self): assert serializer.data == data # Ensure source 1 is updated, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': None}, @@ -277,7 +277,7 @@ def test_foreign_key_update_with_valid_emptystring(self): assert serializer.data == expected_data # Ensure source 1 is updated, and everything else is as expected - queryset = NullableForeignKeySource.objects.all() + queryset = NullableForeignKeySource.objects.order_by('pk') serializer = NullableForeignKeySourceSerializer(queryset, many=True) expected = [ {'id': 1, 'name': 'source-1', 'target': None}, diff --git a/tests/test_validators.py b/tests/test_validators.py index 96354b9b13..f58cd50a01 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -4,7 +4,7 @@ import pytest from django import VERSION as django_version -from django.db import DataError, models +from django.db import DataError, connection, models from django.test import TestCase from rest_framework import serializers @@ -742,8 +742,10 @@ def test_single_field_uniq_validators(self): UniqueConstraint with single field must be transformed into field's UniqueValidator """ - # Django 5 includes Max and Min values validators for IntegerField - extra_validators_qty = 2 if django_version[0] >= 5 else 0 + # Backends like PostgreSQL add Min/Max validators for IntegerField; + # SQLite does not because it has no fixed integer range. + has_int_range = connection.ops.integer_field_range('IntegerField')[0] is not None + extra_validators_qty = 2 if has_int_range else 0 serializer = UniqueConstraintSerializer() assert len(serializer.validators) == 2 validators = serializer.fields['global_id'].validators diff --git a/tox.ini b/tox.ini index 00e5bd57b8..3dcdbf92ed 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,8 @@ envdir = {toxworkdir}/venvs/{envname} setenv = PYTHONDONTWRITEBYTECODE=1 PYTHONWARNINGS=once +pass_env = + DATABASE_URL dependency_groups = test optional @@ -30,6 +32,8 @@ dependency_groups = dependency_groups = test deps = +# Unset passing the DATABASE_URL env var to run on SQLite +pass_env = [testenv:dist] commands = python -W error::DeprecationWarning -W error::PendingDeprecationWarning runtests.py --no-pkgroot --staticfiles {posargs}