235 lines
7.4 KiB
Python
235 lines
7.4 KiB
Python
import pytest
|
||
import asyncio
|
||
import os
|
||
import sys
|
||
from unittest.mock import Mock, AsyncMock, patch
|
||
from aiogram.types import Message, User, Chat
|
||
from aiogram.fsm.context import FSMContext
|
||
|
||
from database.db import BotDB
|
||
|
||
# Импортируем моки в самом начале
|
||
import tests.mocks
|
||
|
||
|
||
@pytest.fixture(scope="session")
|
||
def event_loop():
|
||
"""Создает event loop для асинхронных тестов"""
|
||
loop = asyncio.get_event_loop_policy().new_event_loop()
|
||
yield loop
|
||
loop.close()
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_message():
|
||
"""Создает базовый мок сообщения для тестов"""
|
||
message = Mock(spec=Message)
|
||
message.from_user = Mock(spec=User)
|
||
message.from_user.id = 123456
|
||
message.from_user.full_name = "Test User"
|
||
message.from_user.username = "testuser"
|
||
message.from_user.first_name = "Test"
|
||
message.from_user.is_bot = False
|
||
message.from_user.language_code = "ru"
|
||
message.chat = Mock(spec=Chat)
|
||
message.chat.id = 123456
|
||
message.chat.type = "private"
|
||
message.message_id = 1
|
||
message.text = "/start"
|
||
message.forward = AsyncMock()
|
||
message.answer = AsyncMock()
|
||
message.answer_sticker = AsyncMock()
|
||
message.bot.send_message = AsyncMock()
|
||
return message
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_state():
|
||
"""Создает мок состояния FSM для тестов"""
|
||
state = Mock(spec=FSMContext)
|
||
state.set_state = AsyncMock()
|
||
state.get_state = AsyncMock(return_value="START")
|
||
return state
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_db():
|
||
"""Создает мок базы данных для тестов"""
|
||
db = Mock(spec=BotDB)
|
||
db.user_exists = Mock(return_value=False)
|
||
db.add_new_user_in_db = Mock()
|
||
db.update_date_for_user = Mock()
|
||
db.update_username_and_full_name = Mock()
|
||
db.add_post_in_db = Mock()
|
||
db.update_info_about_stickers = Mock()
|
||
db.add_new_message_in_db = Mock()
|
||
db.get_info_about_stickers = Mock(return_value=False)
|
||
db.get_username_and_full_name = Mock(return_value=("testuser", "Test User"))
|
||
return db
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_bot():
|
||
"""Создает мок бота для тестов"""
|
||
bot = AsyncMock()
|
||
bot.send_message = AsyncMock()
|
||
bot.delete_webhook = AsyncMock()
|
||
return bot
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_dispatcher():
|
||
"""Создает мок диспетчера для тестов"""
|
||
dispatcher = AsyncMock()
|
||
dispatcher.include_routers = Mock()
|
||
dispatcher.start_polling = AsyncMock()
|
||
return dispatcher
|
||
|
||
|
||
@pytest.fixture
|
||
def test_settings():
|
||
"""Возвращает тестовые настройки"""
|
||
return {
|
||
'Telegram': {
|
||
'bot_token': 'test_token_123',
|
||
'preview_link': False,
|
||
'group_for_posts': '-1001234567890',
|
||
'group_for_message': '-1001234567891',
|
||
'main_public': '-1001234567892',
|
||
'group_for_logs': '-1001234567893',
|
||
'important_logs': '-1001234567894'
|
||
},
|
||
'Settings': {
|
||
'logs': True,
|
||
'test': False
|
||
}
|
||
}
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_factory(test_settings, mock_db):
|
||
"""Создает мок фабрики зависимостей"""
|
||
factory = Mock()
|
||
factory.settings = test_settings
|
||
factory.get_db = Mock(return_value=mock_db)
|
||
factory.database = mock_db
|
||
return factory
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_photo_message(mock_message):
|
||
"""Создает сообщение с фото для тестов"""
|
||
mock_message.content_type = 'photo'
|
||
mock_message.caption = 'Тестовое фото'
|
||
mock_message.media_group_id = None
|
||
mock_message.photo = [Mock()]
|
||
mock_message.photo[-1].file_id = 'photo_file_id'
|
||
return mock_message
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_video_message(mock_message):
|
||
"""Создает сообщение с видео для тестов"""
|
||
mock_message.content_type = 'video'
|
||
mock_message.caption = 'Тестовое видео'
|
||
mock_message.media_group_id = None
|
||
mock_message.video = Mock()
|
||
mock_message.video.file_id = 'video_file_id'
|
||
return mock_message
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_audio_message(mock_message):
|
||
"""Создает сообщение с аудио для тестов"""
|
||
mock_message.content_type = 'audio'
|
||
mock_message.caption = 'Тестовое аудио'
|
||
mock_message.media_group_id = None
|
||
mock_message.audio = Mock()
|
||
mock_message.audio.file_id = 'audio_file_id'
|
||
return mock_message
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_voice_message(mock_message):
|
||
"""Создает голосовое сообщение для тестов"""
|
||
mock_message.content_type = 'voice'
|
||
mock_message.media_group_id = None
|
||
mock_message.voice = Mock()
|
||
mock_message.voice.file_id = 'voice_file_id'
|
||
return mock_message
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_video_note_message(mock_message):
|
||
"""Создает видеокружок для тестов"""
|
||
mock_message.content_type = 'video_note'
|
||
mock_message.media_group_id = None
|
||
mock_message.video_note = Mock()
|
||
mock_message.video_note.file_id = 'video_note_file_id'
|
||
return mock_message
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_media_group(mock_message):
|
||
"""Создает медиагруппу для тестов"""
|
||
mock_message.media_group_id = 'group_123'
|
||
mock_message.content_type = 'photo'
|
||
album = [mock_message]
|
||
album[0].caption = 'Подпись к медиагруппе'
|
||
return album
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_text_message(mock_message):
|
||
"""Создает текстовое сообщение для тестов"""
|
||
mock_message.content_type = 'text'
|
||
mock_message.text = 'Тестовое текстовое сообщение'
|
||
mock_message.media_group_id = None
|
||
return mock_message
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_document_message(mock_message):
|
||
"""Создает сообщение с документом для тестов"""
|
||
mock_message.content_type = 'document'
|
||
mock_message.media_group_id = None
|
||
return mock_message
|
||
|
||
|
||
# Маркеры для категоризации тестов
|
||
def pytest_configure(config):
|
||
"""Настройка маркеров pytest"""
|
||
config.addinivalue_line(
|
||
"markers", "asyncio: mark test as async"
|
||
)
|
||
config.addinivalue_line(
|
||
"markers", "slow: mark test as slow"
|
||
)
|
||
config.addinivalue_line(
|
||
"markers", "integration: mark test as integration test"
|
||
)
|
||
config.addinivalue_line(
|
||
"markers", "unit: mark test as unit test"
|
||
)
|
||
|
||
|
||
# Автоматическая маркировка тестов
|
||
def pytest_collection_modifyitems(config, items):
|
||
"""Автоматически маркирует тесты по их расположению"""
|
||
for item in items:
|
||
# Маркируем асинхронные тесты
|
||
if "async" in item.name or "Async" in item.name:
|
||
item.add_marker(pytest.mark.asyncio)
|
||
|
||
# Маркируем интеграционные тесты
|
||
if "integration" in item.name.lower() or "Integration" in str(item.cls):
|
||
item.add_marker(pytest.mark.integration)
|
||
|
||
# Маркируем unit тесты
|
||
if "unit" in item.name.lower() or "Unit" in str(item.cls):
|
||
item.add_marker(pytest.mark.unit)
|
||
|
||
# Маркируем медленные тесты
|
||
if "slow" in item.name.lower() or "Slow" in str(item.cls):
|
||
item.add_marker(pytest.mark.slow)
|