Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
13 changes: 12 additions & 1 deletion rest_framework/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
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
Expand Down Expand Up @@ -89,8 +91,17 @@ def start_response(wsgi_status, wsgi_headers, exc_info=None):
raw_kwargs['original_response'] = MockOriginalResponse(wsgi_headers)

# Make the outgoing request via WSGI.
# Disconnect close_old_connections to prevent closing the
# database connection during tests, matching the behavior
# of Django's ClientHandler.
environ = self.get_environ(request)
wsgi_response = self.app(environ, start_response)
request_started.disconnect(close_old_connections)
request_finished.disconnect(close_old_connections)
try:
wsgi_response = self.app(environ, start_response)
finally:
request_started.connect(close_old_connections)
request_finished.connect(close_old_connections)
Comment thread
browniebroke marked this conversation as resolved.
Outdated

# Build the underlying urllib3.HTTPResponse
raw_kwargs['body'] = io.BytesIO(b''.join(wsgi_response))
Expand Down
29 changes: 29 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Comment thread
browniebroke marked this conversation as resolved.


def pytest_addoption(parser):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
40 changes: 20 additions & 20 deletions tests/test_relations_hyperlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/']},
Expand All @@ -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/']},
Expand All @@ -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/']},
Expand All @@ -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/']},
Expand All @@ -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/']},
Expand All @@ -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/']},
Expand All @@ -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/']},
Expand Down Expand Up @@ -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/'},
Expand All @@ -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/']},
Expand All @@ -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/'},
Expand All @@ -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/']},
Expand All @@ -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/']},
Expand All @@ -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/'},
Expand All @@ -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/']},
Expand Down Expand Up @@ -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/'},
Expand All @@ -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/'},
Expand All @@ -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/'},
Expand All @@ -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},
Expand All @@ -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},
Expand All @@ -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/'},
Expand Down
Loading
Loading