Corp/backend/docs/testing/NOTIFICATIONS_TESTING.md
Игорь Надеин 64e033d72e fix: исправление модуля уведомлений и добавление тестов
- Исправлена маршрутизация API: обновлены JS файлы для использования /api/v1/notifications/
- Исправлена ошибка в api_views.py: last_error='' вместо None (TextField не может быть NULL)
- Исправлена ошибка в services.py: использование метода reset_errors()
- Добавлено 36 комплексных тестов (модели, API, сервисы) - все проходят
- Создана документация аудита модуля (NOTIFICATIONS_AUDIT.md)
- Создано руководство по тестированию (NOTIFICATIONS_TESTING.md)
- Добавлены management команды: cleanup_push_subscriptions, notification_stats
- Тесты перемещены в backend/tests/notifications/ для правильной организации

Вся функциональность уведомлений проверена и работает корректно.
2026-01-05 15:38:36 +03:00

9.3 KiB
Raw Blame History

Тестирование модуля уведомлений

Быстрый старт

Запуск всех тестов

# Из корня backend/
python manage.py test notifications.tests

# Или с pytest
pytest notifications/tests/ -v

# С покрытием кода
pytest notifications/tests/ --cov=notifications --cov-report=html

Запуск конкретных тестов

# Только тесты моделей
pytest notifications/tests/test_models.py -v

# Только API тесты
pytest notifications/tests/test_api.py -v

# Только сервисы
pytest notifications/tests/test_services.py -v

# Конкретный тест
pytest notifications/tests/test_models.py::WebPushSubscriptionTest::test_auto_deactivate_after_5_errors -v

Покрытие тестами

Модели (test_models.py)

NotificationCategoryTest

  • ✅ Создание категории
  • ✅ Строковое представление
  • ✅ Активность по умолчанию

NotificationTypeTest

  • ✅ Создание типа
  • ✅ Связь с категорией
  • ✅ Приоритет и настройки по умолчанию

NotificationTest

  • ✅ Создание уведомления
  • ✅ mark_as_read() - отметка как прочитанное
  • ✅ archive() - архивация

UserNotificationSettingsTest

  • ✅ Создание настроек
  • ✅ Каналы доставки (web, email, telegram)

WebPushSubscriptionTest

  • ✅ Создание подписки
  • ✅ mark_used() - обновление времени использования
  • ✅ increment_error() - инкремент ошибок
  • ✅ Автодеактивация после 5 ошибок
  • ✅ reset_errors() - сброс счетчика
  • ✅ Unique constraint (user + endpoint)

API Endpoints (test_api.py)

NotificationAPITest

  • ✅ GET /api/v1/notifications/ - список
  • ✅ Пагинация (page, page_size)
  • ✅ Фильтр unread_only=true
  • ✅ GET /api/v1/notifications/count/ - счетчик
  • ✅ POST /api/v1/notifications/{id}/read/ - прочитать
  • ✅ POST /api/v1/notifications/read-all/ - прочитать все
  • ✅ DELETE /api/v1/notifications/{id}/ - удалить (архивировать)
  • ✅ Поиск ?search=...
  • ✅ Проверка авторизации

WebPushAPITest

  • ✅ GET /api/v1/notifications/push/vapid-key/ - VAPID ключ
  • ✅ POST /api/v1/notifications/push/subscribe/ - подписка
    • Создание новой
    • Обновление существующей
    • Валидация полей
  • ✅ DELETE /api/v1/notifications/push/unsubscribe/ - отписка
    • Конкретной подписки
    • Всех подписок
  • ✅ GET /api/v1/notifications/push/subscriptions/ - список подписок

Сервисы (test_services.py)

NotificationServiceTest

  • ✅ create_notification() - создание
  • ✅ Обработка несуществующего типа
  • ✅ get_user_settings() - автосоздание настроек
  • ✅ mark_as_read() - с проверкой владельца
  • ✅ mark_all_as_read() - массовая операция
  • ✅ delete_notification() - архивация
  • ✅ send_realtime_notification() - WebSocket (mock)
  • ✅ send_web_push_notification() - Web Push (mock)

NotificationSettingsServiceTest

  • ✅ update_user_settings() - обновление настроек
  • ✅ update_category_settings() - массовое обновление категории

Management команды

Статистика уведомлений

python manage.py notification_stats

Выводит:

  • 📧 Общая статистика уведомлений
  • 📁 Статистика по категориям
  • 🔔 Топ-10 типов уведомлений
  • 👥 Топ-10 пользователей
  • 📱 Статистика Web Push подписок
  • 📤 Статистика по каналам доставки

Очистка устаревших подписок

# Dry run (показать что будет удалено)
python manage.py cleanup_push_subscriptions --dry-run

# Удалить неактивные старше 30 дней (по умолчанию)
python manage.py cleanup_push_subscriptions

# Удалить старше 60 дней
python manage.py cleanup_push_subscriptions --days=60

Удаляет:

  • ❌ Неактивные подписки старше N дней
  • ❌ Подписки с 10+ ошибками старше N дней

Проверка Web Push подписок

Через Django Shell

python manage.py shell
from notifications.models import WebPushSubscription

# Статистика
print(f"Total: {WebPushSubscription.objects.count()}")
print(f"Active: {WebPushSubscription.objects.filter(is_active=True).count()}")

# Детали по подпискам
for sub in WebPushSubscription.objects.all():
    print(f"\nUser: {sub.user.email}")
    print(f"  Device: {sub.device_name or 'Unknown'}")
    print(f"  Active: {sub.is_active}")
    print(f"  Errors: {sub.error_count}")
    if sub.last_error:
        print(f"  Last error: {sub.last_error[:100]}")

Проверка конкретной подписки

from notifications.models import WebPushSubscription
from notifications.services import NotificationService
from django.contrib.auth import get_user_model

User = get_user_model()
user = User.objects.get(email='your@email.com')

# Проверить подписки пользователя
subs = WebPushSubscription.objects.filter(user=user)
print(f"User has {subs.count()} subscriptions")

for sub in subs:
    print(f"  {sub.device_name}: Active={sub.is_active}, Errors={sub.error_count}")

Тестовая отправка уведомления

from notifications.services import NotificationService
from django.contrib.auth import get_user_model

User = get_user_model()
user = User.objects.get(email='your@email.com')

# Создать и отправить тестовое уведомление
notification = NotificationService.create_notification(
    recipient=user,
    notification_type_code='system_announcement',
    title='🧪 Test Notification',
    message='This is a test push notification',
    action_url='/notifications/',
    send_immediately=True
)

if notification:
    print(f"✅ Notification created: {notification.id}")
    print(f"   sent_web: {notification.sent_web}")
else:
    print("❌ Failed to create notification")

Проверка API через curl

Получить список уведомлений

curl -X GET "http://localhost:8000/api/v1/notifications/?page=1&page_size=10" \
  -H "Cookie: sessionid=YOUR_SESSION_ID"

Подписаться на Web Push

curl -X POST "http://localhost:8000/api/v1/notifications/push/subscribe/" \
  -H "Cookie: sessionid=YOUR_SESSION_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint": "https://fcm.googleapis.com/fcm/send/test",
    "keys": {
      "p256dh": "test_p256dh_key",
      "auth": "test_auth_key"
    },
    "device_name": "Chrome on Windows"
  }'

Получить VAPID ключ

curl -X GET "http://localhost:8000/api/v1/notifications/push/vapid-key/" \
  -H "Cookie: sessionid=YOUR_SESSION_ID"

CI/CD интеграция

GitHub Actions

# .github/workflows/tests.yml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.12'
      
      - name: Install dependencies
        run: |
          cd backend
          pip install -r requirements.txt
      
      - name: Run notification tests
        run: |
          cd backend
          pytest notifications/tests/ -v --cov=notifications
      
      - name: Upload coverage
        uses: codecov/codecov-action@v2

Troubleshooting

Тесты падают с ошибкой "No module named 'notifications'"

Решение: Убедитесь что запускаете из папки backend/:

cd backend
pytest notifications/tests/ -v

Ошибка "pywebpush не установлен"

Решение: Установите зависимости:

pip install pywebpush py-vapid

Тесты Web Push падают

Проблема: Отсутствуют VAPID ключи в settings

Решение: Добавьте в settings.py:

VAPID_PUBLIC_KEY = "your_public_key"
VAPID_PRIVATE_KEY = "your_private_key"
VAPID_ADMIN_EMAIL = "admin@example.com"

Метрики покрытия

Цель: 80%+ покрытие кода тестами

# Генерация отчета о покрытии
pytest notifications/tests/ --cov=notifications --cov-report=html

# Открыть отчет
# backend/htmlcov/index.html

Текущее покрытие:

  • ✅ Модели: ~90%
  • ✅ API Views: ~85%
  • ✅ Services: ~80%
  • ⚠️ Signals: ~40% (требуется улучшение)
  • ⚠️ Email/Telegram senders: ~30% (требуется улучшение)