Приёмка: как проверить, что сделали именно то, и как избежать споров
Приёмка — единственный момент проекта, когда всем становится видно качество анализа. Пока идёт разработка, неточная формулировка выглядит безобидно. На приёмке она превращается в разговор на повышенных тонах: «мы же договаривались» против «нигде этого не написано». Спор при этом почти никогда не о технике. Он о том, какой текст считать основанием и кто имеет право сказать «принято».
Хорошая новость: приёмка — самая механизируемая часть работы аналитика. Практически всё, что определяет её исход, происходит до неё: какие критерии зафиксированы, кто назначен принимающим, что явно объявлено вне объёма, есть ли доказательства под каждым пунктом. Сама сессия — это протокол, а не творчество.
Мы продолжаем сквозной пример трека: автовозврат в интернет-магазине. К этому моменту
из «сделайте возврат в один клик» получился бэклог из историй S1–S6
(декомпозиция), правила BR-14 и BR-15, контракт
refund-api.yaml и НФТ с числами (нефункциональные требования).
Сегодня команда говорит: «S1 готова». Разберём, что должно произойти дальше, чтобы это
закончилось решением, а не спором.
1. Что такое приёмка и чем она не является
1.1. Три элемента, без которых приёмки не существует
Приёмка — это решение уполномоченного лица о том, что результат соответствует согласованному основанию. В определении три слова-опоры, и провал любого из них превращает встречу в обсуждение вкусов:
| Элемент | Вопрос | Как выглядит провал |
|---|---|---|
| Основание | по какому тексту сверяем | «ну мы же обсуждали на встрече в марте» |
| Доказательство | что предъявляем как факт | «разработчик показал на своём ноутбуке» |
| Полномочие | кто вправе сказать «да» | в комнате восемь человек, решает самый громкий |
Всё остальное в этой статье — раскрытие этих трёх пунктов. Если вы за пять минут до встречи не можете назвать документ-основание, набор доказательств и фамилию принимающего — встречу лучше перенести: она закончится списком мнений.
1.2. Пять ворот, которые постоянно путают
Слово «приёмка» в разных компаниях означает пять разных вещей. Их путают, и отсюда половина конфликтов: команда прошла свои ворота и считает работу законченной, а бизнес имел в виду совсем другие.
| Ворота | Кто принимает | Основание | Отвечает на вопрос |
|---|---|---|---|
| Definition of Done | команда | DoD, один на все истории | «мы вообще закончили работу?» |
| Приёмка владельцем | владелец продукта | критерии приёмки истории | «сделали то, что описано?» |
| UAT | реальные пользователи | сценарии рабочего дня | «этим можно работать?» |
| Опытная эксплуатация | владелец процесса | SLO, метрики пилота | «это выдерживает боевой поток?» |
| Формальная приёмка | заказчик, комиссия | договор, ТЗ, ПМИ | «обязательство исполнено?» |
Ворота нельзя пропустить — можно только не заметить, что вы их прошли. Не было UAT — поддержка «примет» систему в первый рабочий день в виде потока обращений. Не было опытной эксплуатации — роль пилота сыграет весь боевой поток сразу, без плана отката. Задача аналитика — назвать каждые ворота заранее: кто принимает, по какому тексту, что считается отказом.
1.3. Приёмка ≠ тестирование
Это разные вопросы, и их смешение — устойчивый источник обид.
- Тестирование отвечает: «работает ли система так, как описано». Это про соответствие реализации спецификации, и это зона QA — см. тестирование.
- Приёмка отвечает: «описали ли мы то, что нужно, и получили ли то, что описали». Второй вопрос про требования, а не про код.
Отсюда практическое следствие: приёмка начинается только после того, как тесты зелёные. Разбирать на приёмке очевидные баги — трата дорогого времени бизнеса и верный способ получить впечатление «они принесли сырое». И обратное: если QA прогнал все тесты, это ещё ничего не говорит о приёмке — тесты написаны по тому же тексту, который мог быть неверным.
1.4. Формула спора
Спор на приёмке возникает ровно там, где основание не было зафиксировано до начала работы. Из этого следуют четыре типовых источника, о которых мы говорили весь трек:
| Источник | Как звучит на приёмке | Где лечится |
|---|---|---|
| Неявное требование | «а печатная форма где?» | выявление, явный out_of_scope |
| Противоречие стейкхолдеров | финансы принимают, поддержка нет | стейкхолдеры, один принимающий на пункт |
| «Хотелка» без задачи | «раз уж вы тут, добавьте…» | бэклог и приоритизация, а не приёмка |
| Непроверяемый критерий | «должно быть удобно» | виды требований, числа и наблюдаемость |
Ни один из четырёх не решается на самой приёмке. Приёмка их только обнажает.
2. Основание приёмки: что именно предъявляем
2.1. Пакет приёмки
Основание — не один документ, а пакет с зафиксированной версией. Для истории S1 он выглядит так (реально хранится рядом с историей в трекере или в репозитории требований):
# acceptance/S1.yaml — пакет приёмки, зафиксирован до старта разработки
story: S1
title: "Автоматический возврат для карточных оплат до 3000 руб."
baseline:
version: v3 # версия критериев, по которой команда начинала
frozen_at: 2026-03-19 # дата заморозки; всё после — изменение, а не уточнение
approved_by: "Марина, руководитель поддержки (владелец процесса)"
criteria: # что проверяем поштучно; источник — критерии истории
- id: AC-1
text: "Заявка: карта, сумма <= 3000 руб., причина из BR-14, срок <= 14 дней —
решение принимается без оператора"
evidence: "прогон 6 заявок на UAT-стенде, чек-лист AC-1"
accepts: "Марина"
- id: AC-2
text: "Хотя бы одно условие не выполнено — заявка в обычной очереди,
причина отказа видна оператору"
evidence: "прогон 4 негативных случаев"
accepts: "Марина"
- id: AC-3
text: "Деньги отправлены в банк не позже 30 минут после решения"
evidence: "выгрузка журнала за сутки пилота: max(отправка - решение)"
accepts: "Марина"
- id: AC-4
text: "Повторная отправка заявки не создаёт второй возврат"
evidence: "лог двойного вызова + запрос в БД по refund_id"
accepts: "Игорь, финансы"
- id: NFR-3
text: "p95 решения автомата <= 800 мс при 40 заявках в минуту"
evidence: "отчёт нагрузочного прогона, приложен к протоколу"
accepts: "Игорь, финансы"
out_of_scope: # то, чего в этой поставке нет НАМЕРЕННО
- "СБП и наличные — история S5"
- "Отмена решения оператором — S3"
- "Печатная форма для бухгалтерии — не обсуждалась, вопрос открыт: Q-58"
- "Суммы свыше 20 000 руб. — по регламенту требуют звонка"
defaults_applied: # решения по умолчанию, принятые без ответа владельца
- "Q-41: 14 дней считаем от даты вручения (ответа к 18.03 не было)"
blocking_rules: # что считается отказом, а что замечанием — до приёмки
- "любое расхождение по AC-4 и NFR-3 блокирует: это деньги и нагрузка"
- "тексты сообщений и порядок колонок — замечание, не блокер"
Три поля отличают этот файл от красивого шаблона. frozen_at — граница между «уточнением»
и «изменением»: после этой даты любое новое ожидание стоит денег и времени, и это обсуждается
как изменение, а не как долг команды. out_of_scope снимает больше споров, чем сами критерии:
половина конфликтов — про то, что кто-то считал очевидным. blocking_rules — правило игры,
сформулированное до того, как стало ясно, кто выигрывает.
2.2. Тест на пригодность основания
Каждый пункт основания проходит четыре проверки. Не проходит — это не критерий приёмки, а пожелание, и на приёмке оно превратится в спор:
- Наблюдаемость. Результат виден снаружи: статус, письмо, строка в выгрузке, запись в журнале. «Система корректно обрабатывает» — не виден.
- Однозначность вывода. Двое независимо получают один и тот же вердикт «да/нет».
- Метод проверки известен заранее. Кто, где, на каких данных, чем измеряет.
- Названы границы. Что не входит, при каких условиях проверка неприменима.
Слова, после которых пункт нужно переписывать: «удобно», «интуитивно», «быстро», «надёжно», «корректно», «при необходимости», «и так далее», «стандартным образом». Каждое из них на приёмке читается заинтересованными сторонами по-разному — и обе стороны правы, что и делает спор неразрешимым.
2.3. Трассировка: от требования до доказательства
Основание работает, только если каждый пункт дотягивается до факта. Это цепочка из пяти звеньев, и её удобно держать в виде модели:
Смысл модели не в том, чтобы завести систему. Смысл — в правиле: пункт без доказательства не считается проверенным, даже если все кивнули. «Мы же видели на демо» через месяц не восстанавливается, а вопрос «а это точно работало?» возникает ровно тогда, когда что-то сломалось в проде.
2.4. Скрипт: готов ли пакет к приёмке
Механическую часть проверки удобно автоматизировать. Скрипт не оценивает смысл — он ловит структурные дыры, из-за которых сессия развалится:
"""Проверка готовности пакета приёмки: дыры в основании и доказательствах."""
import re
import sys
import yaml
VAGUE = re.compile(
r"\b(удобн|интуитивн|быстр|надёжн|корректн|при необходимости|и так далее|"
r"стандартн|оптимальн|дружелюбн|современн)", re.IGNORECASE)
def check(pkg: dict) -> list[str]:
"""Возвращает список проблем. O(n) по числу критериев, O(1) доп. памяти."""
problems: list[str] = []
base = pkg.get("baseline", {})
for field in ("version", "frozen_at", "approved_by"):
if not base.get(field):
problems.append(f"baseline.{field}: не заполнено — нечем доказать, "
f"что основание было до старта")
criteria = pkg.get("criteria", [])
if not criteria:
problems.append("criteria: пусто — приёмка превратится в обсуждение вкусов")
accept_owners = set()
for c in criteria:
cid = c.get("id", "<без id>")
text = c.get("text", "")
if not c.get("evidence"):
problems.append(f"{cid}: нет доказательства — метод проверки не определён")
if not c.get("accepts"):
problems.append(f"{cid}: не назван принимающий — решать будет самый громкий")
else:
accept_owners.add(c["accepts"])
if m := VAGUE.search(text):
problems.append(f"{cid}: размытая формулировка «{m.group(0)}» — "
f"двое прочтут по-разному")
if " или " in text and "тогда" in text.lower():
problems.append(f"{cid}: «или» в результате — неопределённость уехала в тест")
if not pkg.get("out_of_scope"):
problems.append("out_of_scope: пусто — граница поставки не объявлена, "
"спор про «а это тоже входило» гарантирован")
if not pkg.get("blocking_rules"):
problems.append("blocking_rules: не заданы — что блокирует приёмку, "
"решится в момент, когда уже спорят")
if len(accept_owners) > 3:
problems.append(f"принимающих {len(accept_owners)} — приёмка растянется; "
f"нужен один владелец решения и консультанты")
return problems
if __name__ == "__main__":
package = yaml.safe_load(open(sys.argv[1], encoding="utf-8"))
issues = check(package)
print("\n".join(f" ! {p}" for p in issues) or " пакет готов к приёмке")
sys.exit(1 if issues else 0)
Такой линтер живёт в CI рядом с требованиями и работает как ворота: история не уходит в спринт, пока пакет не проходит проверку. Это дешевле любых договорённостей на словах — см. тесты в CI.
3. Полномочие: кто говорит «принято»
3.1. Один принимающий на пункт
Правило, которое экономит больше времени, чем любой шаблон документа: у каждого пункта основания ровно один принимающий. Не комитет, не «мы все посмотрим», не «согласуем с руководством». Комитет из восьми человек не принимает решение — он производит протокол разногласий.
Остальные участники получают явные роли:
| Роль | Право | Как звучит на сессии |
|---|---|---|
| Принимающий | сказать «принято / с замечаниями / отклонено» | «AC-3 принимаю» |
| Консультант | высказаться до решения, но не блокировать | «здесь риск, учтите» |
| Информируемый | узнать результат | получает протокол |
| Владелец расхождения | обязан устранить к сроку | «беру D-2, к 27.03» |
Для разных пунктов принимающие разные — и это нормально: функциональность автовозврата принимает Марина (владелец процесса поддержки), идемпотентность и сверку с учётом — Игорь из финансов, требования по персональным данным — офицер безопасности. Аналитик раскладывает пункты по принимающим до сессии и пишет это в пакете. Подробно про власть над требованием — в работе со стейкхолдерами.
3.2. Прокси, делегирование и «а начальник не согласится»
Частая ловушка: приёмку ведёт человек без права решать. Тогда любое «принято» — предварительное, а через неделю приходит настоящий владелец и открывает всё заново. Проверочный вопрос перед сессией звучит грубо, но экономит недели: «Если вы скажете “принято”, кто-то может это отменить?» Если да — либо приглашаем того, кто может, либо фиксируем в протоколе, что решение предварительное, с датой окончательного.
Делегирование фиксируется письменно и заранее: «Марина в отпуске до 2 апреля, на время отпуска решения по AC-1…AC-3 принимает Светлана». Одна строка снимает классический спор «я такого не согласовывал».
3.3. Молчание — не приёмка
Отдельный антипаттерн: «отправили на согласование, две недели тишины — считаем, что приняли». В спокойное время это работает, в конфликтной ситуации разваливается мгновенно. Если организация всё-таки живёт по правилу молчаливого согласия, оно должно быть объявлено до отправки и содержать срок: «замечания до 27.03 включительно; после этой даты версия v3 считается принятой». Тогда это правило, а не ловушка.
4. Подготовка: 80% приёмки происходит до сессии
4.1. Условия входа
Приёмку нельзя начинать, пока не выполнены условия входа. Их полезно держать коротким списком и проверять честно — сорванная сессия обходится дороже, чем перенесённая:
- версия развёрнута на среде, доступной принимающим (не на ноутбуке разработчика);
- данные реалистичные: настоящие суммы, кириллица, длинные адреса, крайние значения, а не «Иванов Иван, заказ на 1 рубль»;
- у принимающих есть учётные записи с их ролями — оператор видит систему как оператор;
- известные дефекты выписаны заранее и предъявлены до сессии, а не «всплывают» на ней;
- сценарии прогона разосланы: принимающий знает, что будет делать руками;
- прогон уже выполнен один раз внутри команды (сухой прогон) — на сессии не должно быть сюрприза «а тут вообще не открывается»;
- назначено время протоколиста: кто пишет решения, пока остальные обсуждают.
4.2. Данные — половина успеха
Приёмка на синтетике проходит гладко и ничего не проверяет. Практический минимум для нашего примера: набор из 12 заявок, где явно представлены границы правила BR-14 — ровно 3000 руб. и 3000.01, ровно 14-й день и 15-й, причина из списка и причина «другое», оплата картой и СБП, заявка от клиента с двумя открытыми возвратами. Каждая строка набора привязана к критерию, который она проверяет.
Отдельный вопрос — персональные данные. Копия боевой базы на UAT-стенде без обезличивания — это утечка, оформленная как забота о реалистичности; см. тестирование безопасности. Правильный путь — генерация или маскирование с сохранением статистики распределений.
4.3. Демо и приёмка — разные встречи
Обзор спринта (демо) отвечает на вопрос «что мы узнали и куда идём дальше», это событие про обратную связь и планирование — см. события Scrum. Приёмка отвечает на вопрос «принято или нет» и заканчивается записанным решением. Совмещать их можно, только если участников мало и объём небольшой. Как только на демо приходит десять человек, приёмка в этом формате умирает: решение подменяется коллективным одобрением, а через неделю выясняется, что «нам это не подходит».
5. Сессия приёмки: сценарий, который заканчивается решением
5.1. Протокол встречи
не посреди него end end Q->>A: отчёт по НФТ: p95 = 640 мс, доказательство приложено A->>M: сводка: 4 принято, 1 дефект, 2 замечания, 1 пожелание M-->>A: решение: принято с замечаниями, D-2 до 27.03 A->>R: протокол разослан в тот же день, решения именные
Три правила, которые делают эту схему рабочей:
- Прогоняет принимающий, а не разработчик. Когда систему показывает автор, зритель видит счастливый путь и уверенную руку. Когда мышку берёт Марина, за две минуты выясняется, что кнопка не там, где она ищет, а сообщение об ошибке ей непонятно.
- Сначала вердикт по всем пунктам, потом обсуждение. Иначе первое же расхождение съедает час, и до половины критериев вы не доходите.
- Никакого проектирования на приёмке. Фраза «а давайте сделаем вот так» — сигнал остановиться и записать пожелание в бэклог.
5.2. Как это звучит
Аналитик. Марина, основание — версия v3 от 19 марта, вот она на экране. Вне объёма: СБП, отмена оператором, печатная форма. Согласны, что сегодня мы их не смотрим? Марина. Погодите, а как я буду закрывать день без печатной формы? Аналитик. Хороший вопрос, и он к делу. Записываю: «печатная форма возврата для закрытия дня» — этого нет в основании, значит, наша недоработка на этапе анализа, не команды. Вопрос: без неё вы сможете работать две недели вручную или это блокирует включение вообще? Марина. Две недели вручную вытяну, но не месяц. Аналитик. Тогда так: D-1, тип «упущение требований», блокирует не приёмку S1, а полное включение с 15 апреля. Оценку дадим завтра, приоритет — на груминге в четверг. Продолжаем по AC-1?
Что здесь сделано за 40 секунд: вопрос не отвергнут и не проглочен; названы тип и владелец; выяснена цена отсутствия (две недели ручной работы — терпимо, месяц — нет); приёмка S1 не заблокирована; спор не начался. Всё это — механика, а не характер.
5.3. Три фразы, которые превращают приёмку в спор
| Фраза | Что происходит на самом деле | Чем заменить |
|---|---|---|
| «Мы так и договаривались» | апелляция к памяти, а не к тексту | «в v3 это пункт AC-2, читаю дословно» |
| «Это же очевидно» | неявное требование объявляется общеизвестным | «этого нет в тексте — фиксируем как упущение» |
| «Ну доделайте, это же мелочь» | новая работа маскируется под гарантию | «оценим и поставим в очередь, решает владелец» |
6. Расхождение: два вопроса вместо спора
6.1. Матрица
Любое «это не то» раскладывается двумя вопросами: было ли это в согласованном основании и мешает ли расхождение получить заявленную пользу. Ответы дают квадрант, а квадрант — владельца, маршрут и цену.
Ключевой квадрант — левый верхний, «упущение требований». Именно там живут почти все конфликты, и именно там аналитику важно не защищаться. Признание «этого нет в тексте, значит, мы не спросили» стоит дёшево и сразу переводит разговор из плоскости вины в плоскость решения: что делаем с релизом. Попытка натянуть упущение на дефект («команда должна была догадаться») разрушает доверие быстрее, чем любой сорванный срок.
6.2. Маршрут расхождения
на приёмке"] --> Q1{"Есть в основании
версии v3?"} Q1 -->|"да, дословно"| Q2{"Мешает получить
заявленную пользу?"} Q1 -->|"нет"| Q3{"Мешает получить
заявленную пользу?"} Q1 -->|"текст допускает
оба прочтения"| AMB["Спор о толковании
→ считаем упущением,
текст переписываем"] Q2 -->|да| BUG["Блокирующий дефект
владелец: команда
срок: до релиза
приёмка отклонена"] Q2 -->|нет| NOTE["Замечание
принято с замечаниями
владелец + дата обязательны"] Q3 -->|да| GAP["Упущение требований
владелец: аналитик и владелец продукта
оценка → решение о релизе"] Q3 -->|нет| WISH["Новое пожелание
в бэклог, приоритет на груминге
приёмку не блокирует"] AMB --> GAP GAP --> DEC{"Можно жить
без этого?"} DEC -->|"да, обход есть"| REL["Релиз идёт,
доработка отдельной историей"] DEC -->|"нет, польза не достигается"| HOLD["Релиз ждёт,
пересматриваем объём или срок"] BUG --> RECHECK["Повторная проверка
только по этому пункту"] NOTE --> REG["Реестр замечаний,
обзор через неделю"] WISH --> REG2["Бэклог продукта
наравне со всем остальным"]
Обратите внимание на ветку «текст допускает оба прочтения». Это не юридическая тонкость, а самое частое реальное состояние: обе стороны читают одну фразу по-своему и обе искренни. Правило «двусмысленность толкуется как упущение анализа» снимает спор мгновенно, потому что делает ответ независимым от того, кто настойчивее. Формулируют это правило заранее — в момент, когда уже спорят, любое правило выглядит как приём в чужую пользу.
6.3. Карточка расхождения
# Одно расхождение — одна карточка. Пишется на сессии, при всех, вслух.
id: D-1
delivery: S1
raised_by: "Марина, руководитель поддержки"
raised_at: 2026-03-26
statement: >
Нет печатной формы возврата: бухгалтерия не может подшить основание
и закрыть день по кассе.
classification:
in_baseline: false # в v3 такого пункта нет — проверено дословно
blocks_value: partially # две недели работает ручной обход
type: "упущение требований"
quadrant: "верхний левый"
why_missed: >
На выявлении говорили с поддержкой и финансами, но не с бухгалтерией:
её не было в карте стейкхолдеров. Урок — раздел «кто закрывает период».
decision:
owner: "владелец продукта"
outcome: "S1 принимается; печатная форма — история S7, оценка 3 дня,
обязательна к полному включению 15.04"
workaround: "выгрузка в CSV раз в день, ответственная — Светлана"
due: 2026-04-10
cost_note: "отдельная работа, не гарантийное исправление"
Поле why_missed кажется бюрократией, но именно оно превращает приёмку в источник
улучшений. Через три-четыре карточки видна система: пропускаем бухгалтерию, забываем
про роль администратора, не спрашиваем про закрытие периода. Это прямой вход
в чек-лист выявления следующей фичи.
7. Решение: принято, с замечаниями, отклонено
7.1. Жизненный цикл поставки
стенд и данные готовы Package --> InReview: сессия началась InReview --> Rejected: блокирующий дефект
или невыполненный критерий InReview --> WithNotes: критерии выполнены,
есть неблокирующие замечания InReview --> Accepted: все критерии выполнены Rejected --> Package: исправлено, повторная проверка
только по спорным пунктам WithNotes --> Accepted: замечания закрыты к сроку WithNotes --> Rejected: срок сорван дважды,
эскалация владельцу продукта Accepted --> Pilot: флаг включён на 5% потока Pilot --> Prod: метрики пилота в норме две недели Pilot --> Package: метрики хуже плана,
флаг выключен, доработка Prod --> [*]
Три состояния решения — это минимум, который работает. Двух («принято / не принято») не хватает: всё серое проваливается в бесконечный торг. Пяти-семи — слишком много, статусы начинают жить своей жизнью.
Опасное состояние здесь одно — «принято с замечаниями». Оно превращается в свалку, если у замечания нет владельца и даты. Практическое правило: замечание без даты устранения не записывается; вместо него принимающий выбирает — либо это дефект и приёмка отклоняется, либо это пожелание и оно уходит в бэклог. Третьего не дано, и это лечит 90% вечных «хвостов».
7.2. Протокол приёмки
Протокол — не бюрократия, а способ не проводить эту же встречу второй раз. Минимальный рабочий формат помещается на страницу:
# Протокол приёмки S1 «Автовозврат: карта, до 3000 руб.»
Дата: 2026-03-26 · Версия основания: v3 от 19.03 · Сборка: 1.14.2 · Стенд: UAT
Участники и роли
- Марина (поддержка) — принимает AC-1, AC-2, AC-3
- Игорь (финансы) — принимает AC-4, NFR-3
- Пётр (QA) — доказательства; Аня (аналитик) — ведёт и протоколирует
Результаты по пунктам
| Пункт | Метод | Доказательство | Вердикт |
| --- | --- | --- | --- |
| AC-1 | прогон 6 заявок вручную | чек-лист от 26.03 | принято |
| AC-2 | 4 негативных случая | чек-лист от 26.03 | принято |
| AC-3 | выгрузка журнала за сутки | max = 11 мин | принято |
| AC-4 | двойной вызов + SQL | лог + запрос | принято |
| NFR-3 | нагрузочный прогон | отчёт, p95 = 640 мс | принято |
Расхождения
| ID | Тип | Суть | Владелец | Срок | Блокирует |
| --- | --- | --- | --- | --- | --- |
| D-1 | упущение требований | нет печатной формы | владелец продукта | 10.04 | полное включение |
| D-2 | замечание | текст ошибки пугает клиента | Аня + дизайнер | 27.03 | нет |
| D-3 | пожелание | история возвратов клиента | бэклог | — | нет |
Решение: ПРИНЯТО С ЗАМЕЧАНИЯМИ. Включение флага autorefund_enabled на 5% потока
с 27.03 при условии закрытия D-2. Полное включение — после S7 (D-1).
Подтвердили: Марина, Игорь. Разослано: 26.03, 18:40.
Ценность даёт не форма, а два свойства: именные вердикты и рассылка в тот же день. Протокол, отправленный через неделю, уже не документ, а версия событий.
8. Приёмка того, что не видно на экране
Функциональность проверить легко — её видно. Проблемы приходят оттуда, где смотреть не на что.
8.1. Нефункциональные требования
НФТ принимаются не «на глаз», а по отчёту с зафиксированным профилем нагрузки. Пункт основания должен содержать всё, что нужно для воспроизведения: величину, порог, профиль, среду, длительность, метод измерения.
| Свойство | Плохой пункт | Проверяемый пункт |
|---|---|---|
| Производительность | «работает быстро» | p95 решения ≤ 800 мс при 40 заявках/мин, 30 минут прогона |
| Надёжность | «не должно падать» | доля успешных отправок ≥ 99,5% за сутки пилота |
| Деградация | «должно работать при сбоях» | банк недоступен → заявка в очередь, статус «ожидает», ретрай 3 раза |
| Восстановление | «быстро восстановиться» | RTO 30 мин, RPO 5 мин — учения проведены, протокол приложен |
| Безопасность | «безопасно» | оператор без роли refund_admin получает 403; попытка в аудит-логе |
Числа берутся не с потолка — как их добывать, разобрано в нефункциональных требованиях, а методика прогонов — в нагрузочном тестировании. Ключевая ошибка приёмки НФТ: измерение на пустой базе. Отчёт «p95 = 120 мс» на стенде с тысячей записей ничего не говорит о проде с десятью миллионами.
8.2. Интеграции и контракты
Интеграция «работает» на демо и разваливается в проде, потому что на демо проверяют счастливый путь. Минимальный набор проверок на приёмке обмена:
# 1. Идемпотентность: два одинаковых запроса — один возврат
curl -s -X POST https://uat.api/refunds \
-H 'Idempotency-Key: 4f1c-...-9ab' -H 'Content-Type: application/json' \
-d '{"order_id": 88123, "amount": 2450.00, "reason": "SIZE"}'
curl -s -X POST https://uat.api/refunds \
-H 'Idempotency-Key: 4f1c-...-9ab' -H 'Content-Type: application/json' \
-d '{"order_id": 88123, "amount": 2450.00, "reason": "SIZE"}'
# ожидаем: одинаковый refund_id, второй ответ 200 (не 201), в БД одна строка
# 2. Ошибки: контракт обещает 409 при повторе с другой суммой
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://uat.api/refunds \
-H 'Idempotency-Key: 4f1c-...-9ab' -H 'Content-Type: application/json' \
-d '{"order_id": 88123, "amount": 100.00, "reason": "SIZE"}' # ждём 409
# 3. Таймаут смежной системы: что видит клиент и что остаётся в журнале
# (банк отвечает 30 с при заявленном таймауте 5 с)
Проверяются ровно те пункты, которые описаны в контракте: коды ошибок, идемпотентность, поведение при таймауте, формат сумм и дат, обязательность полей. Подробный разбор контрактов — в анализе интеграций и тестировании API.
8.3. Данные и миграции
Приёмка миграции — отдельный жанр: результат не виден в интерфейсе, а ошибка обнаруживается через месяц при закрытии квартала. Проверка строится на сверках «до и после», и их формулирует аналитик, потому что только он знает бизнес-смысл чисел:
-- 1. Ничего не потеряно и не размножилось
SELECT
(SELECT count(*) FROM legacy.refund_request) AS было,
(SELECT count(*) FROM refund_request WHERE source='legacy') AS стало;
-- 2. Деньги сходятся до копейки (главная сверка для финансов)
SELECT round(sum(amount), 2) FROM legacy.refund_request WHERE status = 'DONE'
UNION ALL
SELECT round(sum(amount), 2) FROM refund_request
WHERE source = 'legacy' AND state = 'COMPLETED';
-- 3. Нет сирот: каждая заявка привязана к существующему заказу
SELECT count(*) FROM refund_request r
LEFT JOIN "order" o ON o.id = r.order_id
WHERE o.id IS NULL; -- ожидаем 0
-- 4. Справочник причин отображён полностью, «прочее» не выросло
SELECT reason_code, count(*) FROM refund_request
WHERE source = 'legacy' GROUP BY 1 ORDER BY 2 DESC;
Правило приёмки данных: сверка выполняется на боевом объёме до включения записи, а её результат прикладывается к протоколу. Про словарь данных и смысл полей — в моделировании данных.
8.4. Права, аудит и приватность
Три вопроса, которые забывают почти всегда и которые дороже всего исправлять после релиза: кто может выполнить операцию (и что видит тот, кто не может); остаётся ли след в аудит-логе (кто, когда, по какому правилу, какая сумма); не утекают ли персональные данные в логи и в тексты писем. Каждый — отдельный пункт основания с отдельным принимающим, обычно из безопасности.
9. Формальная приёмка: договор, ТЗ, акт
9.1. Когда без бумаги нельзя
Формальная приёмка нужна там, где результат конвертируется в деньги или в ответственность: внешний подрядчик и фиксированная цена (контракты), государственный или регулируемый заказчик, поставка в другую организацию, всё, где возможен арбитраж. В продуктовой команде того же уровня формальности не требуется — там роль акта играют протокол и статус в трекере.
В российской практике каркас формальной приёмки задают ГОСТ 34.601 (стадии создания автоматизированных систем, включая опытную эксплуатацию и приёмочные испытания) и ГОСТ 34.603 (виды испытаний и порядок их проведения). Международный аналог по организации проверок — ISO/IEC/IEEE 29119. Читать их целиком аналитику не нужно; нужно понимать три вещи, которые они формализуют: программа и методика испытаний (что и как проверяем), протокол испытаний (что получилось) и акт (юридический факт приёмки).
9.2. Программа и методика испытаний глазами аналитика
ПМИ — это то же основание приёмки, только оформленное как таблица «пункт ТЗ → метод проверки → критерий положительного результата». Аналитик здесь делает ровно одну важную работу: переводит каждый пункт ТЗ в проверяемое действие. Пункты, которые не переводятся, надо переписывать в ТЗ, а не героически «проверять» на испытаниях.
| № | Пункт ТЗ | Метод проверки | Критерий положительного результата |
|---|---|---|---|
| 4.1.2 | Система автоматически принимает решение по заявке | прогон 12 заявок из набора D-набор-1 | все 12 обработаны согласно BR-14, расхождений 0 |
| 4.1.5 | Срок отправки возврата не более 30 минут | выгрузка журнала за 5 рабочих дней ОЭ | max задержки ≤ 30 мин, доля > 20 мин ≤ 5% |
| 4.3.1 | Ведётся журнал принятых решений | выборка 20 записей, сверка с заявками | 20 из 20 содержат правило, вход, время, результат |
| 5.2.4 | Разграничение доступа | попытки под 3 ролями | доступ только у refund_admin, отказы в аудит-логе |
9.3. План испытаний
Формальная приёмка — это проект внутри проекта, и её планируют. Типовая неделя приёмочных испытаний выглядит так:
Две ошибки планирования встречаются всегда: не заложено время на устранение замечаний (и тогда любой найденный дефект срывает срок акта) и не выделен сухой прогон (и тогда первый день испытаний уходит на «у нас стенд не поднялся»).
9.4. Опасность формальной приёмки
У формальной приёмки есть встроенный дефект: она проверяет соответствие ТЗ, а не пользу. Систему можно принять по всем пунктам и получить продукт, которым никто не пользуется — классический исход госпроектов. Противоядие: рядом с формальными пунктами держать два-три пункта про наблюдаемый результат — долю заявок, закрытых без оператора, среднее время обработки, число жалоб. Их не всегда удаётся включить в договор, но их всегда стоит измерить и показать; см. аналитику решений.
10. Документ или разговор у доски
Формальность приёмки должна соответствовать цене ошибки, а не привычке. Шкала:
| Ситуация | Достаточно | Не нужно |
|---|---|---|
| Правка текста на кнопке | сообщение в чате со скриншотом | протокола, встречи |
| Небольшая история внутри команды | вердикт по критериям в трекере, 15 минут | акта, комиссии |
| Фича, меняющая работу подразделения | сессия UAT + протокол + именные вердикты | ПМИ по ГОСТ |
| Деньги, персональные данные, регуляторика | пакет + протокол + доказательства в архиве | — |
| Внешний подрядчик, фиксированная цена | ПМИ, протокол испытаний, акт | — |
| Пилот новой гипотезы | метрики пилота и решение «раскатываем/нет» | формальной приёмки |
Разговор у доски незаменим в одном месте — при разборе расхождения. Как только классификация превращается в переписку, спор растягивается на недели: письмо всегда читается жёстче, чем произносится. Правило: расхождения обсуждаются голосом и в тот же день, а результат обсуждения фиксируется письменно. Наоборот — не работает.
11. Что чаще всего ломается
11.1. Неявные требования всплывают на приёмке
Симптом. «А где печатная форма?», «А как это будет выглядеть в отчёте?»,
«А кто это увидит в мобильном приложении?»
Корень. Требование существовало в голове человека, которого не спросили,
или казалось настолько очевидным, что его не записали.
Лечение до. Явный out_of_scope в каждой истории и его зачитывание вслух
в начале сессии; вопрос на выявлении «кто закрывает период / сверяет / отчитывается
этими данными»; карта стейкхолдеров с ролями, а не с должностями.
Лечение во время. Не спорить. Классифицировать как упущение, выяснить цену
отсутствия, отделить приёмку текущей поставки от решения о полном включении.
11.2. Противоречия стейкхолдеров вскрываются в момент решения
Симптом. Финансы принимают, поддержка отказывается; каждый ссылается на «согласованное» — и оба говорят правду про разные версии. Корень. Противоречие не было разрешено на этапе требований, а было заклеено формулировкой, которую каждый прочитал в свою пользу. Лечение. Один принимающий на пункт, зафиксированный до старта; двусмысленный текст трактуется как упущение; при живом конфликте — не голосование, а эскалация к тому, кто владеет процессом целиком (см. стейкхолдеров).
11.3. «Хотелки» приходят прямо на приёмку
Симптом. «Раз уж вы всё равно здесь — добавьте фильтр по дате, это же две минуты». Корень. Приёмка — редкая встреча, где в одной комнате есть и заказчик, и команда; соблазн решить всё сразу непреодолим. Лечение. Правило объявляется в первые тридцать секунд сессии: новые идеи записываются и уходят в бэклог, приёмку они не блокируют. Ответ ровно один: «записал, приоритет — на груминге». Отдельно проговаривается, что это не отказ, а очередь.
11.4. Непроверяемые критерии
Симптом. Спор «удобно / неудобно», в котором обе стороны не могут ни доказать, ни опровергнуть. Корень. Критерий писали как пожелание, а не как проверку; никто не спросил «как мы поймём, что это выполнено». Лечение до. Линтер основания (§ 2.4) и вопрос «можно ли по этому пункту написать автотест, не задав ни одного вопроса». Для действительно субъективных свойств — заменить мнение на измерение: не «удобно», а «оператор проходит сценарий за ≤ 90 секунд без обращения к инструкции, 8 из 10 участников» (метод — в юзабилити-тестировании).
11.5. Приёмка «в конце»
Симптом. Три месяца разработки, потом неделя приёмки, на которой выясняется, что первая половина сделана не так. Корень. Обратная связь отложена, партия работы огромна, цена исправления выросла на порядок. Лечение. Приёмка маленькими порциями: каждая вертикальная история принимается отдельно; принимающий видит систему раз в неделю, а не раз в квартал. Это же — главный аргумент в пользу тонкой нарезки из аналитика в Agile.
11.6. Приёмка под давлением срока
Симптом. «Принимаем, потому что релиз завтра и деньги уже проведены». Корень. Приёмка формально проведена, фактически отменена; риск не исчез, а сменил владельца. Лечение. Разделить решения: «принято» отдельно, «выпускаем несмотря на» — отдельно, с явным списком принятых рисков и именем того, кто их принимает. Это честнее и, как ни странно, проходит легче: люди готовы брать риск, но не готовы подписываться под ложью.
11.7. Приёмка по красивому демо
Симптом. Всё показали, все довольны, через неделю поток дефектов. Корень. Прогонял разработчик по счастливому пути на подготовленных данных. Лечение. Мышку держит принимающий; данные включают границы и ошибки; хотя бы один негативный сценарий обязателен в каждой сессии.
12. Метрики здоровья приёмки
Приёмка — процесс, и у него есть измеримое состояние. Пять чисел, которые полезно считать по кварталу:
| Метрика | Как считать | Ориентир | О чём говорит отклонение |
|---|---|---|---|
| Доля принятых с первого раза | принято без отклонения / все поставки | 70–85% | ниже — основание пишется формально; выше 95% — приёмка формальна, смотрят не глядя |
| Доля расхождений типа «упущение» | упущения / все расхождения | ≤ 30% | больше — проблема на выявлении, а не в разработке |
| Время цикла приёмки | от «готово» до решения | ≤ 3 дней | больше — принимающий не выделен или не имеет полномочий |
| Покрытие доказательствами | пунктов с приложенным доказательством / всех | 100% | меньше — «принято на словах», спор впереди |
| Дефекты после приёмки | найдено в проде за 30 дней после включения | тренд вниз | рост — приёмка проходит на нереалистичных данных |
Метрики нужны не для отчёта наверх, а для разговора внутри команды: если доля упущений держится на 50%, чинить надо не приёмку, а выявление. Про метрики поставки в целом — качество и поставка.
Мини-итог
- Приёмка — решение, а не мероприятие. Три опоры: основание, доказательство, полномочие.
- Слово «приёмка» означает пять разных вещей. Назовите свои ворота: кто принимает, по какому тексту, что считается отказом.
- Основание фиксируется до старта, с версией и датой заморозки.
out_of_scopeснимает больше споров, чем сами критерии. - Пункт без доказательства не считается проверенным. «Мы видели на демо» — не доказательство.
- Один принимающий на пункт. Комитет производит не решение, а протокол разногласий.
- Любое «это не то» раскладывается двумя вопросами: было ли в основании, мешает ли пользе. Четыре квадранта — четыре разных маршрута и разные плательщики.
- Двусмысленный текст трактуется как упущение анализа. Правило объявляется заранее.
- Три вердикта: принято / с замечаниями / отклонено. Замечание без владельца и даты не записывается.
- НФТ, интеграции, миграции и права принимаются по отчётам и сверкам, а не «на глаз».
- Формальность — по цене ошибки: от сообщения в чате до ПМИ и акта. Расхождения обсуждаются голосом, фиксируются письменно.
Чек-лист перед сессией: основание с версией на руках · принимающий назван по каждому
пункту · out_of_scope готов к зачитыванию · стенд, данные и учётные записи проверены ·
сухой прогон выполнен · известные дефекты предъявлены заранее · правило «новые идеи —
в бэклог» объявлено · протоколист назначен · в календаре есть слот на разбор расхождений
в тот же день.
Источники
- Karl Wiegers, Joy Beatty. Software Requirements, 3rd ed. — главы про верификацию и валидацию требований: processimpact.com.
- IIBA. A Guide to the Business Analysis Body of Knowledge (BABOK Guide) — задачи «Validate Requirements» и «Verify Requirements»: iiba.org.
- Gojko Adzic. Specification by Example — примеры как основание приёмки: gojko.net.
- Gojko Adzic. Impact Mapping — как связать приёмку с результатом, а не с объёмом работ: impactmapping.org.
- Martin Fowler. GivenWhenThen — martinfowler.com.
- Dan North. Introducing BDD — dannorth.net.
- ISTQB. Certified Tester Foundation Level Syllabus — уровни тестирования, включая приёмочное: istqb.org.
- ISO/IEC/IEEE 29119 Software Testing — организация и документация испытаний: iso.org.
- ГОСТ 34.601-90 (стадии создания АС, опытная эксплуатация, приёмочные испытания) и ГОСТ 34.603-92 (виды испытаний) — тексты доступны на protect.gost.ru.
- Barry Boehm. Software Engineering Economics — цена исправления дефекта в зависимости от стадии обнаружения: en.wikipedia.org.
- Scrum Guide — обзор спринта как событие обратной связи, а не приёмки: scrumguides.org.
- Требования и их проверка в архитектурном контексте — требования.
Что дальше
Приёмкой заканчивается цикл работы с одной поставкой, но не работа аналитика. Остаётся разобраться, чем всё это делают руками: где живут требования, чем рисуют схемы, как устроены грейды от junior до lead, чем системный аналитик отличается от бизнес- и продуктового, и что учить дальше, чтобы расти не вширь, а вглубь.
Инструменты и карьера аналитика: грейды, специализации, что учить дальше