РУБРИК · портал

← Ко всем документам

Приложение учителя — тест-кейсы

Ручные тест-кейсы для тестировщика с реальным железом. Опираются только на то, что реально реализовано в mvp/teacher-app/ на момент написания (сверено с PLAN.md, SCENARIOS-COVERAGE.md, кодом экранов src/pages/, серверной частью electron/server/, протоколом protocols/02-student-app--teacher-app.md). Нереализованное помечено «(если реализовано)» или не включено вовсе — список см. в сводке в конце файла.


Стенд тестировщика

Для полного прохождения нужно:

Сброс к чистому состоянию. Закрыть приложение учителя, удалить его локальную базу (путь и команду уточнить в mvp/BUILD.md/README приложения — файл называется как база student-app, rubrick.db, но в профиле teacher-app). Не удалять базу при запущенном приложении.

Как фиксировать находку: шаг → что сделал → что ожидал → что увидел → скриншот → ОС и версия приложения (вкладка нет отдельного «О программе» в коде на момент письма — версия видна на вкладке «Обновления», «Установлена версия …»).

Термины: «отправлено / подтверждено / недоступен» — три состояния доставки команды (протокол 02 §6.6), см. раздел «Управление классом». «Разрешено» / «эффективное значение» — итоговое значение флага после разрешения приоритета ученик > класс > глобально.


Сводная таблица разделов

№РазделКейсов
1Первый запуск и общая рамка приложения4
2Классы и ученики (ростер)15
3Подключение — сопряжение и обнаружение учеников в LAN12
4Управление классом — живые команды8
5Разрешения (feature flags)8
6Курсы и уроки — выдача заданий13
7Код учеников — приём сдач и просмотр6
8Документация / вики3
9Синхронизация с порталом9
10Обновления приложения9
11Офлайн и деградация сети (D-086)8
12Два учителя в одной сети3
13Кроссплатформенность macOS/Windows4
Итого99

1. Первый запуск и общая рамка приложения

TC-001. Первый запуск создаёт локальный сервер и виден статус-бейдж

Приоритет: P1 Предусловия: Чистая база, приложение учителя не запущено. Шаги:

Ожидаемый результат: Сразу после запуска бейдж кратко показывает «Запуск сервера…», затем переходит в «Сервер для учеников доступен» с указанием порта. Приложение не виснет на этапе запуска.

TC-002. Все восемь вкладок открываются без ошибок

Приоритет: P1 Предусловия: Приложение запущено. Шаги:

Ожидаемый результат: Каждая вкладка открывается, показывает свой контент или явное пустое состояние («Пока нет классов», «Курсов пока нет» и т.п.), не белый экран и не зависание.

TC-003. Пустые состояния читаемы и не выглядят как баг

Приоритет: P2 Предусловия: Чистая база, ничего ещё не создано. Шаги:

Ожидаемый результат: Везде понятные подписи-заглушки («Выберите класс слева…», «Выберите класс выше»), не пустая белая область и не текст ошибки.

TC-004. Повторный запуск не запрашивает ничего заново

Приоритет: P3 Предусловия: После TC-001, база не сброшена. Шаги:

Ожидаемый результат: Приложение открывается сразу на вкладке «Классы» с уже созданными данными, сервер поднимается автоматически без участия учителя.


2. Классы и ученики (ростер)

TC-005. Создание класса

Приоритет: P1 Предусловия: Вкладка «Классы». Шаги:

Ожидаемый результат: Класс появляется в списке слева и автоматически выбирается; справа — «Ученики» с пустым списком.

TC-006. Пустое название класса не создаёт класс

Приоритет: P2 Шаги:

Ожидаемый результат: Ошибка «Название класса не может быть пустым», класс не создан.

TC-007. Переименование класса

Приоритет: P2 Предусловия: Есть класс. Шаги:

Ожидаемый результат: Название в списке обновилось.

TC-008. Блокировка/разблокировка класса из списка классов

Приоритет: P2 Предусловия: Есть класс. Шаги:

Ожидаемый результат: После шага 2 у класса появляется бейдж «заблокирован»; если у кого-то из класса идёт программа, перед блокировкой показывается предупреждение. Ученики видят «Причина: Обед» (при пустом поле строки нет). После шага 4 бейдж пропадает.

TC-009. Удаление пустого класса — без предупреждения о потерях

Приоритет: P2 Предусловия: Есть класс без учеников. Шаги:

Ожидаемый результат: Диалог «Удалить класс «...»?» с текстом «Класс пуст — удаление ничего не затронет», кнопка «Удалить». После подтверждения класс исчезает из списка.

TC-010. Удаление класса с учениками — предупреждение называет последствия

Приоритет: P1 Предусловия: Класс с 2+ учениками, у одного есть сохранённая работа (см. раздел 7, или после интеграционного кейса из раздела 3). Шаги:

Ожидаемый результат: Диалог называет класс и число учеников с верным склонением: «В классе «7А» 3 ученика. Они будут удалены вместе с классом и всеми их работами. Это нельзя отменить», кнопка «Удалить класс и учеников» (не просто «Удалить»). После подтверждения класс, его ученики и их работы исчезают; на ноутбуках учеников их профили пропадают из выбора профиля после очередной синхронизации (как при удалении ученика по одному). Это НЕ нативный confirm() браузера — окно не блокирует остальной интерфейс модально на уровне ОС.

TC-011. Добавление ученика и разовый показ PIN

Приоритет: P1 Предусловия: Выбран класс. Шаги:

Ожидаемый результат: После шага 1 ученик появляется в списке; в блоке показан PIN с подписью «Запишите или продиктуйте ученикам сейчас — второй раз PIN не показывается». После шага 3 PIN больше нигде не виден (ни в списке, ни при повторном открытии вкладки) — сохранить его можно было только скриншотом/записью в момент создания.

TC-012. Повторное имя ученика — предупреждение, затем разрешение (тёзки)

Приоритет: P1 Предусловия: В классе уже есть ученик «Иванов Пётр». Шаги:

Ожидаемый результат: После шага 1 — предупреждение «...уже есть в этом классе. Если это другой ребёнок с таким же именем — нажмите «Добавить ученика» ещё раз», карточка не создана. После шага 3 — создаётся вторая карточка с тем же именем (тёзки — это ожидаемо, не баг).

TC-013. Список учеников: строкой — добавление нескольких сразу

Приоритет: P2 Предусловия: Выбран класс. Шаги:

Ожидаемый результат: Каждая строка создаёт отдельного ученика; для всех показываются PIN в общем блоке «PIN для «...»: ...». Пустые строки в списке игнорируются.

TC-014. Массовое добавление останавливается на ошибке, не откатывает уже созданных

Приоритет: P3 Предусловия: Выбран класс. Шаги:

Ожидаемый результат: Сообщение об ошибке добавляет «— добавление остановлено, уже созданные ученики остались» и список действительно обновляется, показывая тех, кто успел создаться.

TC-015. Сброс PIN ученику

Приоритет: P1 Предусловия: Есть ученик. Шаги:

Ожидаемый результат: Новый PIN показывается один раз в блоке «PIN для «...»»; старый PIN перестаёт подходить (проверяется интеграционно из ветки 3 — старым PIN ученик войти не может, новым — может).

TC-016. Блокировка/разблокировка отдельного ученика

Приоритет: P2 Предусловия: Есть ученик. Шаги:

Ожидаемый результат: Бейдж появляется/пропадает; причина видна только этому ученику, в списке ростера у других её нет. (Реальный эффект на стороне ученика проверяется через command-log — см. TC-039, «Блокировка ученика».)

TC-017. Перевод ученика в другой класс

Приоритет: P2 Предусловия: Есть минимум 2 класса, в одном — ученик. Шаги:

Ожидаемый результат: Ученик исчезает из текущего списка (класс не может остаться пустым по ошибке отображения) и появляется в списке учеников целевого класса.

TC-018. Объединение дублирующихся профилей (merge)

Приоритет: P1 Предусловия: В классе два ученика — явные дубли одного ребёнка (например, созданы саморегистрацией и учителем), у одного или обоих есть сохранённые работы. Шаги:

Ожидаемый результат: Диалог называет число переносимых работ и текст «Работы обоих профилей сохранятся — они просто окажутся под одним именем». После подтверждения — уведомление «Профиль «...» объединён с «...»: перенесено работ — N», исходный профиль-источник исчезает из списка, у оставшегося — работы обоих.

TC-019. Переименование и удаление ученика с работами — диалог называет последствия

Приоритет: P1 Предусловия: У ученика есть сохранённые работы (см. раздел 3/7). Шаги:

Ожидаемый результат: Переименование проходит без диалога подтверждения. Удаление показывает диалог с числом работ: «У ученика N сохранённых работ и его прогресс — после удаления они станут недоступны. Отменить удаление будет нельзя», кнопка «Всё равно удалить». Удаление ученика БЕЗ работ показывает нейтральный текст «У ученика нет сохранённых работ» и кнопку «Удалить».


3. Подключение — сопряжение и обнаружение учеников в LAN

Требует второй ноутбук с приложением ученика в одной сети с ноутбуком учителя.

TC-020. Название кабинета вместо личного имени учителя

Приоритет: P2 Предусловия: Вкладка «Подключение». Шаги:

Ожидаемый результат: Подсказка явно предупреждает не использовать личное имя («транслируется всем в сети без шифрования»). Значение сохраняется и не сбрасывается при перезапуске приложения.

TC-021. Открытие сопряжения показывает отпечаток сервера

Приоритет: P1 Шаги:

Ожидаемый результат: Кнопка меняется на «Закрыть сопряжение» (красная), появляется блок с 6-символьным отпечатком сервера и подсказкой «Ученик увидит тот же отпечаток... Если отпечатки не совпали — подключается не этот компьютер», плюс срок действия («Действует до HH:MM:SS»).

TC-022. Полное сопряжение: ученик находит учителя, PIN совпадает

Приоритет: P1 (интеграционный, с реальным student-app) Предусловия: На ноутбуке учителя создан класс с 1–2 учениками (PIN записаны), сопряжение открыто (TC-021). На втором ноутбуке — приложение ученика с чистой базой, режим «В классе». Шаги:

Ожидаемый результат: Устройство переходит из «Запросы на подключение» в «Подключённые устройства». Отпечатки на обоих экранах совпадают побайтово (все 6 символов). У ученика на экране выбора карточки нет кнопки «Добавить ученика» (ростер — учителя). Вход по PIN, выданному учителем, успешен.

TC-023. Отклонение устройства

Приоритет: P1 Предусловия: Продолжение TC-022, но на шаге подтверждения выбрать «Отклонить». Шаги:

Ожидаемый результат: Устройство переходит в «Неактивные устройства» со статусом «отклонено» и кнопкой «Вернуть в очередь». Ученик на своей стороне не получает доступ к классу.

TC-024. Возврат отклонённого устройства в очередь

Приоритет: P2 Предусловия: После TC-023. Шаги:

Ожидаемый результат: Устройство снова появляется в «Запросы на подключение» после следующей попытки подключения ученика.

TC-025. Отзыв доступа у подключённого устройства

Приоритет: P1 Предусловия: Устройство в «Подключённые устройства» (после TC-022). Шаги:

Ожидаемый результат: Диалог предупреждает «Устройство отключится сразу — чтобы вернуть его, откройте сопряжение и подтвердите заново». После подтверждения устройство переходит в «Неактивные устройства» со статусом «доступ отозван». На ученическом ноутбуке связь рвётся (см. также TC-070 в разделе про офлайн).

TC-026. Закрытие сопряжения — новые устройства подключиться не могут

Приоритет: P2 Шаги:

Ожидаемый результат: После закрытия — текст «Сопряжение закрыто — новые устройства не могут подключиться». Новое устройство не может завершить сопряжение (детали поведения на стороне ученика — см. mvp/testcases/student-app.md, если есть, или TESTER-GUIDE ветка D).

TC-027. Автозакрытие сопряжения по таймауту (60 минут)

Приоритет: P3 Предусловия: Сопряжение открыто. Шаги:

Ожидаемый результат: По истечении срока кнопка возвращается в состояние «Открыть сопряжение» без участия учителя.

TC-028. Ученик без роли в классе (pending) — приём в ростер

Приоритет: P1 (интеграционный) Предусловия: На ученическом ноутбуке создан локальный профиль ДО подключения к учителю (в самостоятельном режиме) и есть хотя бы одна сохранённая программа, затем устройство переключается в режим «В классе» и подключается к этому учителю; в классе учителя пока нет соответствующего ученика. Шаги:

Ожидаемый результат: В разделе виден профиль с (возможно) предложенным именем и числом ожидающих работ («Ждут N работ»). После добавления — уведомление с новым PIN и подсказкой «продиктуйте этот код ученику — он заменяет тот, который ребёнок мог придумать себе сам». Ученик появляется в списке класса на вкладке «Классы»; его прежние работы становятся видны на вкладке «Код учеников» после следующей синхронизации.

TC-029. Отклонение «не мой ученик»

Приоритет: P2 Предусловия: Продолжение TC-028 или отдельный pending-профиль. Шаги:

Ожидаемый результат: Профиль пропадает из списка ожидающих, в класс не добавляется.

TC-030. Несовпадение отпечатка сервера — предупреждение, не блокировка

Приоритет: P2 Предусловия: Требует смоделировать переустановку/подмену сервера — например, сбросить локальную базу учителя (сервер получит новый sid/fp) при уже подключённых/ожидающих устройствах со старым отпечатком. Если условие сложно воспроизвести физически, кейс можно провести как код-ревью факта — пометить соответственно. Шаги:

Ожидаемый результат: Если есть несовпадения — баннер «N из M устройств... видят другой отпечаток сервера» с пояснением «не блокирует подключение». Разрешение конкретного устройства в списке «Запросы на подключение» остаётся возможным (кнопка «Разрешить» активна) — предупреждение не мешает действию.

TC-031. Предупреждение о клонированном образе диска (дублирующаяся установка)

Приоритет: P3 Предусловия: Два ученических устройства, развёрнутых из одного образа (или недостижимо в стенде — тогда пометить «не проверено, нужен клон образа»). Шаги:

Ожидаемый результат: Баннер «N устройств(о) отвечают с разных адресов под одним идентификатором» с пояснением про клонированный диск и текстом «Ничего не блокируется». Подключение работать не перестаёт, только одно из двух устройств фактически сможет удерживать сессию за раз.


4. Управление классом — живые команды

Требует активное подключение ученика (после раздела 3).

Три команды учителя — что каждая делает у ученика

Ответ на вопрос тестировщика (12.09.2026). Ярлыки похожи, последствия разные.

КомандаЧто происходит у ученикаСрокПереживает перезапуск
Заблокировать класс / ученикаКарточку нельзя выбрать; если ученик уже в ней — через 2 секунды его возвращает на выбор карточки с текстом «Твой профиль/группа заблокирован(а) учителем»до «Разблокировать», но не дольше 30 минут без связи с учителемда
Заморозить класс / ученикаИдущая программа останавливается, весь экран закрыт панелью «Учитель приостановил работу» с причиной и таймером; работать нельзядо «Разморозить» или 30 минутда, пока срок не истёк
Остановить всехОстанавливает идущую программу у всех подключённых, класс не важен. Ничего не блокирует, панели нетразовая; при переподключении воспроизводится, только если ей меньше 30 секунднет

Заморозка, срок которой истёк, при следующем входе ученика не применяется — ни живьём, ни воспроизведением. Если после «Остановить всех» у ученика появилась панель «Учитель приостановил работу» — это ошибка, а не поведение команды (так выглядел BUG-08 до 12.09.2026).

TC-032. Заморозка и снятие заморозки класса

Приоритет: P1 (интеграционный) Предусловия: Ученик подключён и на связи, вкладка «Класс» → выбран класс. Шаги:

Ожидаемый результат: Сразу после отправки карточка показывает «отправлено» — учительское приложение никогда само не помечает команду подтверждённой. В течение нескольких секунд после получения командой ученик присылает подтверждение, состояние переходит в «подтверждено», в разделе «Ученики на связи» появляется «сообщает: заморожен». После разморозки — обратный переход.

TC-033. Аварийная остановка всех

Приоритет: P1 (интеграционный, желательно с реальным роботом) Предусловия: Ученик выполняет программу на роботе или в виртуальном роботе. Шаги:

Ожидаемый результат: Команда рассылается всем подключённым ученикам независимо от выбранного класса; исполнение программы у ученика прерывается; карточка команды показывает подтверждение от затронутых учеников. После повторного входа и перезапуска работа продолжается: никакой панели «Учитель приостановил работу» быть не должно — «Остановить всех» ничего не блокирует.

TC-034. Блокировка/разблокировка класса командным каналом

Приоритет: P1 Шаги:

Ожидаемый результат: Аналогично TC-032 — три состояния доставки видны корректно; блокировка класса — это отдельная команда от «заморозки» (разные ярлыки в списке команд: «Блокировка класса» / «Заморозка»).

TC-035. Команды одному ученику: заморозка, блокировка

Приоритет: P1 Предусловия: Раздел «Команды одному ученику», выбран конкретный ученик. Шаги:

Ожидаемый результат: Команды влияют только на выбранного ученика, не на весь класс (проверить на двух подключённых учениках сразу — второй продолжает работать).

TC-036. Состояние «недоступен» для команды, если ученик пропал со связи

Приоритет: P1 Предусловия: Ученик подключён. Шаги:

Ожидаемый результат: Карточка команды переходит в состояние «недоступен» (после ~15 с отсутствия presence или разрыва сокета), не остаётся навсегда в «отправлено» и не помечается ложно «подтверждено».

TC-037. Отправка прав вручную («Отправить права»)

Приоритет: P2 Шаги:

Ожидаемый результат: Команда flags_push появляется в списке команд, подтверждается так же, как остальные. Полезно для повторной отправки без изменения значения (например, после переподключения устройства).

TC-038. Устаревание ограничения через 30 минут без связи

Приоритет: P3 (долгий кейс — можно пометить «не проверено по времени» при нехватке времени) Предусловия: Заморозка/блокировка активна, ученик теряет связь с учителем на 30+ минут. Шаги:

Ожидаемый результат: У ученика ограничение автоматически снимается с объяснением «связь с учителем потеряна, ограничение снято» — работа не остаётся замороженной навечно. На учительской стороне карточка команды рендерится как «истекло — ограничение больше не действует», отдельно от активного состояния (другой бейдж/цвет).

TC-039. Журнал команд не путает конвергентные и разовые команды при переподключении

Приоритет: P3 Предусловия: Несколько разных команд отправлены за сессию (заморозка, stop_all, флаги). Шаги:

Ожидаемый результат: Повторно подключившийся ученик НЕ получает повторную аварийную остановку — поздний stop_all не должен «выстрелить» задним числом (в отличие от «заморозки»/«блокировки», которые сходятся к последнему состоянию при переподключении в любое время).


5. Разрешения (feature flags)

TC-040. Значения по умолчанию на глобальном уровне

Приоритет: P2 Предусловия: Чистая база, вкладка «Разрешения», область «Глобально». Шаги:

Ожидаемый результат: Все флаги, кроме «Обязательный PIN при саморегистрации», показаны как «не задано» (наследуют встроенный дефолт «включено»). «Обязательный PIN» — тоже «не задано», но встроенный дефолт для него «выключено» (единственный флаг, где так).

TC-041. Изменение глобального флага доходит до подключённого ученика

Приоритет: P1 (интеграционный) Предусловия: Ученик подключён, у него доступны оба режима редактора. Шаги:

Ожидаемый результат: Изменение отправляется автоматически подключённым ученикам сразу (без отдельного нажатия «Отправить права» — согласно подсказке «Изменение сразу отправляется подключённым ученикам, кого оно затрагивает»); у ученика режим «Блоки» перестаёт быть доступен, Python остаётся.

TC-042. Оба режима редактора нельзя выключить одновременно

Приоритет: P1 Предусловия: «Режим «Блоки»» уже выключен глобально (после TC-041). Шаги:

Ожидаемый результат: Операция отклоняется с понятной ошибкой — эффективное значение не может оставить ученика без единого редактора. (Проверить формулировку ошибки — она должна объяснять, что именно произошло, а не быть кодом/стектрейсом.)

TC-043. Разрешение конфликта через переопределение на уровне ученика

Приоритет: P2 Предусловия: Продолжение TC-042 (Python и Блоки оба на «включено» глобально). Шаги:

Ожидаемый результат: Переопределение на уровне ученика применяется, для остальных учеников ничего не меняется. Попытка также выключить у этого ученика Python должна быть отклонена той же проверкой (нельзя оставить конкретного ученика без обоих режимов).

TC-044. Сброс переопределения — наследование

Приоритет: P2 Предусловия: Есть переопределение на уровне класса или ученика (после TC-043). Шаги:

Ожидаемый результат: Строка переходит в состояние «не задано — наследуется»; эффективное значение для затронутых учеников возвращается к значению более высокого уровня (класс или глобально).

TC-045. Приоритет разрешения: ученик > класс > глобально

Приоритет: P1 Предусловия: Задать три разных значения одного флага на трёх уровнях (например, «Виртуальный робот»: глобально — включено, класс ученика — выключено, лично ученику — включено). Шаги:

Ожидаемый результат: «Действует сейчас: включено (источник: Ученик)» — переопределение ученика побеждает переопределение класса, которое в свою очередь побеждало бы глобальное.

TC-046. allow_add_student — только глобальный уровень

Приоритет: P2 Шаги:

Ожидаемый результат: Строка показана, но без контролов переключения — только текст «Эта настройка задаётся только на уровне «Глобально»».

TC-046a. Строка каждого разрешения называет своё значение по умолчанию

Приоритет: P2 Шаги:

Ожидаемый результат: Под названием каждой из восьми строк одной и той же жирной строкой написано «По умолчанию: включено» либо «По умолчанию: выключено». Выключено по умолчанию только «Добавление учеников на устройстве» и «Обязательный PIN при саморегистрации», остальные включены. У «Добавление учеников на устройстве» дополнительно: «состав класса ведёт учитель. Пока ноутбук ни разу не подключался к приложению учителя, кнопка «Добавить ученика» доступна.» (D-132, протокол 04 §3.3).

Ожидаемый результат (шаг 2): у «Режим Python» написано «Наследуется: выключено (Глобально)», а не «включено»; у строк без глобальной настройки — «Наследуется: включено (по умолчанию)». В области «Ученик» строка показывает значение класса, если оно задано, иначе глобальное.

TC-047. pin_required включён — только creation-time политика

Приоритет: P2 (интеграционный) Предусловия: Ученический ноутбук в режиме «В классе», подключён к этому учителю. Шаги:

Ожидаемый результат: Новая саморегистрация без PIN отклоняется/требует PIN; уже созданные профили без PIN не блокируются задним числом (ретроактивная блокировка недопустима по описанию флага).


6. Курсы и уроки — выдача заданий

TC-048. Создание курса

Приоритет: P1 Шаги:

Ожидаемый результат: Курс появляется в списке слева и выбирается автоматически; справа — «Уроки» с пустым списком.

TC-049. Пустое название не создаёт курс

Приоритет: P3 Шаги:

Ожидаемый результат: Ничего не создаётся (кнопка неактивна/нет эффекта — форма отбрасывает пустое значение без ошибки).

TC-050. Добавление урока с заданием, сборкой и подсказками

Приоритет: P1 Предусловия: Выбран курс. Шаги:

Ожидаемый результат: Урок появляется в списке последним (новые уроки добавляются в конец порядка); в подписи под названием видно «N мин · [первая строка задания]».

TC-051. Автопроверка — JSON-схема грейдера

Приоритет: P2 Предусловия: Открыт редактор урока. Шаги:

Ожидаемый результат: JSON сохраняется и при повторном открытии показывается заново (с форматированием через отступы); в подписи урока появляется «автопроверка настроена».

TC-100. Автопроверка по расстоянию снова доступна в редакторе (D-143)

Приоритет: P2 Предусловия: Открыт редактор урока, раздел «Автопроверка». Шаги:

Ожидаемый результат: в списке три типа: время, расстояние, датчик; у расстояния пометка «сейчас работает на виртуальном роботе» и «направление пока не проверяется»; урок с этим JSON сохраняется без ошибки.

TC-052. Невалидный JSON автопроверки не даёт сохранить урок

Приоритет: P2 Шаги:

Ожидаемый результат: Сохранение блокируется, показывается понятная ошибка про формат JSON — остальные поля урока при этом не теряются (форма не закрывается и не очищается).

TC-053. Изменение порядка уроков

Приоритет: P2 Предусловия: В курсе 3+ урока. Шаги:

Ожидаемый результат: Порядок в списке меняется соответственно и сохраняется после обновления страницы/переключения курса и обратно.

TC-054. Удаление урока

Приоритет: P2 Шаги:

Ожидаемый результат: Диалог «Урок пропадёт из курса и у учеников. Отменить удаление будет нельзя», после подтверждения урок исчезает из списка.

TC-055. Удаление курса с уроками

Приоритет: P1 Предусловия: Курс с 2+ уроками. Шаги:

Ожидаемый результат: Диалог называет число уроков: «Вместе с курсом будут удалены все его уроки (N шт.). У учеников, проходивших курс, он пропадёт из библиотеки. Отменить удаление будет нельзя», кнопка «Всё равно удалить».

TC-056. Выдача курса ученику — курс появляется на его стороне

Приоритет: P1 (интеграционный) Предусловия: Курс с уроками создан, ученик подключён к этому учителю. Шаги:

Ожидаемый результат: Курс и его уроки видны ученику в том порядке, что задал учитель; содержимое задания/сборки/подсказок совпадает.

TC-057. Экспорт курса в файл

Приоритет: P2 Предусловия: Есть курс. Шаги:

Ожидаемый результат: Уведомление «Курс сохранён: [путь]», файл действительно создан по этому пути и может быть скопирован на флешку.

TC-058. Импорт курса из файла — новый курс

Приоритет: P1 Предусловия: Есть валидный файл-пакет курса (например, экспортированный в TC-057), титул курса уникален для этой базы. Шаги:

Ожидаемый результат: Уведомление «Импортирован курс «...» (N уроков)», курс появляется в списке и автоматически выбирается.

TC-059. Импорт курса с уже установленным названием — копия, не перезапись

Приоритет: P1 Предусловия: Курс с тем же названием уже есть в базе (например, повторно импортировать файл из TC-058). Шаги:

Ожидаемый результат: Диалог явно говорит «Установленный курс и прогресс учеников не изменятся» — импорт создаёт ОТДЕЛЬНУЮ копию, не перезаписывает существующий курс и не трогает прогресс учеников по нему. Уведомление после импорта помечает результат «— как отдельная копия».

TC-060. Импорт битого файла курса

Приоритет: P2 Предусловия: Подготовить файл, не являющийся валидным пакетом курса (переименовать любой другой файл в ожидаемое расширение, или испортить валидный экспорт). Шаги:

Ожидаемый результат: Понятная ошибка («Пакет не читается» или аналогичная), приложение не падает, список курсов не меняется.


7. Код учеников — приём сдач и просмотр

TC-061. Программа ученика доезжает и видна учителю

Приоритет: P1 (интеграционный) Предусловия: Ученик подключён, написал и сохранил программу (Python или блоки) на своей стороне. Шаги:

Ожидаемый результат: Программа появляется в списке с меткой режима («Python» / «Блоки») и временем синхронизации; при выборе показывается исходный код (для Python — обычный текст, для блоков — JSON блочной структуры), подпись «Просмотр только для чтения — редактировать код ученика из панели учителя нельзя».

TC-062. Открытие кода ученика уведомляет его

Приоритет: P2 (интеграционный) Предусловия: Продолжение TC-061, ученический ноутбук на экране, где видно такое уведомление (если реализовано на ученической стороне — иначе кейс пропустить и пометить как непроверяемый с этой стороны). Шаги:

Ожидаемый результат: Ученик получает пассивное уведомление вида «учитель смотрит твою программу».

TC-063. Запуск Python-программы ученика на виртуальном роботе

Приоритет: P1 Предусловия: Выбрана программа в режиме Python. Шаги:

Ожидаемый результат: Кнопка «Запустить» блокируется на время выполнения, в панели появляются строки лога/телеметрии; «Остановить» прерывает выполнение немедленно, в консоли появляется «Остановлено.».

TC-064. Запуск недоступен для программ на блоках

Приоритет: P2 Предусловия: Выбрана программа в режиме «Блоки». Шаги:

Ожидаемый результат: Кнопка неактивна, под ней текст «Запуск на виртуальном роботе в этой версии доступен только для программ на Python».

TC-065. У ученика без синхронизированных программ — пустое состояние

Приоритет: P3 Предусловия: Выбран ученик, ни разу не сохранявший программу. Шаги:

Ожидаемый результат: «У этого ученика пока нет синхронизированных программ», без ошибки.

TC-066. Учитель не может редактировать код ученика

Приоритет: P1 Предусловия: Открыта программа ученика. Шаги:

Ожидаемый результат: Такого элемента нет — код показан в <pre>, только для чтения, как и заявлено (сверено с кодом — экран не имеет write-канала в принципе).


8. Документация / вики

Живёт на публичном портале (/docs), не внутри самого приложения учителя — учитель открывает её в обычном браузере. Не требует входа.

TC-067. Раздел документации открывается без входа

Приоритет: P2 Предусловия: Есть доступ в интернет и адрес развёрнутого портала (или локальный стенд портала). Шаги:

Ожидаемый результат: Список документов открывается, сгруппированный по разделам (например, «Тестировщику», «Устройство продукта», «Состояние работ», «Протоколы обмена»), доступен без входа в аккаунт.

TC-068. Открытие конкретного документа

Приоритет: P2 Шаги:

Ожидаемый результат: Документ отображается читаемым текстом с настоящими абзацами (не «лесенкой» из фрагментов по одной строке в каждом <p>), таблицы и списки не разваливаются на отдельные пункты без структуры.

TC-069. Диаграммы в документах не выглядят сломанными

Приоритет: P3 Предусловия: Открыт документ, содержащий mermaid-диаграмму (например, «Обзор MVP»). Шаги:

Ожидаемый результат: Диаграмма показана как читаемый текст-исходник с подписью о том, что это исходник диаграммы, а не рендерится как визуальная картинка. Это ожидаемое поведение (не баг) — но подпись должна присутствовать, иначе выглядит как поломка.


9. Синхронизация с порталом

Требует интернет и, по возможности, реальный или тестовый портал (см. mvp/portal/PLAN.md). Согласно D-086/OVERVIEW §1 — эта секция никогда не должна мешать LAN-серверу учителя (см. также раздел 11).

TC-070. Портал не настроен — понятное состояние

Приоритет: P2 Предусловия: Чистая база, вкладка «Портал». Шаги:

Ожидаемый результат: Раздел «Аккаунт» показывает «Сначала укажите адрес и ключ портала выше», кнопки входа/регистрации неактивны, пока не сохранён базовый URL/ключ.

TC-071. Регистрация нового аккаунта учителя

Приоритет: P1 Предусловия: Введены и сохранены адрес портала и ключ. Шаги:

Ожидаемый результат: Если требуется подтверждение почты — уведомление «Аккаунт создан. Подтвердите email — до подтверждения синхронизация недоступна»; иначе — «Аккаунт создан и вход выполнен» и раздел переключается в состояние «вошли как …».

TC-072. Вход существующим аккаунтом

Приоритет: P1 Шаги:

Ожидаемый результат: «Вход выполнен», появляются разделы «Мои курсы» и «Публичные курсы».

TC-073. Выход из аккаунта не рвёт связь с учениками

Приоритет: P1 Предусловия: Учитель вошёл, ученик подключён по LAN. Шаги:

Ожидаемый результат: Уведомление «Выход не влияет на подключённых учеников — синхронизация с портала просто выключается»; ученик остаётся подключён, живые команды продолжают работать.

TC-074. Публикация локального курса на портал (push)

Приоритет: P1 Предусловия: Есть локально созданный курс (раздел 6), учитель вошёл в портал. Шаги:

Ожидаемый результат: «Отправлено на портал», у курса появляется пометка «связан с порталом». Повторное нажатие без изменений даёт «Уже отправлено (повтор запроса)», не создаёт дубль.

TC-075. Загрузка курсов с портала (pull)

Приоритет: P1 Предусловия: На портале есть курс, привязанный к аккаунту (например, из другого сеанса/машины). Шаги:

Ожидаемый результат: Уведомление «Обновлено: N[, пропущено (есть локальные правки): M]», список локальных курсов обновляется. Курс с несохранёнными локальными правками не перезаписывается молча — он в числе «пропущено».

TC-076. Конфликт версий при отправке — три явных варианта разрешения

Приоритет: P1 Предусловия: Тот же курс изменён и на портале (с другой машины/сессии), и локально. Шаги:

Ожидаемый результат: Диалог прямо говорит «Слияние текста не выполняется» — выбор один из трёх, без попытки автоматически смержить содержимое. Каждый вариант даёт свою пометку успеха и ни один не происходит молча/без явного действия учителя.

TC-077. Просмотр и импорт публичных курсов

Приоритет: P2 Шаги:

Ожидаемый результат: Список публичных курсов появляется без необходимости быть автором; импорт доступен только вошедшему в аккаунт учителю (кнопка «Импортировать» неактивна для незалогиненного — если получится проверить без входа, см. TC-070).

TC-078. Портал недоступен (нет интернета) — не считается ошибкой приложения

Приоритет: P1 Предусловия: Учитель вошёл ранее, теперь интернет отключён. Шаги:

Ожидаемый результат: Явная, но не пугающая ошибка о недоступности сети; приложение не падает, локальная работа с классом (вкладки «Класс», «Классы», «Разрешения») продолжает работать без сбоев. После восстановления интернета повторное действие проходит успешно без перезапуска приложения.


10. Обновления приложения

TC-079. Проверка обновлений своего приложения

Приоритет: P1 Предусловия: Вкладка «Обновления», есть интернет. Шаги:

Ожидаемый результат: Один из трёх исходов: «Версия актуальна»; блок «Доступна версия X» с кнопкой «Скачать»; либо (без интернета) «Проверить обновления не удалось: [причина]. Приложение работает дальше — это нормально, если в школе нет интернета» — и это НЕ считается багом.

Во всех трёх исходах: на время работы кнопка подписана «Проверяем…», а под сообщением стоит строка «проверено в ЧЧ:ММ» с текущим временем.

TC-079a. Видно, что проверка была, даже когда ответ не изменился

Приоритет: P1 Предусловия: Вкладка «Обновления». Годится любое состояние — в том числе ненастроенный портал. Шаги:

Ожидаемый результат: время в строке «проверено в …» изменилось. Сообщение выше при этом может остаться прежним — это нормально, вопрос кейса именно в том, видно ли, что проверка состоялась.

Была ошибка (до D-125): отметки времени не было, подписи на кнопке не было, и повторная проверка не меняла на экране ничего. QA завела это как неработающую кнопку — и была права: способа отличить сработавшую проверку от несработавшей не существовало.

TC-079b. Ненастроенный портал назван настройкой, а не молчащей сетью

Приоритет: P1 Предусловия: Вкладка «Портал», адрес портала НЕ заполнен (чистая установка). Шаги:

Ожидаемый результат: «Проверить обновления не удалось: адрес портала не настроен — укажите его на вкладке «Портал»». Фразы «ни один источник обновлений не ответил» нет. Фразы «это нормально, если в школе нет интернета» тоже нет — интернет тут ни при чём, и подсказка про него уводила бы от единственного нужного действия. Ниже, в «Раздаче классу», причина названа так же — экран не должен рассказывать две разные истории про одну пустую настройку.

TC-080. Скачивание и отложенная установка обновления

Приоритет: P1 Предусловия: Доступно обновление (TC-079). Шаги:

Ожидаемый результат: Пока скачивается — «Скачивание… N%»; после — состояние «готово» с текстом «Обновление скачано и проверено. Установка закроет приложение — лучше не посреди урока» и отдельная кнопка «Установить сейчас» — то есть скачивание и установка разделены, установка не начинается сама.

TC-081. Установка обновления

Приоритет: P2 Предусловия: Обновление скачано (TC-080). Осторожно: закрывает приложение. Шаги:

Ожидаемый результат: Приложение закрывается для установки; после перезапуска — новая версия видна в «Установлена версия ...».

TC-082. Раздача обновлений классу по локальной сети

Приоритет: P1 Предусловия: В школе/на стенде нет интернета у учеников, но учительский ноутбук предварительно пополнил «запас» (нажатие «Обновить запас», сделанное заранее там, где есть интернет). Шаги:

Ожидаемый результат: Таблица показывает готовые к раздаче пакеты для учеников/учителя с указанием ОС и версии; подсказка «Интернет им при этом не нужен». Ученический ноутбук без интернета получает обновление именно с учительского компьютера по локальной сети.

TC-083. Раздача не поднялась — видимая ошибка, не тишина

Приоритет: P1 Предусловия: Спровоцировать конфликт порта раздачи (например, занять указанный порт другим процессом) или иное препятствие запуску relay-сервера. Шаги:

Ожидаемый результат: Баннер «Раздача не работает: [причина]» с пояснением «Ученики не получат обновления от этого компьютера» — учитель узнаёт о проблеме сразу на этом экране, а не по тому, что тридцать учеников остались на старой версии (комментарий из кода экрана прямо формулирует эту цель).

TC-084. Обновление запаса

Приоритет: P2 Предусловия: есть интернет. Адрес портала настраивать НЕ надо — он зашит в сборку по умолчанию (меняют его только школы со своим порталом, на вкладке «Портал»). Шаги:

Ожидаемый результат: пока идёт — кнопка «Обновляем запас…» и заблокирована от повторного нажатия. После — строка «проверено в ЧЧ:ММ» с текущим временем, и один из исходов названный словами:

Была ошибка (до D-126): портал отвечал 404 на каждую позицию — на пилоте это норма, сборок ещё не выпускали, — и обход завершался, не оставив на экране ни следа: список пуст, ошибки нет, текст тот же, что до нажатия. Отличить «сходили, на портале пусто» от «кнопка не работает» было нечем; QA так и записала — «ничего не происходит».

TC-084a. Ненастроенный портал больше не мешает раздаче на свежей установке

Приоритет: P1 Предусловия: чистый профиль учителя, адрес портала на вкладке «Портал» не заполнен Шаги:

Ожидаемый результат: баннера «Раздача не работает: адрес портала не настроен» НЕТ. Раздача пользуется адресом по умолчанию, зашитым в сборку.

Была ошибка: свежая установка объявляла раздачу неработающей и отправляла учителя настраивать портал на вкладке, которую никто не открывает. Тест-кейс при этом про настройку портала не упоминал — и был прав: настраивать её не должно быть нужно.


11. Офлайн и деградация сети (D-086: LAN — только удобство учителя, урок работает без сети)

Ключевой принцип продукта: путь ученик↔робот не завязан на IP-сеть вообще (Bluetooth + USB), LAN нужна только для того, чтобы УЧИТЕЛЬ видел класс. Раздел проверяет именно это: пропажа сети не должна ломать урок, а данные не должны теряться.

TC-085. Класс без роутера вообще — учитель просто не видит учеников

Приоритет: P1 Предусловия: Ученические ноутбуки НЕ подключены ни к какой сети (Wi-Fi выключен), учительский ноутбук — тоже. Шаги:

Ожидаемый результат: Учительское приложение запускается штатно (локальный сервер поднимается на loopback/локальном интерфейсе даже без внешней сети), вкладка «Класс» показывает «Никто ещё не подключился» — не ошибку. Ученики при этом полноценно работают: пишут код, подключаются к роботу по Bluetooth, запускают программы, видят результат — без единого сбоя, связанного с отсутствием LAN.

TC-086. Хотспот с телефона вместо роутера — работает как обычная сеть

Приоритет: P1 (интеграционный) Предусловия: Точка доступа — обычный мобильный хотспот (не роутер класса). Шаги:

Ожидаемый результат: Обнаружение, сопряжение и командный канал работают так же, как с обычным роутером — хотспот с телефона официально поддерживается как равноценная замена роутеру (OVERVIEW §1: «это обычный хотспот для ноутбуков... несёт класс без проблем»).

TC-087. Ученик отваливается от сети посреди урока — урок не прерывается

Приоритет: P1 (интеграционный) Предусловия: Ученик подключён, работает над программой (пишет код локально, не завязан на связь с учителем для самого написания/запуска). Шаги:

Ожидаемый результат: На шаге 2 у ученика ничего не ломается — редактирование, запуск на роботе продолжают работать. На шаге 3 учитель видит ученика как «недоступен» (не «на связи», не тихо пропавшим без индикации). После шага 4 статус возвращается на «на связи» без ручных действий учителя, без потери данных (продолжение см. TC-088).

TC-088. Работы ученика синхронизируются с опозданием, а не теряются

Приоритет: P1 (интеграционный) Предусловия: Продолжение TC-087 — ученик сохранил/изменил программу, пока был отключён от сети. Шаги:

Ожидаемый результат: Программа, сохранённая офлайн, появляется у учителя после восстановления сети с корректным временем синхронизации — ничего не потеряно, досинхронизация происходит сама, без ручного «отправить ещё раз» со стороны ученика.

TC-089. Незакрытая заморозка не остаётся навечно при пропаже учителя

Приоритет: P1 Предусловия: См. TC-038 — комбинация с реальным отключением учителя. Шаги:

Ожидаемый результат: Тот же результат, что в TC-038: ограничение автоматически снимается через 30 минут без контакта, ученик не остаётся заблокированным до бесконечности из-за того, что учитель закрыл ноутбук в конце урока.

TC-090. Сервер учителя падает посреди урока — видимое состояние, не тихая смерть

Приоритет: P1 Предусловия: Ученики подключены и работают. Шаги:

Ожидаемый результат: Бейдж переходит в «Сервер для учеников недоступен» или «Порт занят» (не остаётся в «Сервер для учеников доступен», пока сервер реально не отвечает). Реклама mDNS-сервиса снимается сразу — подключённые/ищущие ученики видят честное «не найдено», а не зависшее соединение.

TC-091. Восстановление сервера после конфликта порта

Приоритет: P2 Предусловия: Продолжение TC-090, состояние «Порт занят». Шаги:

Ожидаемый результат: При успехе — бейдж переходит в «Сервер для учеников доступен» с новым портом; ученики, повторно ищущие учителя, находят его на новом порте (mDNS/UDP объявление обновляется).

TC-092. Урок без интернета целиком — портал недоступен, класс работает

Приоритет: P1 Предусловия: Локальная сеть (роутер/хотспот) есть, интернета нет вовсе. Шаги:

Ожидаемый результат: Всё, что не требует интернета (ростер, LAN-подключение учеников, живые команды, курсы/уроки, разрешения), работает штатно. Раздел «Портал» либо неактивен, либо честно сообщает о недоступности сети — не подвешивает вкладку и не мешает остальным вкладкам.


12. Два учителя в одной сети

Не описано как отдельная спроектированная фича в PLAN.md/протоколе — раздел проверяет фактическое поведение (эксплораторно), а не заранее заданный сценарий. Расхождение с ожиданием всё равно стоит зафиксировать как находку.

TC-093. Два запущенных приложения учителя не конфликтуют по порту на одном компьютере

Приоритет: P2 Предусловия: Два экземпляра приложения учителя на одном ноутбуке (если это вообще возможно запустить одновременно — иначе кейс неприменим, пометить «неприменимо»). Шаги:

Ожидаемый результат: Либо второй экземпряр честно сообщает о занятом порте (см. TC-090/091), либо подбирает свободный порт сам — в любом случае не падает молча и не создаёт впечатление рабочего сервера, который на деле не слушает.

TC-094. Два разных учителя на разных ноутбуках в одной физической сети

Приоритет: P1 (эксплораторный) Предусловия: Два ноутбука с приложением учителя, каждый со своим классом, оба в одной Wi-Fi сети/хотспоте. Шаги:

Ожидаемый результат: Задокументировать фактическое поведение: находит ли ученик обоих учителей и даёт выбрать нужного, подключается ли к первому найденному, или к «неправильному». Если UI никак не различает двух найденных учителей одинаково видимо для ребёнка (например, по названию кабинета) — это находка для отчёта, а не ожидаемая функция с гарантированным исходом.

TC-095. Ученик по ошибке подключился не к тому учителю (сопряжение чужого класса)

Приоритет: P2 (эксплораторный) Предусловия: Условия TC-094, ученик сопрягается со «своим» учителем через отпечаток по TC-022. Шаги:

Ожидаемый результат: Сверка по 6-символьному отпечатку — единственный способ отличить нужного учителя от соседнего в этой версии (нет pairing-кода, см. protocols/02 §5). Если отпечатки на экранах различаются между двумя учительскими приложениями (что и должно быть), ручная сверка предотвращает случайное присоединение не к тому классу.


13. Кроссплатформенность macOS/Windows

TC-096. Первый запуск на Windows запрашивает сетевое разрешение — обе галочки

Приоритет: P1 Предусловия: Чистая установка на Windows, первый запуск. Шаги:

Ожидаемый результат: Диалог появляется (ожидаемое поведение, не баг — так помечено в TESTER-GUIDE). Если разрешить только «частные» сети — школьный Wi-Fi часто определяется как «общественная», и ученики не смогут подключиться, при этом сам учитель будет видеть зелёный индикатор сервера («слушает»), что маскирует проблему. Кейс TC-021/TC-022 стоит повторить именно после разрешения обеих галочек.

TC-097. Неизвестный издатель при установке на Windows — ожидаемо

Приоритет: P3 Предусловия: Установщик .exe, не имеющий пока купленной подписи. Шаги:

Ожидаемый результат: SmartScreen показывает «Неизвестный издатель»; «Подробнее» → «Выполнить в любом случае» продолжает установку. Это НЕ баг (см. TESTER-GUIDE.md, часть 6, «Что НЕ является багом»).

TC-098. Установка и первый запуск на macOS

Приоритет: P2 Шаги:

Ожидаемый результат: Приложение запускается без дополнительных диалогов о сети (специфично для Windows), сервер поднимается так же, как описано в TC-001.

TC-099. Раздача обновлений между разными ОС в одном классе

Приоритет: P2 Предусловия: В классе есть и Windows-, и macOS-ноутбуки учеников, учительский «запас» на вкладке «Обновления» пополнен для обеих платформ. Шаги:

Ожидаемый результат: Таблица показывает платформу для каждого пакета («Windows» / «macOS, Apple Silicon» / «macOS, Intel»); ученик получает пакет именно под свою ОС, а не универсальный/не тот.


Что не покрыто и почему