guild.channels содержит все типы включая CategoryChannel. Категории — это контейнеры для группировки, а не каналы. Изменено: - commands/stats.py: filter по isinstance(CategoryChannel) - console_commands/stats.py: аналогичный фильтр - test_commands_stats.py: тест test_stats_excludes_categories - Итого: 234 теста
119 lines
4.3 KiB
Python
119 lines
4.3 KiB
Python
"""Тесты для команды !stats."""
|
|
import pytest
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
|
|
class TestStatsCommand:
|
|
"""Тесты Discord-команды stats."""
|
|
|
|
def _make_mock_guild(self, channel_count=5, member_count=100):
|
|
"""Создать mock-сервер."""
|
|
guild = MagicMock()
|
|
guild.channels = [MagicMock() for _ in range(channel_count)]
|
|
guild.member_count = member_count
|
|
return guild
|
|
|
|
async def test_stats_sends_embed(self):
|
|
"""Команда stats отправляет embed-сообщение."""
|
|
from commands.stats import Stats
|
|
|
|
mock_ctx = MagicMock()
|
|
mock_ctx.bot.latency = 0.035
|
|
mock_ctx.bot.guilds = []
|
|
mock_ctx.send = AsyncMock(return_value=None)
|
|
|
|
cog = Stats()
|
|
await cog.stats(cog, mock_ctx)
|
|
|
|
mock_ctx.send.assert_awaited_once()
|
|
call_args = mock_ctx.send.call_args
|
|
embed = call_args[1]["embed"] if call_args[1] else call_args[0][0]
|
|
assert embed.title == "Статистика серверов"
|
|
|
|
async def test_stats_correct_values(self):
|
|
"""Значения серверов, каналов и пользователей считаются верно."""
|
|
from commands.stats import Stats
|
|
|
|
guild1 = self._make_mock_guild(channel_count=10, member_count=200)
|
|
guild2 = self._make_mock_guild(channel_count=5, member_count=50)
|
|
|
|
mock_ctx = MagicMock()
|
|
mock_ctx.bot.latency = 0.035
|
|
mock_ctx.bot.guilds = [guild1, guild2]
|
|
mock_ctx.send = AsyncMock(return_value=None)
|
|
|
|
cog = Stats()
|
|
await cog.stats(cog, mock_ctx)
|
|
|
|
call_args = mock_ctx.send.call_args
|
|
embed = call_args[1]["embed"] if call_args[1] else call_args[0][0]
|
|
|
|
fields = {f.name: f.value for f in embed.fields}
|
|
assert fields["Серверов"] == "2"
|
|
assert fields["Каналов"] == "15"
|
|
assert fields["Пользователей"] == "250"
|
|
assert "35.0 мс" in fields["Пинг"]
|
|
|
|
async def test_stats_empty_guilds(self):
|
|
"""Пустой список серверов не вызывает ошибок."""
|
|
from commands.stats import Stats
|
|
|
|
mock_ctx = MagicMock()
|
|
mock_ctx.bot.latency = 0.050
|
|
mock_ctx.bot.guilds = []
|
|
mock_ctx.send = AsyncMock(return_value=None)
|
|
|
|
cog = Stats()
|
|
await cog.stats(cog, mock_ctx)
|
|
|
|
call_args = mock_ctx.send.call_args
|
|
embed = call_args[1]["embed"] if call_args[1] else call_args[0][0]
|
|
fields = {f.name: f.value for f in embed.fields}
|
|
assert fields["Серверов"] == "0"
|
|
assert fields["Каналов"] == "0"
|
|
assert fields["Пользователей"] == "0"
|
|
|
|
async def test_stats_none_member_count(self):
|
|
"""member_count=None не вызывает ошибок."""
|
|
from commands.stats import Stats
|
|
|
|
guild = self._make_mock_guild(channel_count=3, member_count=None)
|
|
|
|
mock_ctx = MagicMock()
|
|
mock_ctx.bot.latency = 0.040
|
|
mock_ctx.bot.guilds = [guild]
|
|
mock_ctx.send = AsyncMock(return_value=None)
|
|
|
|
cog = Stats()
|
|
await cog.stats(cog, mock_ctx)
|
|
|
|
call_args = mock_ctx.send.call_args
|
|
embed = call_args[1]["embed"] if call_args[1] else call_args[0][0]
|
|
fields = {f.name: f.value for f in embed.fields}
|
|
assert fields["Пользователей"] == "0"
|
|
|
|
async def test_stats_excludes_categories(self):
|
|
"""Категории не входят в счётчик каналов."""
|
|
import discord
|
|
from commands.stats import Stats
|
|
|
|
guild = MagicMock()
|
|
text_ch = MagicMock()
|
|
voice_ch = MagicMock()
|
|
category_ch = MagicMock(spec=discord.CategoryChannel)
|
|
guild.channels = [text_ch, voice_ch, category_ch]
|
|
guild.member_count = 50
|
|
|
|
mock_ctx = MagicMock()
|
|
mock_ctx.bot.latency = 0.040
|
|
mock_ctx.bot.guilds = [guild]
|
|
mock_ctx.send = AsyncMock(return_value=None)
|
|
|
|
cog = Stats()
|
|
await cog.stats(cog, mock_ctx)
|
|
|
|
call_args = mock_ctx.send.call_args
|
|
embed = call_args[1]["embed"] if call_args[1] else call_args[0][0]
|
|
fields = {f.name: f.value for f in embed.fields}
|
|
assert fields["Каналов"] == "2" # text + voice, категория исключена
|