"""Тесты разбора листов: группы, дни/пары/чётность, индексы, вспомогательные листы.""" from datetime import date import pytest from fixtures import fixture_sheets, make_sheets from schedule import parsing from schedule.errors import ScheduleError @pytest.fixture() def sheets(): return make_sheets(fixture_sheets()) @pytest.fixture() def data(sheets): return parsing.parse_schedule(sheets) def test_hidden_group_excluded(data): assert set(data) == {"ИВТ-11БО", "ИТ-12БО"} def test_semester(data): assert data["ИВТ-11БО"]["semester_until"] == "11.01.27" assert data["ИТ-12БО"]["semester_until"] == "29.12.26" def test_day_period_parity(data): mon = data["ИВТ-11БО"]["days"]["понедельник"] p1 = mon[1] assert p1["time"] == "9:00-10:35" assert p1["ч"] is not None and p1["з"] is not None assert "Математика" in p1["ч"] assert "216" in p1["з"] def test_empty_parity_slot_kept(data): mon = data["ИТ-12БО"]["days"]["понедельник"] assert mon[1]["з"] is None # время на пустой слот подставлено assert mon[1]["time"] == "9:00-10:35" def test_lessons_preparsed(data): mon = data["ИВТ-11БО"]["days"]["понедельник"] lesson = mon[1]["lessons"]["ч"][0] assert lesson["subject"] == "Математика" assert lesson["teacher"] == "Смирнов А.В." assert lesson["room"] == "ауд. 215" assert lesson["note"] == "пара 14.09 не будет" # пустое parity -> None assert data["ИТ-12БО"]["days"]["понедельник"][1]["lessons"]["з"] is None def test_marker_parsed(data): mon_g1 = data["ИВТ-11БО"]["days"]["понедельник"] mon_g2 = data["ИТ-12БО"]["days"]["понедельник"] assert mon_g1[2]["lessons"]["ч"][0]["marker"] == "к.в. - 2" assert mon_g2[2]["lessons"]["з"][0]["marker"] == "к.в." def test_tuesday_only_ch(data): tue = data["ИВТ-11БО"]["days"]["вторник"] assert tue[1]["ч"] and "Биология" in tue[1]["ч"] assert tue[1]["з"] is None def test_missing_main_sheet(sheets): del sheets[parsing.MAIN_SHEET] with pytest.raises(ScheduleError): parsing.parse_schedule(sheets) def test_odd_day_block_warns(caplog): sheets = make_sheets(fixture_sheets()) # уберём вторую строку понедельника (пара 1, з) -> нечётное число строк rows = sheets[parsing.MAIN_SHEET].rows # строки: 0 header, 1 с/по, 2..5 понедельник, 6..7 вторник del rows[3] with caplog.at_level("WARNING"): result = parsing.parse_schedule(sheets) assert any("сдвинуться" in r.message for r in caplog.records) # разбор всё равно завершается assert "ИВТ-11БО" in result def test_week_ranges(sheets): weeks = parsing.extract_week_ranges(sheets) assert len(weeks) == 8 assert weeks[0] == {"parity": "ч", "start": date(2026, 8, 31), "end": date(2026, 9, 6)} assert weeks[1]["parity"] == "з" assert weeks[-2]["parity"] == "ч" def test_current_parity(): sheets = make_sheets(fixture_sheets()) weeks = parsing.extract_week_ranges(sheets) assert parsing.current_parity(weeks, date(2026, 9, 1)) == "ч" assert parsing.current_parity(weeks, date(2026, 9, 9)) == "з" assert parsing.current_parity(weeks, date(2030, 1, 1)) is None def test_teacher_room_index(data): teachers, rooms = parsing.build_teacher_room_index(data) assert set(teachers) == {"Смирнов А.В.", "Иванов И.И.", "Петров П.П.", "Сидорова С.С."} smirnov = teachers["Смирнов А.В."]["понедельник"]["1"] assert len(smirnov["ч"]) == 1 and len(smirnov["з"]) == 1 assert smirnov["ч"][0]["subject"] == "Математика" assert smirnov["ч"][0]["room"] == "ауд. 215" assert smirnov["ч"][0]["groups"] == ["ИВТ-11БО"] petrov_zn = teachers["Петров П.П."]["понедельник"]["2"]["з"] assert petrov_zn[0]["marker"] == "к.в." assert set(rooms) == {"ауд. 215", "ауд. 216", "ауд. 301", "ауд. 220", "ауд. 201"} room_301 = rooms["ауд. 301"]["понедельник"] assert room_301["1"]["ч"][0]["subject"] == "Физика" assert room_301["1"]["ч"][0]["teacher"] == "Иванов И.И." assert room_301["2"]["ч"][0]["groups"] == ["ИВТ-11БО"] def test_day_times(data): times = parsing.build_day_times(data) assert times["понедельник"] == {"1": "9:00-10:35", "2": "10:45-12:20"} assert times["вторник"] == {"1": "9:00-10:35"} def test_group_schedule_shape(data): out = parsing.build_group_schedule(data, "ИВТ-11БО") assert out["group"] == "ИВТ-11БО" assert out["semester_until"] == "11.01.27" p1 = out["days"]["понедельник"]["1"] assert p1["time"] == "9:00-10:35" assert "raw" in p1["ч"] and "lessons" in p1["ч"] assert p1["з"]["lessons"][0]["room"] == "ауд. 216" assert parsing.build_group_schedule(data, "НЕТ-11БО") is None def test_rooms_info(sheets): info = parsing.parse_rooms_info(sheets) assert info == { "ауд. 215": {"room": "ауд. 215", "info": "комп.класс, 12 мест"}, "ауд. 301": {"room": "ауд. 301", "info": "интерактивная панель, 24 места"}, "ауд. 220": {"room": "ауд. 220", "info": "20 мест"}, } def test_teachers_full(sheets): full = parsing.parse_teachers_full(sheets) assert full == { "Смирнов А.В.": "Смирнов Александр Викторович", "Иванов И.И.": "Иванов Иван Иванович", } def test_sort_rooms(): assert parsing.sort_rooms(["ауд. 10", "ауд. 9", "ауд. 100", "зал"]) == [ "ауд. 9", "ауд. 10", "ауд. 100", "зал", ] def test_build_room_schedule(data): _, rooms = parsing.build_teacher_room_index(data) times = parsing.build_day_times(data) out = parsing.build_room_schedule(rooms, "ауд. 301", times) # дни с расписанием плюс дни, где есть время пар (даже без занятий) assert set(out["days"]) == {"понедельник", "вторник"} assert out["days"]["понедельник"]["1"]["ч"][0]["subject"] == "Физика" assert parsing.build_room_schedule(rooms, "ауд. 999", times) is None