mirror of
https://github.com/FerraSoft/bottohelp.git
synced 2026-08-06 21:55:03 +00:00
Подготовка к релизу
This commit is contained in:
@@ -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())
|
||||
Reference in New Issue
Block a user