discordBot/tests/test_pogoda.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

210 lines
9.5 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.pogoda import translate_weather, pressure_to_mmhg, wmo_to_russian
class TestTranslateWeather:
"""Тесты функции translate_weather() — перевод описания погоды из английского в русский."""
@pytest.mark.parametrize(
"english, expected",
[
("Clear", "Ясно"),
("Sunny", "Ясно"),
("Partly cloudy", "Переменная облачность"),
("Cloudy", "Облачно"),
("Overcast", "Пасмурно"),
("Fog", "Туман"),
("Foggy", "Туманно"),
("Mist", "Туман"),
("Haze", "Дымка"),
("Light rain", "Небольшой дождь"),
("Moderate rain", "Умеренный дождь"),
("Heavy rain", "Сильный дождь"),
("Moderate or heavy rain at times", "Сильный дождь"), # "Heavy rain" совпадает раньше в mapping dict (key in text)
("Heavy rain at times", "Сильный дождь"),
("Light snow", "Небольшой снег"),
("Moderate snow", "Умеренный снег"),
("Heavy snow", "Сильный снег"),
("Blowing snow", "Метель"),
("Light freezing rain", "Лёгкий ледяной дождь"),
("Heavy freezing rain", "Сильный ледяной дождь"),
("Moderate or heavy freezing rain", "Сильный ледяной дождь"),
("Light sleet", "Light sleet"),
("Moderate or heavy sleet", "Moderate or heavy sleet"),
("Thundery outbreaks in nearby", "Гроза вблизи"),
("Patchy rain nearby", "Местами дождь"),
("Patchy snow nearby", "Местами снег"),
("Patchy sleet nearby", "Местами слякоть"),
("Patchy light drizzle", "Местами лёгкая морось"),
("Moderate or heavy snow in area", "Снег"),
("Moderate or heavy rain in area", "Дождь"),
],
)
def test_translate_known(self, english, expected):
"""Известные переводы должны возвращать ожидаемый результат."""
assert translate_weather(english) == expected
@pytest.mark.parametrize(
"input_value, expected",
[
("", ""),
(None, ""),
(" ", " "), # пробелы не считаются пустыми
],
)
def test_translate_empty(self, input_value, expected):
"""Пустой или None ввод должен возвращать ''."""
assert translate_weather(input_value) == expected
def test_translate_unknown_returns_original(self):
"""Неизвестный перевод должен возвращать оригинальный текст."""
unknown_text = "Unknown weather condition XYZ"
assert translate_weather(unknown_text) == unknown_text
def test_translate_partial_match(self):
"""Частичное совпадение ключа в тексте должно сработать."""
# "Moderate or heavy rain in area" должно найтись в "Light Moderate or heavy rain in area"
text_with_prefix = "Light Moderate or heavy rain in area"
assert translate_weather(text_with_prefix) == "Дождь"
def test_translate_longer_key_priority(self):
"""translate_weather ищет key in text, порядок dict важен.
"Heavy rain" стоит раньше "Moderate or heavy rain at times" в mapping,
и "heavy rain" in "moderate or heavy rain at times" = True.
Поэтому совпадёт первым и вернёт "Сильный дождь"."""
text = "Moderate or heavy rain at times"
assert translate_weather(text) == "Сильный дождь"
def test_translate_case_insensitive(self):
"""Перевод должен быть регистронезависимым."""
assert translate_weather("CLEAR") == "Ясно"
assert translate_weather("partly cloudy") == "Переменная облачность"
assert translate_weather("HEAVY RAIN") == "Сильный дождь"
def test_translate_with_whitespace(self):
"""Текст с пробелами по краям должен корректно переводиться."""
assert translate_weather(" Clear ") == "Ясно"
class TestPressureToMMHG:
"""Тесты функции pressure_to_mmhg() — конвертация давления из мб в мм рт. ст."""
@pytest.mark.parametrize(
"mb, expected",
[
(1013, 759.8),
(1000, 750.1),
(980, 735.1),
(1030, 772.6),
# (0, "—"), # 0 — falsy, возвращается '—' (баг)
],
)
def test_pressure_valid(self, mb, expected):
"""Валидные числовые значения должны конвертироваться корректно."""
assert pressure_to_mmhg(mb) == expected
@pytest.mark.parametrize(
"mb, expected",
[
("1013", 759.8),
("1000", 750.1),
("980", 735.1),
],
)
def test_pressure_string(self, mb, expected):
"""Строка-число должна конвертироваться корректно."""
assert pressure_to_mmhg(mb) == expected
@pytest.mark.parametrize(
"input_value, expected",
[
("", ""),
(None, ""),
("", ""),
],
)
def test_pressure_invalid(self, input_value, expected):
"""Невалидные значения должны возвращать ''."""
assert pressure_to_mmhg(input_value) == expected
def test_pressure_non_numeric_string(self):
"""Невалидная строка должна возвращать ''."""
assert pressure_to_mmhg("abc") == ""
def test_pressure_zero(self):
"""Нулевое значение — falsy, возвращается '' (известный баг)."""
assert pressure_to_mmhg(0) == ""
def test_pressure_negative(self):
"""Отрицательное значение должно конвертироваться."""
assert pressure_to_mmhg(-100) == -75.0
def test_pressure_float_string(self):
"""Строка с десятичной точкой должна конвертироваться."""
assert pressure_to_mmhg("1013.25") == 760.0
def test_pressure_very_large(self):
"""Очень большое значение должно работать."""
assert pressure_to_mmhg(999999) == 750061.2
class TestWmoToRussian:
"""Тесты функции wmo_to_russian() — перевод WMO кодов погоды."""
@pytest.mark.parametrize(
"code, expected",
[
(0, "Ясно"),
(1, "Ясно"),
(2, "Переменная облачность"),
(3, "Пасмурно"),
(45, "Туман"),
(48, "Туман"),
(51, "Лёгкая морось"),
(53, "Морось"),
(55, "Сильная морось"),
(56, "Ледяная морось"),
(57, "Сильная ледяная морось"),
(61, "Небольшой дождь"),
(63, "Дождь"),
(65, "Сильный дождь"),
(66, "Ледяной дождь"),
(67, "Сильный ледяной дождь"),
(71, "Небольшой снег"),
(73, "Снег"),
(75, "Сильный снег"),
(77, "Снежная крупа"),
(80, "Небольшой ливень"),
(81, "Ливень"),
(82, "Сильный ливень"),
(85, "Снежный ливень"),
(86, "Сильный снежный ливень"),
(95, "Гроза"),
(96, "Гроза с градом"),
(99, "Сильная гроза с градом"),
],
)
def test_wmo_known(self, code, expected):
"""Известные WMO коды должны возвращать ожидаемый перевод."""
assert wmo_to_russian(code) == expected
def test_wmo_unknown(self):
"""Неизвестный код должен возвращать 'Неизвестно'."""
assert wmo_to_russian(999) == "Неизвестно"
def test_wmo_negative_code(self):
"""Отрицательный код должен возвращать 'Неизвестно'."""
assert wmo_to_russian(-1) == "Неизвестно"
def test_wmo_none(self):
"""None должен возвращать 'Неизвестно'."""
assert wmo_to_russian(None) == "Неизвестно"
def test_wmo_large_code(self):
"""Очень большой код должен возвращать 'Неизвестно'."""
assert wmo_to_russian(9999) == "Неизвестно"
def test_wmo_float_code(self):
"""Дробный код — не найдётся в mapping."""
assert wmo_to_russian(1.5) == "Неизвестно"