style: isort + black

This commit is contained in:
2026-02-02 00:13:33 +03:00
parent 5f66c86d99
commit 561c9074dd
86 changed files with 8459 additions and 5793 deletions

View File

@@ -3,13 +3,14 @@ from datetime import datetime
from unittest.mock import AsyncMock, MagicMock, Mock, patch
import pytest
from database.models import BlacklistUser
from database.repositories.blacklist_repository import BlacklistRepository
class TestBlacklistRepository:
"""Тесты для BlacklistRepository"""
@pytest.fixture
def mock_db_connection(self):
"""Мок для DatabaseConnection"""
@@ -18,18 +19,20 @@ class TestBlacklistRepository:
mock_connection._execute_query_with_result = AsyncMock()
mock_connection.logger = Mock()
return mock_connection
@pytest.fixture
def blacklist_repository(self, mock_db_connection):
"""Экземпляр BlacklistRepository для тестов"""
# Патчим наследование от DatabaseConnection
with patch.object(BlacklistRepository, '__init__', return_value=None):
with patch.object(BlacklistRepository, "__init__", return_value=None):
repo = BlacklistRepository()
repo._execute_query = mock_db_connection._execute_query
repo._execute_query_with_result = mock_db_connection._execute_query_with_result
repo._execute_query_with_result = (
mock_db_connection._execute_query_with_result
)
repo.logger = mock_db_connection.logger
return repo
@pytest.fixture
def sample_blacklist_user(self):
"""Тестовый пользователь в черном списке"""
@@ -40,7 +43,7 @@ class TestBlacklistRepository:
created_at=int(time.time()),
ban_author=999,
)
@pytest.fixture
def sample_blacklist_user_permanent(self):
"""Тестовый пользователь с постоянным баном"""
@@ -51,144 +54,171 @@ class TestBlacklistRepository:
created_at=int(time.time()),
ban_author=None,
)
@pytest.mark.asyncio
async def test_create_tables(self, blacklist_repository):
"""Тест создания таблицы черного списка"""
await blacklist_repository.create_tables()
# Проверяем, что метод вызван
blacklist_repository._execute_query.assert_called()
calls = blacklist_repository._execute_query.call_args_list
# Проверяем, что создается таблица с правильной структурой
create_table_call = calls[0]
assert "CREATE TABLE IF NOT EXISTS blacklist" in create_table_call[0][0]
assert "user_id INTEGER NOT NULL PRIMARY KEY" in create_table_call[0][0]
assert "message_for_user TEXT" in create_table_call[0][0]
assert "date_to_unban INTEGER" in create_table_call[0][0]
assert "created_at INTEGER DEFAULT (strftime('%s', 'now'))" in create_table_call[0][0]
assert "FOREIGN KEY (user_id) REFERENCES our_users (user_id) ON DELETE CASCADE" in create_table_call[0][0]
assert (
"created_at INTEGER DEFAULT (strftime('%s', 'now'))"
in create_table_call[0][0]
)
assert (
"FOREIGN KEY (user_id) REFERENCES our_users (user_id) ON DELETE CASCADE"
in create_table_call[0][0]
)
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with("Таблица черного списка создана")
blacklist_repository.logger.info.assert_called_once_with(
"Таблица черного списка создана"
)
@pytest.mark.asyncio
async def test_add_user(self, blacklist_repository, sample_blacklist_user):
"""Тест добавления пользователя в черный список"""
await blacklist_repository.add_user(sample_blacklist_user)
# Проверяем, что метод вызван с правильными параметрами
blacklist_repository._execute_query.assert_called_once()
call_args = blacklist_repository._execute_query.call_args
# Проверяем SQL запрос (учитываем форматирование)
sql_query = call_args[0][0].replace('\n', ' ').replace(' ', ' ').replace(' ', ' ').strip()
sql_query = (
call_args[0][0]
.replace("\n", " ")
.replace(" ", " ")
.replace(" ", " ")
.strip()
)
expected_sql = "INSERT INTO blacklist (user_id, message_for_user, date_to_unban, ban_author) VALUES (?, ?, ?, ?)"
assert sql_query == expected_sql
# Проверяем параметры
assert call_args[0][1] == (12345, "Нарушение правил", sample_blacklist_user.date_to_unban, 999)
assert call_args[0][1] == (
12345,
"Нарушение правил",
sample_blacklist_user.date_to_unban,
999,
)
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Пользователь добавлен в черный список: user_id=12345"
)
@pytest.mark.asyncio
async def test_add_user_permanent_ban(self, blacklist_repository, sample_blacklist_user_permanent):
async def test_add_user_permanent_ban(
self, blacklist_repository, sample_blacklist_user_permanent
):
"""Тест добавления пользователя с постоянным баном"""
await blacklist_repository.add_user(sample_blacklist_user_permanent)
call_args = blacklist_repository._execute_query.call_args
assert call_args[0][1] == (67890, "Постоянный бан", None, None)
blacklist_repository.logger.info.assert_called_once_with(
"Пользователь добавлен в черный список: user_id=67890"
)
@pytest.mark.asyncio
async def test_remove_user_success(self, blacklist_repository):
"""Тест успешного удаления пользователя из черного списка"""
await blacklist_repository.remove_user(12345)
# Проверяем, что метод вызван с правильными параметрами
blacklist_repository._execute_query.assert_called_once()
call_args = blacklist_repository._execute_query.call_args
assert call_args[0][0] == "DELETE FROM blacklist WHERE user_id = ?"
assert call_args[0][1] == (12345,)
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Пользователь с идентификатором 12345 успешно удален из черного списка."
)
@pytest.mark.asyncio
async def test_remove_user_failure(self, blacklist_repository):
"""Тест неудачного удаления пользователя из черного списка"""
# Симулируем ошибку при удалении
blacklist_repository._execute_query.side_effect = Exception("Database error")
result = await blacklist_repository.remove_user(12345)
# Проверяем, что возвращается False при ошибке
assert result is False
# Проверяем логирование ошибки
blacklist_repository.logger.error.assert_called_once()
error_log = blacklist_repository.logger.error.call_args[0][0]
assert "Ошибка удаления пользователя с идентификатором 12345" in error_log
assert "Database error" in error_log
@pytest.mark.asyncio
async def test_user_exists_true(self, blacklist_repository):
"""Тест проверки существования пользователя (пользователь существует)"""
# Симулируем результат запроса - пользователь найден
blacklist_repository._execute_query_with_result.return_value = [(1,)]
result = await blacklist_repository.user_exists(12345)
# Проверяем, что возвращается True
assert result is True
# Проверяем, что метод вызван с правильными параметрами
blacklist_repository._execute_query_with_result.assert_called_once()
call_args = blacklist_repository._execute_query_with_result.call_args
assert call_args[0][0] == "SELECT 1 FROM blacklist WHERE user_id = ?"
assert call_args[0][1] == (12345,)
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Существует ли пользователь: user_id=12345 Итог: [(1,)]"
)
@pytest.mark.asyncio
async def test_user_exists_false(self, blacklist_repository):
"""Тест проверки существования пользователя (пользователь не существует)"""
# Симулируем результат запроса - пользователь не найден
blacklist_repository._execute_query_with_result.return_value = []
result = await blacklist_repository.user_exists(12345)
# Проверяем, что возвращается False
assert result is False
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Существует ли пользователь: user_id=12345 Итог: []"
)
@pytest.mark.asyncio
async def test_get_user_success(self, blacklist_repository):
"""Тест успешного получения пользователя по ID"""
# Симулируем результат запроса
mock_row = (12345, "Нарушение правил", int(time.time()) + 86400, int(time.time()), 111)
mock_row = (
12345,
"Нарушение правил",
int(time.time()) + 86400,
int(time.time()),
111,
)
blacklist_repository._execute_query_with_result.return_value = [mock_row]
result = await blacklist_repository.get_user(12345)
# Проверяем, что возвращается правильный объект
assert result is not None
assert result.user_id == 12345
@@ -196,37 +226,40 @@ class TestBlacklistRepository:
assert result.date_to_unban == mock_row[2]
assert result.created_at == mock_row[3]
assert result.ban_author == mock_row[4]
# Проверяем, что метод вызван с правильными параметрами
blacklist_repository._execute_query_with_result.assert_called_once()
call_args = blacklist_repository._execute_query_with_result.call_args
assert "SELECT user_id, message_for_user, date_to_unban, created_at, ban_author" in call_args[0][0]
assert (
"SELECT user_id, message_for_user, date_to_unban, created_at, ban_author"
in call_args[0][0]
)
assert call_args[0][1] == (12345,)
@pytest.mark.asyncio
async def test_get_user_not_found(self, blacklist_repository):
"""Тест получения пользователя по ID (пользователь не найден)"""
# Симулируем результат запроса - пользователь не найден
blacklist_repository._execute_query_with_result.return_value = []
result = await blacklist_repository.get_user(12345)
# Проверяем, что возвращается None
assert result is None
@pytest.mark.asyncio
async def test_get_all_users_with_limits(self, blacklist_repository):
"""Тест получения пользователей с лимитами"""
# Симулируем результат запроса
mock_rows = [
(12345, "Нарушение правил", int(time.time()) + 86400, int(time.time())),
(67890, "Постоянный бан", None, int(time.time()) - 86400)
(67890, "Постоянный бан", None, int(time.time()) - 86400),
]
blacklist_repository._execute_query_with_result.return_value = mock_rows
result = await blacklist_repository.get_all_users(offset=0, limit=10)
# Проверяем, что возвращается правильный список
assert len(result) == 2
assert result[0].user_id == 12345
@@ -234,188 +267,211 @@ class TestBlacklistRepository:
assert result[1].user_id == 67890
assert result[1].message_for_user == "Постоянный бан"
assert result[1].date_to_unban is None
# Проверяем, что метод вызван с правильными параметрами
blacklist_repository._execute_query_with_result.assert_called_once()
call_args = blacklist_repository._execute_query_with_result.call_args
# Нормализуем SQL запрос (убираем лишние пробелы и переносы строк)
actual_query = ' '.join(call_args[0][0].split())
actual_query = " ".join(call_args[0][0].split())
expected_query = "SELECT user_id, message_for_user, date_to_unban, created_at, ban_author FROM blacklist LIMIT ?, ?"
assert actual_query == expected_query
assert call_args[0][1] == (0, 10)
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Получен список пользователей в черном списке (offset=0, limit=10): 2"
)
@pytest.mark.asyncio
async def test_get_all_users_no_limit(self, blacklist_repository):
"""Тест получения всех пользователей без лимитов"""
# Симулируем результат запроса (теперь включает ban_author)
mock_rows = [
(12345, "Нарушение правил", int(time.time()) + 86400, int(time.time()), 999),
(67890, "Постоянный бан", None, int(time.time()) - 86400, None)
(
12345,
"Нарушение правил",
int(time.time()) + 86400,
int(time.time()),
999,
),
(67890, "Постоянный бан", None, int(time.time()) - 86400, None),
]
blacklist_repository._execute_query_with_result.return_value = mock_rows
result = await blacklist_repository.get_all_users_no_limit()
# Проверяем, что возвращается правильный список
assert len(result) == 2
# Проверяем, что метод вызван без лимитов
blacklist_repository._execute_query_with_result.assert_called_once()
call_args = blacklist_repository._execute_query_with_result.call_args
# Нормализуем SQL запрос (убираем лишние пробелы и переносы строк)
actual_query = ' '.join(call_args[0][0].split())
actual_query = " ".join(call_args[0][0].split())
expected_query = "SELECT user_id, message_for_user, date_to_unban, created_at, ban_author FROM blacklist"
assert actual_query == expected_query
# Проверяем, что параметры пустые (без лимитов)
assert len(call_args[0]) == 1 # Только SQL запрос, без параметров
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Получен список всех пользователей в черном списке: 2"
)
@pytest.mark.asyncio
async def test_get_users_for_unblock_today(self, blacklist_repository):
"""Тест получения пользователей для разблокировки сегодня"""
current_timestamp = int(time.time())
# Симулируем результат запроса - пользователи с истекшим сроком
mock_rows = [(12345,), (67890,)]
blacklist_repository._execute_query_with_result.return_value = mock_rows
result = await blacklist_repository.get_users_for_unblock_today(current_timestamp)
result = await blacklist_repository.get_users_for_unblock_today(
current_timestamp
)
# Проверяем, что возвращается правильный словарь
assert len(result) == 2
assert 12345 in result
assert 67890 in result
assert result[12345] == 12345
assert result[67890] == 67890
# Проверяем, что метод вызван с правильными параметрами
blacklist_repository._execute_query_with_result.assert_called_once()
call_args = blacklist_repository._execute_query_with_result.call_args
assert call_args[0][0] == "SELECT user_id FROM blacklist WHERE date_to_unban IS NOT NULL AND date_to_unban <= ?"
assert (
call_args[0][0]
== "SELECT user_id FROM blacklist WHERE date_to_unban IS NOT NULL AND date_to_unban <= ?"
)
assert call_args[0][1] == (current_timestamp,)
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Получен список пользователей для разблокировки: {12345: 12345, 67890: 67890}"
)
@pytest.mark.asyncio
async def test_get_users_for_unblock_today_empty(self, blacklist_repository):
"""Тест получения пользователей для разблокировки (пустой результат)"""
current_timestamp = int(time.time())
# Симулируем пустой результат запроса
blacklist_repository._execute_query_with_result.return_value = []
result = await blacklist_repository.get_users_for_unblock_today(current_timestamp)
result = await blacklist_repository.get_users_for_unblock_today(
current_timestamp
)
# Проверяем, что возвращается пустой словарь
assert result == {}
# Проверяем логирование
blacklist_repository.logger.info.assert_called_once_with(
"Получен список пользователей для разблокировки: {}"
)
@pytest.mark.asyncio
async def test_get_count(self, blacklist_repository):
"""Тест получения количества пользователей в черном списке"""
# Симулируем результат запроса
blacklist_repository._execute_query_with_result.return_value = [(5,)]
result = await blacklist_repository.get_count()
# Проверяем, что возвращается правильное количество
assert result == 5
# Проверяем, что метод вызван с правильными параметрами
blacklist_repository._execute_query_with_result.assert_called_once()
call_args = blacklist_repository._execute_query_with_result.call_args
assert call_args[0][0] == "SELECT COUNT(*) FROM blacklist"
# Проверяем, что параметры пустые
assert len(call_args[0]) == 1 # Только SQL запрос, без параметров
@pytest.mark.asyncio
async def test_get_count_zero(self, blacklist_repository):
"""Тест получения количества пользователей (0 пользователей)"""
# Симулируем пустой результат запроса
blacklist_repository._execute_query_with_result.return_value = []
result = await blacklist_repository.get_count()
# Проверяем, что возвращается 0
assert result == 0
@pytest.mark.asyncio
async def test_get_count_none_result(self, blacklist_repository):
"""Тест получения количества пользователей (None результат)"""
# Симулируем None результат запроса
blacklist_repository._execute_query_with_result.return_value = None
result = await blacklist_repository.get_count()
# Проверяем, что возвращается 0
assert result == 0
@pytest.mark.asyncio
async def test_error_handling_in_get_user(self, blacklist_repository):
"""Тест обработки ошибок при получении пользователя"""
# Симулируем ошибку базы данных
blacklist_repository._execute_query_with_result.side_effect = Exception("Database connection failed")
blacklist_repository._execute_query_with_result.side_effect = Exception(
"Database connection failed"
)
# Проверяем, что исключение пробрасывается
with pytest.raises(Exception) as exc_info:
await blacklist_repository.get_user(12345)
assert "Database connection failed" in str(exc_info.value)
@pytest.mark.asyncio
async def test_error_handling_in_get_all_users(self, blacklist_repository):
"""Тест обработки ошибок при получении всех пользователей"""
# Симулируем ошибку базы данных
blacklist_repository._execute_query_with_result.side_effect = Exception("Database connection failed")
blacklist_repository._execute_query_with_result.side_effect = Exception(
"Database connection failed"
)
# Проверяем, что исключение пробрасывается
with pytest.raises(Exception) as exc_info:
await blacklist_repository.get_all_users()
assert "Database connection failed" in str(exc_info.value)
@pytest.mark.asyncio
async def test_error_handling_in_get_count(self, blacklist_repository):
"""Тест обработки ошибок при получении количества"""
# Симулируем ошибку базы данных
blacklist_repository._execute_query_with_result.side_effect = Exception("Database connection failed")
blacklist_repository._execute_query_with_result.side_effect = Exception(
"Database connection failed"
)
# Проверяем, что исключение пробрасывается
with pytest.raises(Exception) as exc_info:
await blacklist_repository.get_count()
assert "Database connection failed" in str(exc_info.value)
@pytest.mark.asyncio
async def test_error_handling_in_get_users_for_unblock_today(self, blacklist_repository):
async def test_error_handling_in_get_users_for_unblock_today(
self, blacklist_repository
):
"""Тест обработки ошибок при получении пользователей для разблокировки"""
# Симулируем ошибку базы данных
blacklist_repository._execute_query_with_result.side_effect = Exception("Database connection failed")
blacklist_repository._execute_query_with_result.side_effect = Exception(
"Database connection failed"
)
# Проверяем, что исключение пробрасывается
with pytest.raises(Exception) as exc_info:
await blacklist_repository.get_users_for_unblock_today(int(time.time()))
assert "Database connection failed" in str(exc_info.value)
# TODO: 20-й тест - test_integration_workflow
@@ -426,7 +482,7 @@ class TestBlacklistRepository:
# 4. Получение общего количества пользователей
# 5. Удаление пользователя из черного списка
# 6. Проверка, что пользователь больше не существует
#
#
# Проблема: тест падает из-за сложности мокирования возвращаемых значений
# при создании объектов BlacklistUser из результатов запросов к БД.
# Требует более сложной настройки моков для корректной работы.