#!/usr/bin/env python3 import requests import json import sys import logging from datetime import datetime, date, timedelta from enum import Enum # Настройка логирования logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Порт основного сервиса календаря CALENDAR_SERVICE_PORT = 8004 # Валидный токен аутентификации TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyOSIsImVtYWlsIjoidGVzdDJAZXhhbXBsZS5jb20iLCJleHAiOjE3NTg4NjQwMzV9.Ap4ZD5EtwhLXRtm6KjuFvXMlk6XA-3HtMbaGEu9jX6M" # Мобильные типы записей и данных class MobileEntryType(str, Enum): MENSTRUATION = "MENSTRUATION" OVULATION = "OVULATION" SPOTTING = "SPOTTING" DISCHARGE = "DISCHARGE" PAIN = "PAIN" MOOD = "MOOD" class MobileMood(str, Enum): HAPPY = "HAPPY" SAD = "SAD" ANXIOUS = "ANXIOUS" IRRITABLE = "IRRITABLE" ENERGETIC = "ENERGETIC" TIRED = "TIRED" NORMAL = "NORMAL" class MobileSymptom(str, Enum): CRAMPS = "CRAMPS" HEADACHE = "HEADACHE" BLOATING = "BLOATING" FATIGUE = "FATIGUE" NAUSEA = "NAUSEA" BREAST_TENDERNESS = "BREAST_TENDERNESS" ACNE = "ACNE" BACKACHE = "BACKACHE" def test_calendar_apis(): """Тестирование всех API эндпоинтов календарного сервиса""" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {TOKEN}" } base_url = f"http://localhost:{CALENDAR_SERVICE_PORT}" logger.info(f"Тестирование основного сервиса календаря на порту {CALENDAR_SERVICE_PORT}") # Проверяем доступность сервиса if not check_service_available(base_url): logger.error(f"Сервис календаря на порту {CALENDAR_SERVICE_PORT} недоступен!") return 1 # 1. Тест стандартного формата на /api/v1/calendar/entries standard_entry = { "entry_date": (date.today() + timedelta(days=1)).isoformat(), "entry_type": "period", "flow_intensity": "medium", "period_symptoms": "cramps", "energy_level": 3, "sleep_hours": 7, "medications": "", "symptoms": "headache", "notes": f"Стандартный тест {datetime.now().isoformat()}" } standard_response = test_endpoint( url=f"{base_url}/api/v1/calendar/entries", method="POST", data=standard_entry, headers=headers, description="Стандартный формат - /api/v1/calendar/entries" ) # 2. Тест мобильного формата на /api/v1/calendar/entry mobile_entry = { "entry_date": date.today().isoformat(), "entry_type": "MENSTRUATION", "flow_intensity": 4, "mood": "HAPPY", "symptoms": "FATIGUE,HEADACHE", "notes": f"Мобильный тест {datetime.now().isoformat()}" } mobile_response = test_endpoint( url=f"{base_url}/api/v1/calendar/entry", method="POST", data=mobile_entry, headers=headers, description="Мобильный формат - /api/v1/calendar/entry" ) # 3. Тест стандартного формата на /api/v1/entries (legacy) legacy_entry = { "entry_date": (date.today() + timedelta(days=2)).isoformat(), "entry_type": "symptoms", "flow_intensity": None, "period_symptoms": "", "energy_level": 4, "sleep_hours": 8, "medications": "vitamin", "symptoms": "fatigue", "notes": f"Тест legacy endpoint {datetime.now().isoformat()}" } legacy_response = test_endpoint( url=f"{base_url}/api/v1/entries", method="POST", data=legacy_entry, headers=headers, description="Стандартный формат - /api/v1/entries (legacy)" ) # 4. Тест стандартного формата на /api/v1/entry (без префикса /calendar) entry_endpoint_entry = { "entry_date": (date.today() + timedelta(days=3)).isoformat(), "entry_type": "mood", "mood": "happy", "energy_level": 5, "sleep_hours": 9, "symptoms": "", "medications": "", "period_symptoms": "", "notes": f"Тест /entry endpoint {datetime.now().isoformat()}" } entry_response = test_endpoint( url=f"{base_url}/api/v1/entry", method="POST", data=entry_endpoint_entry, headers=headers, description="Стандартный формат - /api/v1/entry (без префикса)" ) # 5. Проверка списка записей get_entries_response = test_endpoint( url=f"{base_url}/api/v1/calendar/entries", method="GET", headers=headers, description="Получение списка записей" ) if get_entries_response and get_entries_response.status_code == 200: entries = get_entries_response.json() logger.info(f"Всего записей в календаре: {len(entries)}") if entries: for i, entry in enumerate(entries[:5]): # Показываем первые 5 записей logger.info(f"Запись {i+1}: ID={entry.get('id')}, Дата={entry.get('entry_date')}, Тип={entry.get('entry_type')}") # Подсчитываем успешные тесты tests = [standard_response, mobile_response, legacy_response, entry_response, get_entries_response] success_count = sum(1 for test in tests if test and test.status_code in [200, 201]) expected_success = 5 if success_count >= expected_success: logger.info(f"✅ Успешно пройдено {success_count}/{expected_success} тестов!") return 0 else: logger.error(f"❌ Пройдено только {success_count}/{expected_success} тестов") return 1 def check_service_available(base_url): """Проверяет доступность сервиса""" try: response = requests.get(f"{base_url}/health", timeout=5) return response.status_code == 200 except requests.exceptions.RequestException: return False def test_endpoint(url, method, headers, description, data=None): """Выполняет тест для конкретного эндпоинта""" logger.info(f"\nТестирование: {description}") logger.info(f"URL: {url}, Метод: {method}") if data: logger.info(f"Данные: {json.dumps(data, indent=2)}") try: if method.upper() == "GET": response = requests.get(url, headers=headers, timeout=10) elif method.upper() == "POST": response = requests.post(url, headers=headers, json=data, timeout=10) else: logger.error(f"Неподдерживаемый метод: {method}") return None logger.info(f"Статус ответа: {response.status_code}") # Для успешных ответов логируем детали if response.status_code in [200, 201]: logger.info("✅ Тест успешно пройден!") try: response_data = response.json() if isinstance(response_data, dict): logger.info(f"Ответ: ID={response_data.get('id')}, Тип={response_data.get('entry_type')}") except ValueError: logger.info(f"Ответ не в формате JSON: {response.text[:100]}...") else: logger.warning(f"❌ Тест не пройден. Статус: {response.status_code}") logger.warning(f"Ответ: {response.text}") return response except requests.exceptions.RequestException as e: logger.error(f"❌ Ошибка при выполнении запроса: {str(e)}") return None if __name__ == "__main__": sys.exit(test_calendar_apis())