Тесты и инфраструктура
- tests/: 104 теста — lessons (все форматы ячеек), xlsx (мержи/скрытые столбцы/красный текст/даты), parsing (группы/недели/индексы), API (TestClient, TTL/modified/stale-while-error, 404/400/502) - xlsx_builder.py: генерация xlsx в памяти для тестов без openpyxl - docker-compose: healthz-хелскчеки (не блокируют старт), SCHEDULE_LINK - Makefile: target test - requirements: закреплённые версии - .gitignore: __pycache__/, .venv/ и т.д.
This commit is contained in:
78
tests/test_xlsx.py
Normal file
78
tests/test_xlsx.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""Тесты чтения xlsx: ячейки, мержи, скрытые столбцы, красный текст, даты."""
|
||||
|
||||
import zipfile
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
|
||||
from fixtures import fixture_sheets, fixture_xlsx, MAIN
|
||||
from schedule.errors import ScheduleError
|
||||
from schedule.xlsx import excel_serial_to_date, parse_workbook
|
||||
|
||||
|
||||
def test_parse_workbook_fixture():
|
||||
sheets = parse_workbook(fixture_xlsx())
|
||||
assert set(sheets) == {"Бакалавры и магистры", "аудитории", "Преподаватели"}
|
||||
|
||||
rows = sheets[MAIN].rows
|
||||
# заголовок группы
|
||||
assert rows[0][6] == "ИВТ-11БО\nсеместр до 11.01.27"
|
||||
# скрытый столбец
|
||||
assert 8 in sheets[MAIN].hidden_cols
|
||||
# дата-серия как число
|
||||
assert rows[2][0] == "46265"
|
||||
# мерж F3:F4 -> значение пары попало во вторую строку
|
||||
assert rows[3][5] == "1\n9:00-\n10:35"
|
||||
assert rows[2][5] == "1\n9:00-\n10:35"
|
||||
|
||||
|
||||
def test_red_runs_marked():
|
||||
sheets = parse_workbook(fixture_xlsx())
|
||||
cell = sheets[MAIN].rows[2][6]
|
||||
assert cell.startswith("Математика\nСмирнов А.В.\nауд. 215\n")
|
||||
assert "\u27EA" in cell and "\u27EB" in cell
|
||||
assert cell.endswith("пара 14.09 не будет\u27EB")
|
||||
|
||||
|
||||
def test_empty_cells_are_empty_strings():
|
||||
sheets = parse_workbook(fixture_xlsx())
|
||||
assert sheets[MAIN].rows[5][6] == ""
|
||||
# все строки одной ширины
|
||||
widths = {len(r) for r in sheets[MAIN].rows}
|
||||
assert len(widths) == 1
|
||||
|
||||
|
||||
def test_bad_zip_raises():
|
||||
with pytest.raises(ScheduleError):
|
||||
parse_workbook(b"this is not an xlsx file")
|
||||
|
||||
|
||||
def test_truncated_zip_raises():
|
||||
good = fixture_xlsx()
|
||||
with pytest.raises(ScheduleError):
|
||||
parse_workbook(good[:20])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"serial, expected",
|
||||
[
|
||||
("46265", date(2026, 8, 31)),
|
||||
(46265, date(2026, 8, 31)),
|
||||
("46278", date(2026, 9, 13)),
|
||||
# до 1900: Excel считает несуществующий 29.02.1900
|
||||
(1, date(1900, 1, 1)),
|
||||
(59, date(1900, 2, 28)),
|
||||
(61, date(1900, 3, 1)),
|
||||
],
|
||||
)
|
||||
def test_excel_serial_to_date(serial, expected):
|
||||
assert excel_serial_to_date(serial) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("bad", ["", "текст", None, "0", "-5", "1,5x"])
|
||||
def test_excel_serial_to_date_invalid(bad):
|
||||
# "1,5x" не парсится; остальные — None
|
||||
if bad == "1,5x":
|
||||
assert excel_serial_to_date(bad) is None
|
||||
else:
|
||||
assert excel_serial_to_date(bad) is None
|
||||
Reference in New Issue
Block a user