""" Тесты производительности для API домашних заданий. Измеряют время ответа и количество SQL запросов. """ import time import pytest from django.test.utils import override_settings from django.db import connection, reset_queries from django.contrib.auth import get_user_model User = get_user_model() @pytest.mark.django_db @pytest.mark.performance class TestHomeworkPerformance: """Тесты производительности API домашних заданий.""" @pytest.fixture def setup_data(self, mentor_user, client_user): """Создает тестовые данные для проверки производительности.""" from apps.schedule.models import Lesson from apps.homework.models import Homework, HomeworkSubmission # Создаем несколько студентов students = [] for i in range(10): student = User.objects.create_user( email=f'student{i}@test.com', password='TestPass123!', first_name=f'Студент{i}', last_name=f'Тестовый{i}', role='client', is_email_verified=True, is_active=True ) students.append(student) # Создаем занятие lesson = Lesson.objects.create( mentor=mentor_user, title='Тестовое занятие', status='scheduled' ) # Создаем домашние задания homeworks = [] for i in range(5): homework = Homework.objects.create( title=f'ДЗ {i+1}', description=f'Описание ДЗ {i+1}', mentor=mentor_user, lesson=lesson, status='published', max_score=100 ) # Назначаем студентов homework.assigned_to.set(students) # Создаем решения для некоторых студентов for j, student in enumerate(students[:5]): # 5 студентов сдали HomeworkSubmission.objects.create( homework=homework, student=student, content=f'Решение от студента {j}', status='graded' if j % 2 == 0 else 'pending', score=80 + j if j % 2 == 0 else None ) homeworks.append(homework) return { 'mentor_user': mentor_user, 'students': students, 'homeworks': homeworks } def test_homework_list_performance_mentor(self, authenticated_client): """Тест производительности списка ДЗ для ментора.""" reset_queries() start_time = time.time() response = authenticated_client.get('/api/homework/homeworks/') end_time = time.time() elapsed_time = end_time - start_time query_count = len(connection.queries) assert response.status_code == 200 assert elapsed_time < 0.5, f"Время ответа слишком долгое: {elapsed_time:.3f}с" assert query_count < 20, f"Слишком много SQL запросов: {query_count}" print(f"\n📊 Список ДЗ (ментор):") print(f" Время: {elapsed_time:.3f}с") print(f" SQL запросов: {query_count}") print(f" ДЗ в ответе: {len(response.json().get('results', response.json()))}") def test_homework_list_performance_student(self, authenticated_client_user): """Тест производительности списка ДЗ для студента.""" reset_queries() start_time = time.time() response = authenticated_client_user.get('/api/homework/homeworks/') end_time = time.time() elapsed_time = end_time - start_time query_count = len(connection.queries) assert response.status_code == 200 assert elapsed_time < 0.3, f"Время ответа слишком долгое: {elapsed_time:.3f}с" assert query_count < 15, f"Слишком много SQL запросов: {query_count}" print(f"\n📊 Список ДЗ (студент):") print(f" Время: {elapsed_time:.3f}с") print(f" SQL запросов: {query_count}") def test_homework_statistics_performance(self, authenticated_client, setup_data): """Тест производительности статистики ДЗ.""" homework = setup_data['homeworks'][0] reset_queries() start_time = time.time() response = authenticated_client.get(f'/api/homework/homeworks/{homework.id}/statistics/') end_time = time.time() elapsed_time = end_time - start_time query_count = len(connection.queries) assert response.status_code == 200 assert elapsed_time < 0.2, f"Время ответа слишком долгое: {elapsed_time:.3f}с" assert query_count < 5, f"Слишком много SQL запросов: {query_count}" print(f"\n📊 Статистика ДЗ:") print(f" Время: {elapsed_time:.3f}с") print(f" SQL запросов: {query_count}") print(f" Данные: {response.json()}") def test_homework_submissions_list_performance(self, authenticated_client, setup_data): """Тест производительности списка решений ДЗ.""" homework = setup_data['homeworks'][0] reset_queries() start_time = time.time() response = authenticated_client.get( f'/api/homework/submissions/?homework_id={homework.id}' ) end_time = time.time() elapsed_time = end_time - start_time query_count = len(connection.queries) assert response.status_code == 200 assert elapsed_time < 0.3, f"Время ответа слишком долгое: {elapsed_time:.3f}с" assert query_count < 10, f"Слишком много SQL запросов: {query_count}" print(f"\n📊 Список решений ДЗ:") print(f" Время: {elapsed_time:.3f}с") print(f" SQL запросов: {query_count}") print(f" Решений в ответе: {len(response.json().get('results', response.json()))}") @pytest.mark.django_db @pytest.mark.performance class TestChatPerformance: """Тесты производительности API чата.""" @pytest.fixture def setup_chat_data(self, mentor_user, client_user): """Создает тестовые данные для чата.""" from apps.chat.models import Chat, ChatParticipant, Message, MessageRead # Создаем несколько пользователей users = [mentor_user, client_user] for i in range(5): user = User.objects.create_user( email=f'user{i}@test.com', password='TestPass123!', first_name=f'Пользователь{i}', last_name=f'Тестовый{i}', role='client', is_email_verified=True, is_active=True ) users.append(user) # Создаем чаты с участниками и сообщениями chats = [] for i in range(3): chat = Chat.objects.create( chat_type='group', name=f'Чат {i+1}', created_by=mentor_user ) # Добавляем участников for user in users[:3]: ChatParticipant.objects.create( chat=chat, user=user, role='member' ) # Создаем сообщения for j in range(10): message = Message.objects.create( chat=chat, sender=users[j % len(users)], content=f'Сообщение {j+1} в чате {i+1}' ) # Помечаем некоторые сообщения как прочитанные if j % 2 == 0: MessageRead.objects.create( message=message, user=mentor_user ) chats.append(chat) return { 'mentor_user': mentor_user, 'chats': chats } def test_chat_list_performance(self, authenticated_client): """Тест производительности списка чатов.""" reset_queries() start_time = time.time() response = authenticated_client.get('/api/chat/chats/') end_time = time.time() elapsed_time = end_time - start_time query_count = len(connection.queries) assert response.status_code == 200 assert elapsed_time < 0.4, f"Время ответа слишком долгое: {elapsed_time:.3f}с" assert query_count < 15, f"Слишком много SQL запросов: {query_count}" print(f"\n📊 Список чатов:") print(f" Время: {elapsed_time:.3f}с") print(f" SQL запросов: {query_count}") print(f" Чатов в ответе: {len(response.json().get('results', response.json()))}") def test_chat_messages_performance(self, authenticated_client, setup_chat_data): """Тест производительности сообщений чата.""" chat = setup_chat_data['chats'][0] reset_queries() start_time = time.time() response = authenticated_client.get(f'/api/chat/chats/{chat.uuid}/messages/') end_time = time.time() elapsed_time = end_time - start_time query_count = len(connection.queries) assert response.status_code == 200 assert elapsed_time < 0.3, f"Время ответа слишком долгое: {elapsed_time:.3f}с" assert query_count < 10, f"Слишком много SQL запросов: {query_count}" print(f"\n📊 Сообщения чата:") print(f" Время: {elapsed_time:.3f}с") print(f" SQL запросов: {query_count}") messages_data = response.json().get('results', response.json()) print(f" Сообщений в ответе: {len(messages_data)}") @pytest.mark.django_db @pytest.mark.performance class TestGeneralPerformance: """Общие тесты производительности.""" def test_multiple_requests_performance(self, authenticated_client): """Тест производительности при множественных запросах.""" times = [] query_counts = [] for i in range(5): reset_queries() start_time = time.time() response = authenticated_client.get('/api/homework/homeworks/') end_time = time.time() times.append(end_time - start_time) query_counts.append(len(connection.queries)) assert response.status_code == 200 avg_time = sum(times) / len(times) avg_queries = sum(query_counts) / len(query_counts) max_time = max(times) max_queries = max(query_counts) print(f"\n📊 Множественные запросы (5 раз):") print(f" Среднее время: {avg_time:.3f}с") print(f" Максимальное время: {max_time:.3f}с") print(f" Среднее SQL запросов: {avg_queries:.1f}") print(f" Максимум SQL запросов: {max_queries}") assert avg_time < 0.5, f"Среднее время слишком долгое: {avg_time:.3f}с" assert avg_queries < 20, f"Среднее количество запросов слишком большое: {avg_queries:.1f}"