- Add Model Mixins: TimestampMixin, SoftDeleteMixin, AuditMixin, etc. - Add Base Services: BaseService, BulkOperationsMixin, QueryOptimizerMixin - Add Base ViewSets with bulk operations - Add BackgroundJob model for Celery task tracking - Add BaseAppCommand for management commands - Add permissions, pagination, filters, cache, logging - Migrate tests to factory_boy + faker - Add CHANGELOG.md - 297 tests passing
187 lines
6.9 KiB
Python
187 lines
6.9 KiB
Python
"""Тесты для BulkOperationsMixin и QueryOptimizerMixin."""
|
||
|
||
from apps.core.models import BackgroundJob
|
||
from apps.core.services import (
|
||
BulkOperationsMixin,
|
||
QueryOptimizerMixin,
|
||
)
|
||
from django.test import TestCase
|
||
from faker import Faker
|
||
|
||
fake = Faker()
|
||
|
||
|
||
class BulkOperationsMixinTest(TestCase):
|
||
"""Тесты для BulkOperationsMixin."""
|
||
|
||
def test_mixin_has_bulk_create_chunked(self):
|
||
"""Проверка наличия метода bulk_create_chunked."""
|
||
self.assertTrue(hasattr(BulkOperationsMixin, "bulk_create_chunked"))
|
||
|
||
def test_mixin_has_bulk_update_or_create(self):
|
||
"""Проверка наличия метода bulk_update_or_create."""
|
||
self.assertTrue(hasattr(BulkOperationsMixin, "bulk_update_or_create"))
|
||
|
||
def test_mixin_has_bulk_delete(self):
|
||
"""Проверка наличия метода bulk_delete."""
|
||
self.assertTrue(hasattr(BulkOperationsMixin, "bulk_delete"))
|
||
|
||
def test_mixin_has_bulk_update_fields(self):
|
||
"""Проверка наличия метода bulk_update_fields."""
|
||
self.assertTrue(hasattr(BulkOperationsMixin, "bulk_update_fields"))
|
||
|
||
|
||
class QueryOptimizerMixinTest(TestCase):
|
||
"""Тесты для QueryOptimizerMixin."""
|
||
|
||
def test_mixin_has_get_optimized_queryset(self):
|
||
"""Проверка наличия метода get_optimized_queryset."""
|
||
self.assertTrue(hasattr(QueryOptimizerMixin, "get_optimized_queryset"))
|
||
|
||
def test_mixin_has_apply_optimizations(self):
|
||
"""Проверка наличия метода apply_optimizations."""
|
||
self.assertTrue(hasattr(QueryOptimizerMixin, "apply_optimizations"))
|
||
|
||
def test_mixin_has_get_list_queryset(self):
|
||
"""Проверка наличия метода get_list_queryset."""
|
||
self.assertTrue(hasattr(QueryOptimizerMixin, "get_list_queryset"))
|
||
|
||
def test_mixin_has_get_detail_queryset(self):
|
||
"""Проверка наличия метода get_detail_queryset."""
|
||
self.assertTrue(hasattr(QueryOptimizerMixin, "get_detail_queryset"))
|
||
|
||
def test_mixin_has_with_counts(self):
|
||
"""Проверка наличия метода with_counts."""
|
||
self.assertTrue(hasattr(QueryOptimizerMixin, "with_counts"))
|
||
|
||
def test_mixin_has_with_exists(self):
|
||
"""Проверка наличия метода with_exists."""
|
||
self.assertTrue(hasattr(QueryOptimizerMixin, "with_exists"))
|
||
|
||
def test_mixin_default_attributes(self):
|
||
"""Проверка атрибутов по умолчанию."""
|
||
self.assertEqual(QueryOptimizerMixin.select_related, [])
|
||
self.assertEqual(QueryOptimizerMixin.prefetch_related, [])
|
||
self.assertEqual(QueryOptimizerMixin.default_only, [])
|
||
self.assertEqual(QueryOptimizerMixin.default_defer, [])
|
||
|
||
|
||
class BulkOperationsIntegrationTest(TestCase):
|
||
"""Интеграционные тесты для bulk операций с BackgroundJob."""
|
||
|
||
def test_bulk_create_chunked(self):
|
||
"""Тест массового создания чанками."""
|
||
# Создаём тестовый сервис с BulkOperationsMixin
|
||
class TestService(BulkOperationsMixin):
|
||
model = BackgroundJob
|
||
|
||
# Создаём 10 объектов чанками по 3
|
||
jobs = [
|
||
BackgroundJob(
|
||
task_id=f"bulk-chunk-{i}",
|
||
task_name="test.bulk.task",
|
||
)
|
||
for i in range(10)
|
||
]
|
||
|
||
count = TestService.bulk_create_chunked(jobs, chunk_size=3)
|
||
self.assertEqual(count, 10)
|
||
|
||
# Проверяем что все созданы
|
||
self.assertEqual(BackgroundJob.objects.filter(task_name="test.bulk.task").count(), 10)
|
||
|
||
def test_bulk_delete(self):
|
||
"""Тест массового удаления."""
|
||
class TestService(BulkOperationsMixin):
|
||
model = BackgroundJob
|
||
|
||
# Создаём несколько задач
|
||
jobs = []
|
||
for i in range(5):
|
||
job = BackgroundJob.objects.create(
|
||
task_id=f"bulk-delete-{i}",
|
||
task_name="test.delete.task",
|
||
)
|
||
jobs.append(job)
|
||
|
||
# Удаляем первые 3
|
||
ids_to_delete = [j.pk for j in jobs[:3]]
|
||
deleted = TestService.bulk_delete(ids_to_delete)
|
||
|
||
self.assertEqual(deleted, 3)
|
||
self.assertEqual(BackgroundJob.objects.filter(task_name="test.delete.task").count(), 2)
|
||
|
||
def test_bulk_update_fields(self):
|
||
"""Тест массового обновления полей."""
|
||
class TestService(BulkOperationsMixin):
|
||
model = BackgroundJob
|
||
|
||
# Создаём задачи
|
||
for i in range(5):
|
||
BackgroundJob.objects.create(
|
||
task_id=f"bulk-update-{i}",
|
||
task_name="test.update.task",
|
||
progress=0,
|
||
)
|
||
|
||
# Обновляем все задачи этого типа
|
||
updated = TestService.bulk_update_fields(
|
||
filters={"task_name": "test.update.task"},
|
||
updates={"progress": 50},
|
||
)
|
||
|
||
self.assertEqual(updated, 5)
|
||
|
||
# Проверяем что обновились
|
||
for job in BackgroundJob.objects.filter(task_name="test.update.task"):
|
||
self.assertEqual(job.progress, 50)
|
||
|
||
def test_bulk_update_or_create_creates(self):
|
||
"""Тест upsert - создание новых."""
|
||
class TestService(BulkOperationsMixin):
|
||
model = BackgroundJob
|
||
|
||
items = [
|
||
{"task_id": "upsert-new-1", "task_name": "upsert.task", "progress": 10},
|
||
{"task_id": "upsert-new-2", "task_name": "upsert.task", "progress": 20},
|
||
]
|
||
|
||
created, updated = TestService.bulk_update_or_create(
|
||
items=items,
|
||
unique_fields=["task_id"],
|
||
update_fields=["task_name", "progress"],
|
||
)
|
||
|
||
self.assertEqual(created, 2)
|
||
self.assertEqual(updated, 0)
|
||
|
||
def test_bulk_update_or_create_updates(self):
|
||
"""Тест upsert - обновление существующих."""
|
||
class TestService(BulkOperationsMixin):
|
||
model = BackgroundJob
|
||
|
||
# Создаём существующую запись
|
||
BackgroundJob.objects.create(
|
||
task_id="upsert-existing",
|
||
task_name="old.task",
|
||
progress=0,
|
||
)
|
||
|
||
items = [
|
||
{"task_id": "upsert-existing", "task_name": "new.task", "progress": 100},
|
||
]
|
||
|
||
created, updated = TestService.bulk_update_or_create(
|
||
items=items,
|
||
unique_fields=["task_id"],
|
||
update_fields=["task_name", "progress"],
|
||
)
|
||
|
||
self.assertEqual(created, 0)
|
||
self.assertEqual(updated, 1)
|
||
|
||
# Проверяем обновление
|
||
job = BackgroundJob.objects.get(task_id="upsert-existing")
|
||
self.assertEqual(job.task_name, "new.task")
|
||
self.assertEqual(job.progress, 100)
|