Подготовка к релизу

This commit is contained in:
2025-10-30 18:28:26 +03:00
parent 69c0162c6b
commit 4981db90a0
191 changed files with 45557 additions and 3651 deletions
+348
View File
@@ -0,0 +1,348 @@
#!/usr/bin/env python3
"""
Комплексная система автоматического тестирования телеграм-бота.
Проверяет все команды, callback кнопки и обработчики сообщений.
"""
import asyncio
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from unittest.mock import MagicMock, AsyncMock
from telegram import Update, User, Chat, Message, CallbackQuery
from telegram.ext import ContextTypes
from typing import Dict, List, Tuple
# Импортируем все компоненты бота
from core.application import Application
from handlers.user_handlers import UserHandlers
from handlers.game_handlers import GameHandlers
from handlers.admin_handlers import AdminHandlers
from services.user_service import UserService
from services.game_service import GameService
from database.repository import UserRepository, ScoreRepository
class ComprehensiveTestSuite:
"""Комплексная система тестирования бота"""
def __init__(self):
"""Инициализация тестера"""
self.results = {
'commands': [],
'callbacks': [],
'messages': [],
'errors': []
}
# Создаем мок-конфигурацию
self.mock_config = MagicMock()
self.mock_config.api_keys = MagicMock()
self.mock_config.api_keys.openweather = "test_key"
self.mock_config.api_keys.news = "test_key"
self.mock_config.api_keys.openai = "test_key"
self.mock_config.bot_config = MagicMock()
self.mock_config.bot_config.admin_ids = [1278359005]
self.mock_config.bot_config.enable_developer_notifications = True
self.mock_config.bot_config.developer_chat_id = 1278359005
# Создаем репозитории и сервисы
self.user_repo = UserRepository("telegram_bot.db")
self.score_repo = ScoreRepository("telegram_bot.db")
self.user_service = UserService(self.user_repo, self.score_repo)
self.game_service = GameService(self.user_repo, self.score_repo)
# Создаем обработчики
self.user_handlers = UserHandlers(self.mock_config, MagicMock(), self.user_service)
self.game_handlers = GameHandlers(self.mock_config, MagicMock(), self.game_service)
print("Комплексная система тестирования инициализирована")
def create_mock_update(self, text=None, callback_data=None, user_id=123456789,
username="test_user", first_name="Test", last_name="User"):
"""Создание мок-объекта Update"""
# Создаем мок-пользователя
user = MagicMock(spec=User)
user.id = user_id
user.username = username
user.first_name = first_name
user.last_name = last_name
# Создаем мок-сообщение
message = MagicMock(spec=Message)
message.text = text
message.message_id = 1
# Создаем мок-коллбек запрос
callback_query = MagicMock(spec=CallbackQuery)
callback_query.data = callback_data
callback_query.message = MagicMock()
callback_query.from_user = user
# Создаем мок-чат
chat = MagicMock(spec=Chat)
chat.id = -1001234567890
chat.type = "supergroup"
# Создаем мок-update
update = MagicMock(spec=Update)
update.effective_user = user
update.message = message if text else None
update.callback_query = callback_query if callback_data else None
update.effective_chat = chat
return update
def create_mock_context(self):
"""Создание мок-объекта ContextTypes"""
context = MagicMock(spec=ContextTypes)
context.args = []
context.bot = MagicMock()
context.user_data = {}
# Настраиваем асинхронные методы
context.bot.send_message = AsyncMock()
context.bot.edit_message_text = AsyncMock()
return context
async def test_single_command(self, command: str, description: str, handler, method_name: str) -> Dict:
"""Тестирование одной команды"""
result = {
'command': command,
'description': description,
'success': False,
'error': None,
'execution_time': 0
}
try:
import time
start_time = time.time()
# Создаем мок-объекты
update = self.create_mock_update(text=command)
context = self.create_mock_context()
# Получаем метод обработчика
method = getattr(handler, method_name)
# Выполняем команду
await method(update, context)
execution_time = time.time() - start_time
result['success'] = True
result['execution_time'] = execution_time
print(f"[SUCCESS] {command}: {execution_time:.3f}с")
except Exception as e:
result['error'] = str(e)
print(f"[ERROR] {command}: {e}")
self.results['errors'].append({
'command': command,
'error': str(e),
'traceback': str(e.__class__.__name__)
})
return result
async def test_callback_button(self, callback_data: str, description: str, handler, method_name: str) -> Dict:
"""Тестирование callback кнопки"""
result = {
'callback': callback_data,
'description': description,
'success': False,
'error': None,
'execution_time': 0
}
try:
import time
start_time = time.time()
# Создаем мок-объекты
update = self.create_mock_update(callback_data=callback_data)
context = self.create_mock_context()
# Получаем метод обработчика
method = getattr(handler, method_name)
# Выполняем обработчик
await method(update, context)
execution_time = time.time() - start_time
result['success'] = True
result['execution_time'] = execution_time
print(f"[SUCCESS] {callback_data}: {execution_time:.3f}с")
except Exception as e:
result['error'] = str(e)
print(f"[ERROR] {callback_data}: {e}")
self.results['errors'].append({
'callback': callback_data,
'error': str(e),
'traceback': str(e.__class__.__name__)
})
return result
async def run_command_tests(self):
"""Тестирование команд"""
print("\n" + "="*60)
print("ТЕСТИРОВАНИЕ КОМАНД")
print("="*60)
commands_to_test = [
("/start", "Запуск бота", self.user_handlers, "handle_start"),
("/help", "Помощь", self.user_handlers, "handle_help"),
("/rank", "Ранг пользователя", self.user_handlers, "handle_rank"),
("/leaderboard", "Таблица лидеров", self.user_handlers, "handle_leaderboard"),
("/info", "Информация о пользователе", self.user_handlers, "handle_info"),
("/donate", "Донаты", self.user_handlers, "handle_donate"),
("/play_game", "Меню игр", self.game_handlers, "handle_play_game"),
("/rock_paper_scissors", "Камень-ножницы-бумага", self.game_handlers, "handle_rock_paper_scissors"),
("/battleship", "Морской бой", self.game_handlers, "handle_battleship"),
]
for command, description, handler, method_name in commands_to_test:
result = await self.test_single_command(command, description, handler, method_name)
self.results['commands'].append(result)
async def run_callback_tests(self):
"""Тестирование callback кнопок"""
print("\n" + "="*60)
print("ТЕСТИРОВАНИЕ CALLBACK КНОПОК")
print("="*60)
callbacks_to_test = [
("menu_main", "Главное меню", self.user_handlers, "handle_main_menu"),
("menu_help", "Меню помощи", self.user_handlers, "handle_help_menu"),
("menu_rank", "Меню ранга", self.user_handlers, "handle_rank_menu"),
("game_rps_start", "Запуск RPS", self.game_handlers, "handle_rps_choice"),
("game_battleship_start", "Запуск морского боя", self.game_handlers, "handle_battleship_shot"),
("donate_100", "Донат 100", self.user_handlers, "handle_donation_callback"),
("donate_500", "Донат 500", self.user_handlers, "handle_donation_callback"),
("donate_1000", "Донат 1000", self.user_handlers, "handle_donation_callback"),
]
for callback_data, description, handler, method_name in callbacks_to_test:
result = await self.test_callback_button(callback_data, description, handler, method_name)
self.results['callbacks'].append(result)
async def test_database_operations(self):
"""Тестирование операций с базой данных"""
print("\n" + "="*60)
print("ТЕСТИРОВАНИЕ БАЗЫ ДАННЫХ")
print("="*60)
try:
# Тестируем создание пользователя
user_profile = await self.user_service.get_or_create_user(
999999999, "db_test_user", "DB", "Test"
)
if user_profile:
print(f"[SUCCESS] Пользователь создан: {user_profile.first_name}")
print(f" ID: {user_profile.user_id}")
print(f" Репутация: {user_profile.reputation}")
else:
print("[ERROR] Не удалось создать пользователя")
# Тестируем получение топ пользователей
top_users = await self.user_service.get_top_users(5)
print(f"[SUCCESS] Топ пользователей получен: {len(top_users)} записей")
# Тестируем обновление активности
activity_result = await self.user_service.update_user_activity(999999999, -1001234567890)
print(f"[SUCCESS] Активность обновлена: {activity_result}")
except Exception as e:
print(f"[ERROR] Ошибка базы данных: {e}")
def generate_report(self):
"""Генерация отчета о тестировании"""
print("\n" + "="*60)
print("ОТЧЕТ О ТЕСТИРОВАНИИ")
print("="*60)
total_commands = len(self.results['commands'])
successful_commands = len([r for r in self.results['commands'] if r['success']])
total_callbacks = len(self.results['callbacks'])
successful_callbacks = len([r for r in self.results['callbacks'] if r['success']])
total_errors = len(self.results['errors'])
print(f"Команды: {successful_commands}/{total_commands} успешных")
print(f"Callback кнопки: {successful_callbacks}/{total_callbacks} успешных")
print(f"Ошибок: {total_errors}")
# Подробный отчет по командам
print("\nДЕТАЛЬНЫЙ ОТЧЕТ ПО КОМАНДАМ:")
for result in self.results['commands']:
status = "SUCCESS" if result['success'] else "ERROR"
print(f" {result['command']:<20} | {status:<8} | {result['execution_time']:.3f}с")
# Подробный отчет по callback кнопкам
print("\nДЕТАЛЬНЫЙ ОТЧЕТ ПО CALLBACK КНОПКАМ:")
for result in self.results['callbacks']:
status = "SUCCESS" if result['success'] else "ERROR"
print(f" {result['callback']:<20} | {status:<8} | {result['execution_time']:.3f}с")
# Отчет об ошибках
if self.results['errors']:
print("\nОШИБКИ:")
for error in self.results['errors']:
if 'command' in error:
print(f" Команда {error['command']}: {error['error']}")
else:
print(f" Callback {error['callback']}: {error['error']}")
# Итоговая оценка
total_tests = total_commands + total_callbacks
successful_tests = successful_commands + successful_callbacks
success_rate = (successful_tests / total_tests * 100) if total_tests > 0 else 0
print(f"\nОБЩИЙ РЕЗУЛЬТАТ:")
print(f"Всего тестов: {total_tests}")
print(f"Успешных: {successful_tests}")
print(f"Процент успеха: {success_rate:.1f}%")
if success_rate >= 90:
print("ОЦЕНКА: ОТЛИЧНО - Бот готов к работе!")
elif success_rate >= 70:
print("ОЦЕНКА: ХОРОШО - Есть небольшие проблемы")
else:
print("ОЦЕНКА: ТРЕБУЕТ УЛУЧШЕНИЙ - Много ошибок")
async def run_all_tests(self):
"""Запуск всех тестов"""
print("НАЧАЛО КОМПЛЕКСНОГО ТЕСТИРОВАНИЯ ТЕЛЕГРАМ-БОТА")
print("=" * 70)
# Тестируем команды
await self.run_command_tests()
# Тестируем callback кнопки
await self.run_callback_tests()
# Тестируем базу данных
await self.test_database_operations()
# Генерируем отчет
self.generate_report()
print("\n" + "="*70)
print("ТЕСТИРОВАНИЕ ЗАВЕРШЕНО")
async def main():
"""Главная функция"""
# Создаем и запускаем тестовую систему
test_suite = ComprehensiveTestSuite()
await test_suite.run_all_tests()
if __name__ == "__main__":
asyncio.run(main())