Files
orchestrator/docs/work-items/ORCH-088/04-test-plan.yaml

154 lines
7.8 KiB
YAML
Raw Permalink 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.
work_item: ORCH-088
title: "Serial gate (Этап 1: пакетный автономный режим, serial e2e)"
scope: "FR-1..FR-5 only. Merge-queue / pre-merge rebase / phases A/B/C / ORCH-83 — out of scope."
framework: pytest
# Принципы тестирования:
# - чистую логику gate/freeze покрываем unit-тестами на leaf-функциях (без сети/БД где можно);
# - claim-gate и e2e-последовательность — integration на временной SQLite-БД;
# - все тесты детерминированы (без реальных Plane/Gitea/прод вызовов — мокируются);
# - проверяем оба направления kill-switch (вкл/выкл) и never-raise.
tests:
# ---------- FR-1 / AC-1: gate закрыт при активной задаче ----------
- id: TC-01
type: unit
description: "claim_next_job НЕ выбирает analyst-job новой задачи B, если в репо есть задача A со stage!='done' (gate закрыт)"
module: tests/test_serial_gate.py
expected: PASS
- id: TC-02
type: unit
description: "serial_gate_applies(repo): enabled + пустой CSV → True для зарегистрированного репо; CSV с членством → True; репо вне CSV → False"
module: tests/test_serial_gate.py
expected: PASS
- id: TC-03
type: unit
description: "Job'ы УЖЕ активной задачи (architect/developer/.../deployer) gate'ом НЕ блокируются — единственная активная задача свободно идёт по конвейеру"
module: tests/test_serial_gate.py
expected: PASS
# ---------- FR-1/2 / AC-2: автостарт следующей по достижении done ----------
- id: TC-04
type: integration
description: "После перевода A.stage='done' claim_next_job выбирает analyst-job ожидающей B того же репо (gate открылся автоматически)"
module: tests/test_serial_gate_e2e.py
expected: PASS
- id: TC-05
type: integration
description: "Очередь из 3 задач одного репо обрабатывается строго по одной: пока A не done, ни B, ни C не стартуют; порядок FIFO по jobs.id"
module: tests/test_serial_gate_e2e.py
expected: PASS
# ---------- FR-4 / AC-3: restart-safe ----------
- id: TC-06
type: integration
description: "Активная задача определяется из БД (tasks.repo + stage!='done'), не из in-memory — после пересоздания воркера/состояния gate остаётся закрытым при A.stage<done"
module: tests/test_serial_gate_e2e.py
expected: PASS
- id: TC-07
type: integration
description: "Freeze переживает рестарт: выставленный в БД freeze читается после пересоздания состояния; следующая задача не стартует"
module: tests/test_serial_gate_freeze.py
expected: PASS
# ---------- FR-3 / AC-4: per-repo ----------
- id: TC-08
type: unit
description: "Активная задача в orchestrator (stage<done) НЕ блокирует claim analyst-job задачи в enduro-trails (gate фильтруется по repo)"
module: tests/test_serial_gate.py
expected: PASS
- id: TC-09
type: unit
description: "Freeze репо orchestrator не влияет на claim/старт задач enduro-trails"
module: tests/test_serial_gate_freeze.py
expected: PASS
# ---------- FR-5 / AC-5: rollback-freeze + алерт ----------
- id: TC-10
type: unit
description: "post-deploy вердикт DEGRADED → выставляется durable per-repo freeze (запись в БД) + вызывается Telegram-алерт (send_telegram замокан, проверяется вызов)"
module: tests/test_serial_gate_freeze.py
expected: PASS
- id: TC-11
type: integration
description: "При активном freeze репо claim_next_job НЕ выбирает analyst-job следующей задачи, даже если нет задач stage<done (деградировавшая уже done — BR-7)"
module: tests/test_serial_gate_freeze.py
expected: PASS
- id: TC-12
type: integration
description: "Ручное снятие freeze → следующая задача стартует на ближайшем цикле; freeze помечается cleared в БД"
module: tests/test_serial_gate_freeze.py
expected: PASS
# ---------- FR-1 / AC-6: нет stale-base ----------
- id: TC-13
type: integration
description: "Ветка B не создаётся (ни Gitea-ветка, ни worktree), пока gate закрыт — _create_gitea_branch/ensure_worktree для B не вызывается при A.stage<done"
module: tests/test_serial_gate_branch.py
expected: PASS
- id: TC-14
type: integration
description: "После A.stage='done' (A влита в main) база ветки B = origin/main с кодом A: git merge-base --is-ancestor <sha A> <base B> истинно (на временном git-репо)"
module: tests/test_serial_gate_branch.py
expected: PASS
# ---------- AC-7: kill-switch / нулевая регрессия ----------
- id: TC-15
type: unit
description: "serial_gate_enabled=False → claim_next_job SQL/поведение идентичны исходным (gate инертен); B стартует независимо от A"
module: tests/test_serial_gate.py
expected: PASS
- id: TC-16
type: unit
description: "Репо вне serial_gate_repos (CSV непуст) → gate не применяется к этому репо"
module: tests/test_serial_gate.py
expected: PASS
# ---------- AC-8 / AC-9: never-raise ----------
- id: TC-17
type: unit
description: "Ошибка БД при вычислении gate в claim → перехвачена, залогирована, claim не падает (fail-OPEN: claim продолжается)"
module: tests/test_serial_gate.py
expected: PASS
- id: TC-18
type: unit
description: "Ошибка при определении freeze → fail-CLOSED: следующая не стартует при невозможности подтвердить отсутствие freeze"
module: tests/test_serial_gate_freeze.py
expected: PASS
# ---------- AC-10: наблюдаемость ----------
- id: TC-19
type: unit
description: "serial_gate snapshot() возвращает {enabled, repos, per-repo active_task, waiting, frozen}; never-raise при ошибке → минимальный словарь"
module: tests/test_serial_gate.py
expected: PASS
- id: TC-20
type: integration
description: "GET /queue содержит аддитивный блок serial_gate и НЕ меняет существующие ключи (counts/max_concurrency/reconcile/reaper/post_deploy/task_deps/recent)"
module: tests/test_queue_endpoint.py
expected: PASS
# ---------- AC-11: инварианты ----------
- id: TC-21
type: unit
description: "STAGE_TRANSITIONS и реестр QG_CHECKS не изменены (снимок ключей совпадает с эталоном); новых QG-проверок нет"
module: tests/test_serial_gate.py
expected: PASS
- id: TC-22
type: unit
description: "Миграция freeze-хранилища идемпотентна: повторный вызов init_db/_ensure не падает и не дублирует структуру"
module: tests/test_serial_gate_freeze.py
expected: PASS