Files
schedule/tests/test_lessons.py

423 lines
18 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 schedule.lessons import Lesson, parse_lesson_cell
R = "\u27EA" # ⟨
Cc = "\u27EB" # ⟩
def lessons(text):
return [l.to_dict() for l in parse_lesson_cell(text)]
def one(text):
ls = parse_lesson_cell(text)
assert len(ls) == 1, f"ожидалось 1 занятие, got: {ls}"
return ls[0].to_dict()
# --- базовые формы -------------------------------------------------------------
def test_simple_three_lines():
assert one("Математика\nСмирнов А.В.\nауд. 215") == {
"marker": "", "subject": "Математика", "teacher": "Смирнов А.В.",
"room": "ауд. 215", "note": "",
}
def test_two_lines_no_room():
assert one("ТВИМС\nКоролев Г.К") == {
"marker": "", "subject": "ТВИМС", "teacher": "Королев Г.К", "room": "", "note": "",
}
def test_single_word_subject():
assert one("ДАСП") == {
"marker": "", "subject": "ДАСП", "teacher": "", "room": "", "note": "",
}
def test_acronym_subject_not_org():
for subject in ("МАИС", "БЖД", "ООП", "ЯПМТ", "ТВиМС", "ФТД"):
result = one(f"{subject}\nГладков А.Н.\nауд. 207")
assert result["subject"] == subject, subject
assert result["teacher"] == "Гладков А.Н."
def test_multiple_teachers_slash():
result = one("Иностранный язык\nМастакова Н.К./Умнова И.В./Чвягина Т.В.\nауд. 305 / 207")
assert result["teacher"] == "Мастакова Н.К./Умнова И.В./Чвягина Т.В."
assert result["room"] == "ауд. 305 / 207"
def test_subject_lines_join():
result = one("Методы компьютерной лингвистики\nв ИИ - 2\nПарамонов И.В.\nауд. 231")
assert result["subject"] == "Методы компьютерной лингвистики в ИИ - 2"
assert result["teacher"] == "Парамонов И.В."
assert result["room"] == "ауд. 231"
# --- маркеры -------------------------------------------------------------------
@pytest.mark.parametrize(
"raw, expected",
[
("к.в. - 2\nФизика\nИванов И.И.\nауд. 301", "к.в. - 2"),
("к.в.-7\nСети Петри\nБашкин В.А.\nауд. 224", "к.в. - 7"),
("к.в.\nХимия\nПетров П.П.\nауд. 201", "к.в."),
("к.в. - 1 \nОсновы тестирования\nОкопный Марк Олегович\nонлайн", "к.в. - 1"),
("к.в.-2 Распределенные технологии\nКорсаков С.В.\nауд. 201", "к.в. - 2"),
],
)
def test_markers(raw, expected):
assert one(raw)["marker"] == expected
def test_marker_alone_line_then_blank():
ls = lessons("к.в. \n\nОсновы веб-технологий\nЛавровский В.А.\nауд. 210")
assert len(ls) == 1
assert ls[0]["marker"] == "к.в."
assert ls[0]["subject"] == "Основы веб-технологий"
def test_marker_inherited():
ls = lessons("к.в. - 3\nA\nБелов А.А.\nауд. 1\n\nB\nБелов А.А.\nауд. 2")
assert [l["marker"] for l in ls] == ["к.в. - 3", "к.в. - 3"]
# --- аудитории и локации ---------------------------------------------------------
def test_room_normalization():
result = one("Математика\nСмирнов А.В.\nауд312")
assert result["room"] == "ауд. 312"
def test_room_with_building():
result = one("Основы права (л)\nКолпазанова Е.В.\nюридический корпус, 3 этаж ауд. 22\nначало в 16:05")
assert result["subject"] == "Основы права (л)"
assert result["teacher"] == "Колпазанова Е.В."
assert result["room"] == "юридический корпус, 3 этаж ауд. 22"
assert result["note"] == "начало в 16:05"
def test_room_with_time_after():
result = one("Бизнес-аналитика\nЕлин А.С.\nонлайн\nс 17:00 до 20:00\nс 8.09.26")
assert result["room"] == "онлайн"
assert "с 17:00 до 20:00" in result["note"]
assert "с 8.09.26" in result["note"]
def test_room_online_with_time_inside():
result = one("Облачные сервисы\nБегунов А.В.\nонлайн (начало в 14:30)")
assert result["room"] == "онлайн"
assert result["note"] == "начало в 14:30"
def test_room_url():
result = one("Физкультура (онлайн)\nhttps://next.uniyar.ac.ru/course/view.php?id=407")
assert result["subject"] == "Физкультура (онлайн)"
assert result["room"].startswith("https://next.uniyar.ac.ru")
assert result["teacher"] == ""
def test_location_instead_of_room():
result = one("Прикладная физическая культура\nТкач О.С.\nпервый этаж, восточное крыло")
assert result["room"] == "первый этаж, восточное крыло"
assert result["note"] == ""
def test_room_paren_note():
result = one("Базы данных\nПолетаев А.Ю.\nауд. 223 (возможно и 221)")
assert result["room"] == "ауд. 223"
assert result["note"] == "возможно и 221"
def test_room_paren_alternative_kept():
result = one("Сетевые технологии Huawei\nКорсаков С.В.\nауд.201 (221)")
assert result["room"] == "ауд. 201 (221)"
assert result["note"] == ""
# --- преподаватели ---------------------------------------------------------------
def test_full_name_teacher():
result = one("Основы тестирования\nОкопный Марк Олегович (БИФИТ)\nонлайн\nначало в 12:00")
assert result["teacher"] == "Окопный Марк Олегович (БИФИТ)"
assert result["room"] == "онлайн"
assert result["note"] == "начало в 12:00"
def test_full_name_with_company():
result = one("Проектный практикум\nЛабеев Игорь Владимирович (Корус консалтинг)\nначало занятия в 18:30 онлайн\nссылка в эл. университете")
assert result["teacher"] == "Лабеев Игорь Владимирович (Корус консалтинг)"
assert result["room"] == "онлайн"
assert "начало занятия в 18:30" in result["note"]
assert "ссылка в эл. университете" in result["note"]
def test_teacher_with_substitute():
result = one("Параллельное программирование\nМещеряков И.А. (Федулов Д.Д.) (начало пары в 14:05)\nауд.213")
assert result["teacher"] == "Мещеряков И.А. (Федулов Д.Д.)"
assert result["room"] == "ауд. 213"
assert result["note"] == "начало пары в 14:05"
def test_teacher_lecture_marker_kept():
result = one("Теория автоматов\nСмирнов А.В. (л)\nауд.312")
assert result["teacher"] == "Смирнов А.В. (л)"
def test_org_as_teacher():
result = one("Управление ИТ-проектами\nПравоТех\nауд. 309")
assert result["teacher"] == "ПравоТех"
assert result["subject"] == "Управление ИТ-проектами"
def test_single_word_org_in_teacher_position():
result = one("Оценка качества ПО\nХинт")
assert result["teacher"] == "Хинт"
assert result["subject"] == "Оценка качества ПО"
def test_org_as_location():
ls = lessons(
"Сети Петри\nБашкин В.А.\nауд. 224\n\nСовременные инструменты промышленной разработки\nКоновал О.В.\nНПО Криста"
)
second = ls[1]
assert second["teacher"] == "Коновал О.В."
assert second["room"] == "НПО Криста"
def test_teacher_and_room_on_one_line():
result = one("Логические контроллеры\nКузьмин Е.В.ауд. 301 (начало в 12:30)")
assert result["teacher"] == "Кузьмин Е.В."
assert result["room"] == "ауд. 301"
assert result["note"] == "начало в 12:30"
def test_initials_without_space():
result = one("Методы сжатия КрасновМ.В.\nауд.231")
assert result["subject"] == "Методы сжатия"
assert result["teacher"] == "КрасновМ.В."
assert result["room"] == "ауд. 231"
def test_inline_subject_teacher_room():
result = one("Сети Петри Башкин В.А. ауд. 224")
assert result["subject"] == "Сети Петри"
assert result["teacher"] == "Башкин В.А."
assert result["room"] == "ауд. 224"
# --- заметки ---------------------------------------------------------------------
def test_red_note():
assert one(f"Математика\nСмирнов А.В.\nауд. 215\n{R}пара 14.09 не будет{Cc}")["note"] == "пара 14.09 не будет"
def test_red_note_on_room_line():
result = one(f"Русский язык\nШаманова М.В.\nауд.312 {R}с 7.09 по 20.09 пары не будет{Cc}")
assert result["room"] == "ауд. 312"
assert result["note"] == "с 7.09 по 20.09 пары не будет"
def test_red_note_multiline_with_embedded_lesson():
raw = (
"Теория автоматов\nСмирнов А.В. (л)\nауд.312\n"
f"{R}занятия начнутся с 21.09\nИностранный язык\nБугрова Е.И.\n"
f"ауд. 312 у ИТ-22БО 7.09 и 14.09 с 12:30{Cc}"
)
result = one(raw)
assert result["subject"] == "Теория автоматов"
assert result["teacher"] == "Смирнов А.В. (л)"
assert result["room"] == "ауд.312" or result["room"] == "ауд. 312"
assert "занятия начнутся с 21.09" in result["note"]
assert "Бугрова Е.И." in result["note"]
def test_red_note_between_teacher_and_room():
raw = f"Математика\nСмирнов А.В.\n{R}(пара 8.09 не будет)\n{Cc}ауд. 203"
result = one(raw)
assert result["teacher"] == "Смирнов А.В."
assert result["room"] == "ауд. 203"
assert result["note"] == "пара 8.09 не будет"
def test_only_red_text_gives_lesson_with_note():
result = one(f"{R}нет занятий{Cc}")
assert result["note"] == "нет занятий"
def test_date_note_not_room():
result = one("Практика в НПО Криста\nс 9.09.2026")
assert result["subject"] == "Практика в НПО Криста"
assert result["room"] == ""
assert result["note"] == "с 9.09.2026"
# --- несколько занятий в одной ячейке ---------------------------------------------
def test_two_lessons_blank_line():
ls = lessons("Сети Петри\nБашкин В.А.\nауд. 224\n\nСовременные инструменты\nКоновал О.В.\nауд. 301")
assert [l["subject"] for l in ls] == ["Сети Петри", "Современные инструменты"]
assert [l["room"] for l in ls] == ["ауд. 224", "ауд. 301"]
def test_two_lessons_room_subject_border():
ls = lessons("Логические контроллеры\nКузьмин Е.В.ауд. 301 (начало в 12:30)\nЧисленные методы\nГлызин С.Д. ауд. 312")
assert [l["subject"] for l in ls] == ["Логические контроллеры", "Численные методы"]
assert [l["teacher"] for l in ls] == ["Кузьмин Е.В.", "Глызин С.Д."]
assert [l["room"] for l in ls] == ["ауд. 301", "ауд. 312"]
def test_group_tag_after_room_is_note():
result = one("Алгебра и геометрия\nСедов А.Г.\nауд.219\nИТ-11")
assert result["room"] == "ауд. 219"
assert result["note"] == "ИТ-11"
def test_lesson_with_red_between_lessons():
ls = lessons(
"Введение в промышленную разработку\nПарамонов И.В.\n"
f"ауд. 220 {R}2.09 пара отменяется{Cc}\n\n"
"Язык UML и CASE-системы\nЛарина Ю.А.\nауд.210"
)
assert ls[0]["note"] == "2.09 пара отменяется"
assert ls[0]["room"] == "ауд. 220"
assert ls[1]["subject"] == "Язык UML и CASE-системы"
# --- оторвавшиеся пустой строкой преподаватель/аудитория ---------------------------
def test_room_detached_by_blank_line():
# ПИЭ-31БО, вторник: «ауд.210» оторвана пустой строкой от предмета
result = one("Программная инженерия\nЛарина Ю.А.\n\n ауд.210")
assert result["subject"] == "Программная инженерия"
assert result["teacher"] == "Ларина Ю.А."
assert result["room"] == "ауд. 210"
def test_teacher_and_room_detached_by_red_note():
# ИВТ-13БО, четверг: красная заметка снята со своей строки, осталась пустая
raw = f"Практикум по матанализу\n{R}пара для тех кто не ТОП{Cc}\nШабаршина Г.В.\nауд. 219"
result = one(raw)
assert result["subject"] == "Практикум по матанализу"
assert result["teacher"] == "Шабаршина Г.В."
assert result["room"] == "ауд. 219"
assert result["note"] == "пара для тех кто не ТОП"
def test_detached_room_inherits_marker():
ls = lessons("к.в. - 2\nФизика\nИванов И.И.\n\nауд. 301")
assert len(ls) == 1
assert ls[0]["marker"] == "к.в. - 2"
assert ls[0]["room"] == "ауд. 301"
def test_detached_room_kept_if_prev_has_room():
ls = lessons("Физика\nСмирнов А.В.\nауд. 221\n\nауд. 222")
assert len(ls) == 2
assert ls[0]["room"] == "ауд. 221"
def test_detached_teacher_kept_if_prev_has_teacher():
ls = lessons("Физика\nСмирнов А.В.\nауд. 221\n\nПетров П.П.\nауд. 222")
assert len(ls) == 2
assert ls[0]["teacher"] == "Смирнов А.В."
def test_lesson_after_detached_room_starts_fresh():
ls = lessons("Физика\nСмирнов А.В.\n\nауд. 221\n\nХимия\nПетров П.П.\nауд. 222")
assert len(ls) == 2
assert ls[0]["room"] == "ауд. 221"
assert ls[1]["subject"] == "Химия"
# --- пустые и экзотические ----------------------------------------------------------
def test_empty_cell():
assert parse_lesson_cell("") == []
assert parse_lesson_cell(" \n ") == []
def test_cell_with_underscores_subject():
lesson = one("Промышленное программирование\nПарамонов И.В.\nауд. 220")
assert lesson["subject"] == "Промышленное программирование"
def test_lesson_subject_only():
result = one(f"{R}не будет{Cc}")
assert result["subject"] == ""
assert result["note"] == "не будет"
def test_unclosed_paren_in_table():
# в таблице не закрыли скобку вокруг красной заметки
result = one("Основы веб-технологий\nЛавровский В.А. (" + R + "предмет начнется с 8.09)" + Cc + "\nауд. 210")
assert result["teacher"] == "Лавровский В.А."
assert result["room"] == "ауд. 210"
assert result["note"] == "предмет начнется с 8.09"
def test_inline_lesson_after_room_no_blank_line():
raw = (
"к.в. - 2\nАлгоритмы и структуры данных Волченков С.Г. "
+ R + "(14.09 по 30.09 пары нет) " + Cc
+ "ауд.219 \nМетоды сжатия КрасновМ.В. ауд.231"
)
ls = lessons(raw)
assert len(ls) == 2
assert ls[0]["room"] == "ауд. 219"
assert "14.09 по 30.09 пары нет" in ls[0]["note"]
assert ls[1]["subject"] == "Методы сжатия"
assert ls[1]["teacher"] == "КрасновМ.В."
assert ls[1]["room"] == "ауд. 231"
def test_plain_time_paren_line():
result = one("Параллельное программирование (пр)\nМещеряков И.А.\nауд. 213\n(начало пары в 12:30)")
assert result["note"] == "начало пары в 12:30"
def test_full_name_inline_after_subject():
result = one("Основы тестирования веб-приложений Денис Верховцев (Сигма)\nонлайн")
assert result["subject"] == "Основы тестирования веб-приложений"
assert result["teacher"] == "Денис Верховцев (Сигма)"
assert result["room"] == "онлайн"
def test_cell_note_applies_to_all_lessons():
# ПИЭ-13МО, понедельник, 5-я пара: два курса по выбору, заметка о паре
raw = (
"к.в. Управление ИТ-проектами\nЕрофеев Александр Александрович (ПравоТех)\nонлайн\n"
"к.в. Математические методы и модели принятия решения Наука онлайн\n"
+ R + "14.09 пары не будет" + Cc
)
ls = lessons(raw)
assert len(ls) == 2
assert all(l["note"] == "14.09 пары не будет" for l in ls)
assert {l["subject"] for l in ls} == {
"Управление ИТ-проектами",
"Математические методы и модели принятия решения",
}
def test_inline_note_stays_with_its_lesson():
raw = (
"Русский язык\nШаманова М.В.\nауд. 312 " + R + "с 7.09 по 20.09 пары не будет" + Cc
+ "\n\nМатематика\nСмирнов А.В.\nауд. 203"
)
ls = lessons(raw)
assert ls[0]["note"] == "с 7.09 по 20.09 пары не будет"
assert ls[1]["note"] == ""