discordBot/tests/test_format_articles.py
deadzilla 4b9bb7e97a Добавить pytest-тесты и конфигурацию
- pytest.ini для конфигурации тестов
- tests/test_pogoda.py — тесты translate_weather, pressure_to_mmhg, wmo_to_russian (93 теста)
- tests/test_fetch_cat.py — тесты fetch_cat (10 тестов)
- tests/test_fetch_rss.py — тесты fetch_rss (20 тестов)
- tests/test_format_articles.py — тесты truncate_title, parse_date, format_articles (24 теста)
- tests/test_fetch_weather.py — тесты fetch_weather, fetch_open_meteo (20 тестов)
- tests/test_commands_pogoda.py — тесты команды !pogoda (13 тестов)
- Обновить AGENTS.md и requirements.txt
2026-05-29 15:45:56 +05:00

230 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import pytest
from utils.news import format_articles, truncate_title, _parse_date
class TestTruncateTitle:
"""Тесты функции truncate_title() — обрезка заголовка."""
@pytest.mark.parametrize(
"title, max_len, expected",
[
("Короткий заголовок", 60, "Короткий заголовок"),
("Заголовок ровно в 60 символов1234567890", 60, "Заголовок ровно в 60 символов1234567890"),
("A" * 80, 60, "A" * 60 + "..."), # ASCII для надёжного сравнения
("", 60, ""),
("A" * 100, 100, "A" * 100),
("A" * 101, 100, "A" * 100 + "..."),
("A" * 50, 100, "A" * 50),
],
)
def test_truncate(self, title, max_len, expected):
"""Проверка обрезки заголовка."""
assert truncate_title(title, max_len) == expected
def test_truncate_default_max_len(self):
"""По умолчанию max_len=60."""
long_title = "A" * 61
result = truncate_title(long_title)
assert result == "A" * 60 + "..."
assert len(result) == 63 # 60 + "..."
class TestParseDate:
"""Тесты функции _parse_date() — парсинг даты из RSS."""
@pytest.mark.parametrize(
"pub_date, expected",
[
("Mon, 28 May 2026 10:00:00 +0000", "28.05.2026"),
("Mon, 28 May 2026 10:00:00 GMT", "28.05.2026"),
("2026-05-28T10:00:00Z", "2026.05.28"),
("2026-12-31T23:59:59Z", "2026.12.31"),
("2026-01-01T00:00:00Z", "2026.01.01"),
],
)
def test_parse_date_known(self, pub_date, expected):
"""Известные форматы даты должны парситься корректно."""
assert _parse_date(pub_date) == expected
@pytest.mark.parametrize(
"pub_date, expected",
[
("", ""),
(None, ""),
],
)
def test_parse_date_empty(self, pub_date, expected):
"""Пустая или None дата должна вернуть пустую строку."""
assert _parse_date(pub_date) == expected
def test_parse_date_invalid(self):
"""Невалидная дата должна вернуть первые 10 символов."""
result = _parse_date("invalid-date-string")
assert result == "invalid.da" # первые 10 символов: 'invalid-da' → 'invalid.da' (replace('-','.'))
class TestFormatArticles:
"""Тесты функции format_articles() — формирование строк для вывода."""
def test_format_articles_normal(self):
"""Нормальный список статей должен вернуть заголовок + 5 статей."""
articles = [
{
"title": "Статья 1",
"link": "https://habr.com/1",
"pub_date": "Mon, 28 May 2026 10:00:00 +0000",
"creator": "Автор 1",
"tags": ["AI"],
},
{
"title": "Статья 2",
"link": "https://habr.com/2",
"pub_date": "Tue, 29 May 2026 12:00:00 +0000",
"creator": "Автор 2",
"tags": ["ML"],
},
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert len(result) == 3 # заголовок + 2 статьи
assert result[0] == "**Заголовок**\n<https://habr.com/feed>"
assert result[1] == "Статья 1\n28.05.2026 <https://habr.com/1>"
assert result[2] == "Статья 2\n29.05.2026 <https://habr.com/2>"
def test_format_articles_limit_to_5(self):
"""Больше 5 статей должно быть обрезано до 5."""
articles = [
{"title": f"Статья {i}", "link": f"https://habr.com/{i}", "pub_date": "Mon, 28 May 2026 10:00:00 +0000", "creator": "", "tags": []}
for i in range(10)
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert len(result) == 6 # заголовок + 5 статей
assert result[-1] == "Статья 4\n28.05.2026 <https://habr.com/4>"
def test_format_articles_empty_list(self):
"""Пустой список должен вернуть только заголовок."""
result = format_articles([], "Заголовок", "https://habr.com/feed")
assert result == ["**Заголовок**\n<https://habr.com/feed>"]
assert len(result) == 1
def test_format_articles_none(self):
"""None должен вызвать TypeError (articles[:5] на None)."""
with pytest.raises(TypeError):
format_articles(None, "Заголовок", "https://habr.com/feed")
def test_format_articles_single_article(self):
"""Одна статья должна быть корректно отформатирована."""
articles = [
{
"title": "Единственная статья",
"link": "https://habr.com/1",
"pub_date": "Mon, 28 May 2026 10:00:00 +0000",
"creator": "Автор",
"tags": ["AI"],
},
]
result = format_articles(articles, "Новости AI", "https://habr.com/ai")
assert len(result) == 2
assert result[0] == "**Новости AI**\n<https://habr.com/ai>"
assert result[1] == "Единственная статья\n28.05.2026 <https://habr.com/1>"
def test_format_articles_long_title_truncated(self):
"""Длинный заголовок должен быть обрезан до 60 символов с '...'."""
long_title = "A" * 100
articles = [
{"title": long_title, "link": "https://habr.com/1", "pub_date": "Mon, 28 May 2026 10:00:00 +0000", "creator": "", "tags": []}
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert len(result[1].split("\n")[0]) == 63 # 60 + "..."
assert result[1].split("\n")[0].endswith("...")
def test_format_articles_short_title_unchanged(self):
"""Короткий заголовок должен остаться без изменений."""
short_title = "Кот"
articles = [
{"title": short_title, "link": "https://habr.com/1", "pub_date": "Mon, 28 May 2026 10:00:00 +0000", "creator": "", "tags": []}
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert result[1].split("\n")[0] == "Кот"
def test_format_articles_exact_60_chars(self):
"""Заголовок ровно 60 символов не должен обрезаться."""
exact_title = "A" * 60
articles = [
{"title": exact_title, "link": "https://habr.com/1", "pub_date": "Mon, 28 May 2026 10:00:00 +0000", "creator": "", "tags": []}
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert result[1].split("\n")[0] == exact_title
assert "..." not in result[1]
def test_format_articles_iso_date(self):
"""Дата в формате ISO должна парситься корректно."""
articles = [
{
"title": "Статья",
"link": "https://habr.com/1",
"pub_date": "2026-05-28T10:00:00Z",
"creator": "",
"tags": [],
},
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert result[1] == "Статья\n2026.05.28 <https://habr.com/1>"
def test_format_articles_empty_date(self):
"""Пустая дата должна быть пустой строкой."""
articles = [
{"title": "Статья", "link": "https://habr.com/1", "pub_date": "", "creator": "", "tags": []}
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert result[1] == "Статья\n <https://habr.com/1>"
def test_format_articles_none_date(self):
"""None дата должна быть пустой строкой."""
articles = [
{"title": "Статья", "link": "https://habr.com/1", "pub_date": None, "creator": "", "tags": []}
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert result[1] == "Статья\n <https://habr.com/1>"
def test_format_articles_empty_link(self):
"""Пустая ссылка должна быть пустой строкой в угловых скобках."""
articles = [
{"title": "Статья", "link": "", "pub_date": "Mon, 28 May 2026 10:00:00 +0000", "creator": "", "tags": []}
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert result[1].endswith(" <>")
def test_format_articles_russian_title(self):
"""Русские заголовки должны корректно отображаться."""
articles = [
{
"title": "Искусственный интеллект в медицине",
"link": "https://habr.com/1",
"pub_date": "Mon, 28 May 2026 10:00:00 +0000",
"creator": "Иван Иванов",
"tags": ["AI", "медицина"],
},
]
result = format_articles(articles, "Новости AI", "https://habr.com/ai")
assert "Искусственный интеллект в медицине" in result[1]
def test_format_articles_exact_5_articles(self):
"""Ровно 5 статей должно быть включено."""
articles = [
{"title": f"Статья {i}", "link": f"https://habr.com/{i}", "pub_date": "Mon, 28 May 2026 10:00:00 +0000", "creator": "", "tags": []}
for i in range(5)
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert len(result) == 6 # заголовок + 5 статей
assert result[-1] == "Статья 4\n28.05.2026 <https://habr.com/4>"
def test_format_articles_6th_article_excluded(self):
"""6-я статья должна быть исключена."""
articles = [
{"title": f"Статья {i}", "link": f"https://habr.com/{i}", "pub_date": "Mon, 28 May 2026 10:00:00 +0000", "creator": "", "tags": []}
for i in range(6)
]
result = format_articles(articles, "Заголовок", "https://habr.com/feed")
assert len(result) == 6 # заголовок + 5 статей
assert "Статья 5" not in result[5]