Первый коммит

This commit is contained in:
admin
2025-08-30 07:39:44 +07:00
commit d0baf76f8f
86 changed files with 7362 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
from datetime import datetime, timedelta, timezone
import pytest
from sqlalchemy import select, Sequence
from sqlalchemy.ext.asyncio import AsyncSession
from database import User, UserMessage, BotDatabase
@pytest.mark.asyncio
class TestUserStatistics:
"""Тесты для статистики пользователей с полной строгой типизацией"""
async def test_add_user(self, test_db: BotDatabase, test_session: AsyncSession) -> None:
"""
Тест добавления пользователя.
Проверяет, что пользователь создаётся с правильными данными и статусом 'active'.
"""
user_id: int = 111222333
await test_db.add_user(
user_id=user_id,
username="new_user",
full_name="New User"
)
user: User | None = await test_session.get(User, user_id)
assert user is not None
assert user.username == "new_user"
assert user.status.value == "active"
async def test_add_message_creates_user(
self, test_db: BotDatabase, test_session: AsyncSession
) -> None:
"""
Тест, что добавление сообщения создаёт пользователя, если его нет.
Проверяет, что пользователь и сообщение корректно создаются.
"""
user_id: int = 111222333
await test_db.add_message(
user_id=user_id,
message_text="Тестовое сообщение"
)
user: User | None = await test_session.get(User, user_id)
assert user is not None
assert user.status.value == "active"
stmt = select(UserMessage).where(UserMessage.user_id == user_id)
result = await test_session.execute(stmt)
messages: Sequence[UserMessage] = result.scalars().all()
assert len(messages) == 1
assert messages[0].message_text == "Тестовое сообщение"
async def test_message_stats_calculation(
self, test_db: BotDatabase, test_user_with_messages: int
) -> None:
"""
Тест расчёта статистики сообщений пользователя.
Проверяет корректность статистики по дням, неделям, месяцам и общему количеству сообщений.
"""
user_id: int = test_user_with_messages
# Получаем статистику
day: int
week: int
month: int
total: int
day, week, month, total = await test_db.get_message_stats(user_id)
assert total >= 10, f"Ожидается минимум 10 сообщений, получено {total}"
assert day >= 0
assert week >= 0
assert month >= 0
assert total >= 0
assert day <= week <= month <= total
async def test_message_stats_with_dates(
self, test_db: BotDatabase, test_user: int
) -> None:
"""
Тест статистики с конкретными известными датами сообщений.
Проверяет подсчёт сообщений за день, неделю, месяц и общее количество.
"""
user_id: int = test_user
now: datetime = datetime.now(timezone.utc)
# Очищаем старые сообщения
async with test_db.session_factory() as session:
stmt = select(UserMessage).where(UserMessage.user_id == user_id)
result = await session.execute(stmt)
old_messages: Sequence[UserMessage] = result.scalars().all()
for msg in old_messages:
await session.delete(msg)
await session.commit()
# Создаём сообщения с фиксированными датами
test_messages: list[tuple[datetime, str]] = [
(now - timedelta(days=45), "45 дней назад"),
(now - timedelta(days=30), "30 дней назад"),
(now - timedelta(days=15), "15 дней назад"),
(now - timedelta(days=7), "7 дней назад"),
(now - timedelta(days=3), "3 дня назад"),
(now - timedelta(hours=6), "6 часов назад"),
(now, "сейчас")
]
for date, text in test_messages:
await test_db.add_message(user_id, text, date)
day: int
week: int
month: int
total: int
day, week, month, total = await test_db.get_message_stats(user_id)
assert total == 7, f"Ожидалось 7 сообщений, получено {total}"
day_start: datetime = now.replace(hour=0, minute=0, second=0, microsecond=0)
expected_day: int = sum(1 for date, _ in test_messages if date >= day_start)
assert day == expected_day, f"За день: ожидалось {expected_day}, получено {day}"
monday: datetime = (now - timedelta(days=now.weekday())).replace(hour=0, minute=0, second=0, microsecond=0)
expected_week: int = sum(1 for date, _ in test_messages if date >= monday)
assert week == expected_week, f"За неделю: ожидалось {expected_week}, получено {week}"
month_start: datetime = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
expected_month: int = sum(1 for date, _ in test_messages if date >= month_start)
assert month == expected_month, f"За месяц: ожидалось {expected_month}, получено {month}"
async def test_empty_user_stats(self, test_db: BotDatabase) -> None:
"""
Тест статистики для пользователя без сообщений.
Все значения должны быть равны нулю.
"""
user_id: int = 0o00111222
await test_db.add_user(user_id, "empty_user", "Empty User")
day: int
week: int
month: int
total: int
day, week, month, total = await test_db.get_message_stats(user_id)
assert day == 0
assert week == 0
assert month == 0
assert total == 0
async def test_user_management(self, test_db: BotDatabase) -> None:
"""
Тест управления пользователями.
Проверяет добавление, назначение админа, бан/разбан и возврат статуса пользователя.
"""
user_id: int = 555666777
# Добавление пользователя
await test_db.add_user(user_id, "managed_user", "Managed User")
async with test_db.session_factory() as session:
user: User | None = await session.get(User, user_id)
assert user is not None
assert user.status.value == "active"
# Назначение админом
await test_db.set_admin(user_id, True)
async with test_db.session_factory() as session:
user = await session.get(User, user_id)
assert user is not None
assert user.status.value == "admin"
# Бан пользователя
await test_db.ban_user(user_id)
async with test_db.session_factory() as session:
user = await session.get(User, user_id)
assert user is not None
assert user.status.value == "banned"
# Разбан
await test_db.unban_user(user_id)
async with test_db.session_factory() as session:
user = await session.get(User, user_id)
assert user is not None
assert user.status.value == "active"
# Снятие админки
await test_db.set_admin(user_id, False)
async with test_db.session_factory() as session:
user = await session.get(User, user_id)
assert user is not None
assert user.status.value == "active"