Тест-кейсы, чек-листы, тест-план и как писать баг-репорт, который починят
Тестовая документация — самая нелюбимая часть профессии и самая недооценённая. Нелюбимая, потому что её пишут «для отчётности» и никто не читает. Недооценённая, потому что хорошо написанный артефакт — это способ передать знание о системе другому человеку и себе-через-полгода, а плохо написанный — способ потратить неделю и получить папку мёртвых файлов.
Эта статья про то, как выбирать формат осознанно: что документировать подробно, что — одной строкой, а что вообще не документировать, потому что дешевле проверить заново, чем поддерживать описание.
В предыдущей статье — тест-дизайн — мы разбирали, какие проверки нужны. Здесь — в какой форме их зафиксировать.
Зачем вообще писать, если можно просто протестировать
Документация решает четыре задачи, и только четыре. Если ваш артефакт не решает ни одну — его не нужно писать.
- Передача знания. Новый человек в команде должен за день понять, что и как проверяется. Устно это не масштабируется.
- Воспроизводимость. Регресс через полгода должен пройти так же, как сегодня, даже если исходный тестировщик уволился.
- Согласование ожиданий. «Ожидаемый результат» в тест-кейсе — это зафиксированный контракт: аналитик, разработчик и тестировщик договорились, что система должна делать. Половина багов ловится не при выполнении кейса, а при его написании.
- Аудит и соответствие требованиям. В медицине, финтехе, авиации документация обязательна по стандартам (IEC 62304, DO-178C, ISO 26262). Там вопрос «а нужно ли» не стоит.
Всё остальное — «менеджер попросил», «так принято», «чтобы было» — не задачи, а симптомы.
Взгляд тестировщика: документация — рабочий инструмент и доказательство проделанной работы. Взгляд разработчика: документация — то, что устаревает быстрее, чем код, и «настоящий тест — это исполняемый тест».
Оба правы в своей зоне. Автотест не заменит чек-лист исследовательской сессии для новой фичи без стабильного UI, а сотня ручных тест-кейсов на бизнес-логику калькулятора — это сотня юнит-тестов, которые не написали.
Спектр формализации: от «в голове» до сертифицируемого кейса
Форматы документации — не набор коробок, а непрерывная шкала подробности. Чем подробнее — тем дороже написание и поддержка, но тем ниже требования к квалификации исполнителя и тем выше воспроизводимость.
(строка в блокноте)"] --> B["Чек-лист
(что проверить)"] B --> C["Тест-кейс
(шаги + ожидание)"] C --> D["Тест-кейс с данными
(точные значения, скриншоты)"] D --> E["Автотест
(исполняемая спецификация)"] A -.->|дёшево писать
невоспроизводимо| A E -.->|дорого писать
исполняется само| E style A fill:#4a90d9,fill-opacity:0.15 style C fill:#e0a252,fill-opacity:0.2 style E fill:#4caf82,fill-opacity:0.2
Ключевое решение принимается по трём осям:
| Ось | В сторону чек-листа | В сторону подробного кейса |
|---|---|---|
| Кто выполняет | автор или эксперт в домене | новичок, аутсорс, другая команда |
| Частота выполнения | один раз, разово | каждый релиз, годами |
| Цена ошибки | низкая, обнаружится быстро | регуляторка, деньги, здоровье |
| Стабильность требований | фича меняется каждую неделю | логика заморожена |
Простое правило: если проверку выполнит один и тот же человек, который её придумал, в течение ближайшей недели — хватит строки в чек-листе. Всё, что переживёт эту неделю или уйдёт другому человеку, требует шагов.
через код?"} Q1 -->|"да, стабильный
интерфейс"| Auto["Автотест
(unit / api / e2e)"] Q1 -->|"нет: визуал, UX,
исследование"| Q2{"Выполнят другие
люди много раз?"} Q2 -->|нет| CL["Чек-лист
или тест-идея"] Q2 -->|да| Q3{"Цена ошибки
высокая?"} Q3 -->|нет| CL2["Чек-лист
с уточнениями"] Q3 -->|да| TC["Полный тест-кейс
с точными данными"] style Auto fill:#4caf82,fill-opacity:0.2 style TC fill:#e05252,fill-opacity:0.15
Чек-лист: минимальная полезная документация
Чек-лист — список проверок без описания шагов. Его сила в скорости написания и в том, что он не мешает думать: исполнитель сам решает, как проверить, опираясь на знание системы.
Плохой чек-лист выглядит как список существительных: «Авторизация», «Корзина», «Оплата». Это оглавление, а не чек-лист — по нему нельзя понять, проверено что-то или нет.
Хороший чек-лист состоит из проверяемых утверждений, каждое из которых однозначно закрывается ответом «да / нет».
# Чек-лист: применение промокода в корзине
## Позитивные сценарии
- [ ] Валидный процентный промокод уменьшает итог на нужный процент
- [ ] Валидный фиксированный промокод (−10 EUR) уменьшает итог на 10 EUR
- [ ] Скидка отображается отдельной строкой в итоговой сумме
- [ ] Промокод сохраняется после перезагрузки страницы корзины
- [ ] Промокод переносится на шаг оплаты и попадает в созданный заказ
## Границы и негатив
- [ ] Истёкший промокод отклоняется с понятным текстом ошибки
- [ ] Промокод с исчерпанным лимитом активаций отклоняется
- [ ] Промокод, применённый повторно, не суммируется сам с собой
- [ ] Скидка больше суммы корзины даёт итог 0, а не отрицательное число
- [ ] Промокод в нижнем регистре / с пробелами по краям принимается
- [ ] Пустое поле и ввод из 200 символов не ломают форму
## Взаимодействия
- [ ] Промокод + товар по акции: правила комбинирования как в требованиях (см. REQ-412)
- [ ] Удаление последнего товара сбрасывает применённый промокод
- [ ] Смена валюты пересчитывает фиксированную скидку по курсу
- [ ] Промокод для категории не применяется к товарам вне категории
## Нефункциональное
- [ ] Ответ на применение промокода приходит быстрее 1 с на stage
- [ ] Поле промокода доступно с клавиатуры, ошибка озвучивается скринридером
- [ ] Ошибка «неверный промокод» не раскрывает, существует ли такой код (перебор)
Обратите внимание на структуру: секции соответствуют категориям тест-дизайна, а не экранам интерфейса. Это не случайно — группировка по технике не даёт пропустить целый класс проверок.
Типичные ошибки в чек-листах:
- Пункты, требующие интерпретации: «проверить корректность расчёта» — а что такое корректность?
- Смешение уровней: рядом стоят «залогиниться» и «проверить всю бизнес-логику скидок».
- Отсутствие ссылок на требования — через год никто не вспомнит, откуда взялось ожидание.
- Чек-лист как копия ТЗ: если пункт слово в слово повторяет требование, он не добавляет знания.
Тест-кейс: когда нужны шаги
Тест-кейс — это чек-лист-пункт, развёрнутый до уровня «выполнит незнакомый с системой человек». Канонический состав описан в стандарте ISO/IEC/IEEE 29119-3, но на практике достаточно семи полей.
| Поле | Зачем | Частая ошибка |
|---|---|---|
| ID | ссылаться из багов и отчётов | человекочитаемый ID, который меняется |
| Название | понять суть, не открывая | «Тест 1», «Проверка корзины» |
| Приоритет | что гонять при нехватке времени | у всех High |
| Предусловия | стартовое состояние системы | «пользователь залогинен» без указания какого |
| Шаги | воспроизводимость | смешаны действия и проверки |
| Ожидаемый результат | критерий прохождения | «всё работает корректно» |
| Тестовые данные | повторяемость | «любой товар» |
Пример нормального кейса:
id: TC-CART-0142
title: "Фиксированный промокод в EUR уменьшает итог на номинал скидки"
priority: High
component: checkout/promo
requirements: [REQ-412, REQ-418]
preconditions:
- "Пользователь qa+eur@test.io авторизован, валюта аккаунта EUR"
- "Корзина пуста"
- "В админке активен промокод FIX10EUR: тип fixed, номинал 10.00 EUR, лимит 100"
steps:
- action: "Добавить в корзину товар SKU-1001 (цена 45.00 EUR) в количестве 2"
expected: "Итог корзины 90.00 EUR"
- action: "Ввести FIX10EUR в поле «Промокод» и нажать «Применить»"
expected: |
Появляется строка «Скидка −10.00 EUR».
Итог становится 80.00 EUR.
Поле промокода переходит в состояние applied (код нельзя изменить, есть крестик).
- action: "Обновить страницу (F5)"
expected: "Промокод остаётся применённым, итог 80.00 EUR"
postconditions:
- "Промокод FIX10EUR имеет счётчик активаций +0 (списывается только при оплате)"
Три правила, которые отличают рабочий кейс от бумажного:
- Ожидаемый результат у каждого шага, а не один в конце. Иначе при падении непонятно, где именно разошлось поведение.
- Точные данные вместо «любых». «Товар за 45.00 EUR, количество 2» воспроизводимо, «какой-нибудь товар» — нет. Полезный побочный эффект: числа подобраны так, что ошибка округления или неверный порядок операций сразу видна.
- Кейс проверяет одну идею. Кейс на 40 шагов, покрывающий весь чекаут, падает на шаге 6 и не даёт информации об остальных 34.
Атомарность и её цена
Соблазн написать один длинный сценарий велик: меньше кейсов, меньше повторов подготовки данных. Но у атомарности есть измеримая выгода — локализация дефекта. Если кейс проверяет одно утверждение, факт падения сразу указывает на область кода.
Компромисс, который работает: длинные сквозные сценарии допустимы для смоука («деньги проходят по всей цепочке»), атомарные кейсы — для регресса конкретной логики. Подробнее про типы прогонов — в статье про ручное тестирование.
Тест-кейс как код: сближение с автоматизацией
Разработчику формат выше кажется избыточным — и он прав, если проверку можно выразить кодом. Тот же кейс на pytest, где параметризация заменяет десяток бумажных кейсов:
import pytest
from decimal import Decimal
from shop.cart import Cart
from shop.promo import Promo, PromoError
# Каждая строка — отдельный тест-кейс из «бумажного» набора.
# Название параметра попадает в отчёт, поэтому пишем его как заголовок кейса.
@pytest.mark.parametrize(
"subtotal, promo, expected_total",
[
(Decimal("90.00"), Promo.fixed("FIX10EUR", Decimal("10.00")), Decimal("80.00")),
(Decimal("90.00"), Promo.percent("SALE20", 20), Decimal("72.00")),
# Граница: скидка больше суммы — итог не уходит в минус.
(Decimal("5.00"), Promo.fixed("FIX10EUR", Decimal("10.00")), Decimal("0.00")),
# Граница: скидка ровно равна сумме.
(Decimal("10.00"), Promo.fixed("FIX10EUR", Decimal("10.00")), Decimal("0.00")),
# Округление: 33.33 * 0.85 = 28.3305 -> банковское округление до 28.33.
(Decimal("33.33"), Promo.percent("SALE15", 15), Decimal("28.33")),
],
ids=[
"фиксированная скидка вычитается из суммы",
"процентная скидка считается от суммы",
"скидка больше суммы даёт ноль, а не отрицательный итог",
"скидка равна сумме даёт ровно ноль",
"процент округляется до копеек по правилам банка",
],
)
def test_promo_applies_to_subtotal(subtotal, promo, expected_total):
cart = Cart(subtotal=subtotal, currency="EUR")
cart.apply(promo)
assert cart.total == expected_total
def test_expired_promo_rejected_without_leaking_existence():
cart = Cart(subtotal=Decimal("90.00"), currency="EUR")
expired = Promo.fixed("OLD2019", Decimal("10.00"), expired=True)
with pytest.raises(PromoError) as err:
cart.apply(expired)
# Текст ошибки одинаков для «истёк» и «не существует»:
# иначе перебором можно узнать список валидных кодов.
assert str(err.value) == "Промокод недействителен"
assert cart.total == Decimal("90.00") # сумма не изменилась
Эти пять параметров — та же таблица границ, что и в бумажном кейсе, но она
исполняется в CI за миллисекунды и не может протухнуть незаметно.
Осторожно с ловушкой: ids на русском читаемы в отчёте, но некоторые
CI-парсеры плохо работают с не-ASCII в именах тестов — проверьте свой пайплайн.
Где граница. Кодом хорошо выражается всё, что имеет детерминированный проверяемый выход: расчёты, статусы, схемы ответов. Плохо — «понятно ли пользователю сообщение об ошибке», «не выглядит ли форма сломанной на узком экране», «есть ли способ сделать это за меньшее число кликов». Для второго нужен человек и чек-лист, а не кейс на 20 шагов.
Тест-план: документ, который обычно пишут зря
Классический тест-план по IEEE 829 — это 20 страниц, где 18 никто не откроет. При этом сама задача реальна: договориться до начала работы о том, что считается достаточным тестированием. Меняется не задача, а объём.
Живой тест-план помещается на одну страницу и отвечает на семь вопросов:
# Тест-план: релиз 4.18 «Мультивалютный чекаут»
## 1. Что тестируем (scope)
Расчёт корзины и промокодов в EUR/USD/GBP, конвертация по курсу дня,
отображение валюты в письмах и чеках.
## 2. Что НЕ тестируем (out of scope) — и почему
- Интеграция с новым эквайрингом — переносится в 4.19, за флагом.
- Локализация текстов — отдельный процесс перевода, отвечает контент-команда.
- Нагрузка — профиль трафика не меняется, риск оценён как низкий.
## 3. Риски и их приоритет
| Риск | Вероятность | Влияние | Что делаем |
|---|---|---|---|
| Ошибка округления при конвертации | средняя | критическое (деньги) | property-based тесты + сверка с бухгалтерией на 1000 заказов |
| Курс не обновился, применился вчерашний | низкая | высокое | интеграционный тест с подменой времени + алерт в проде |
| Промокод в одной валюте применяется в другой | высокая | высокое | матрица валюта × тип промокода, 12 кейсов |
| Съехала вёрстка символа валюты | высокая | низкое | визуальный смоук на 3 разрешениях, без автоматизации |
## 4. Подход
- Юнит и property-based на расчёты — разработчики, в рамках PR.
- API-тесты матрицы валют — автоматизируются, гоняются в CI на каждый merge.
- E2E — только один сквозной сценарий покупки в EUR (smoke).
- Исследовательская сессия 2 × 90 минут по хартии «деньги и валюты».
## 5. Критерии входа
Фича на stage, курсы валют заполнены, тестовые аккаунты по валютам созданы.
## 6. Критерии выхода
- Все P0/P1 кейсы пройдены, открытых Blocker/Critical нет.
- Сверка 1000 заказов с бухгалтерским расчётом: расхождений 0.
- Известные Major-дефекты приняты владельцем продукта письменно.
## 7. Ресурсы и сроки
2 инженера × 4 дня, окно регресса 12–15 числа, релизное окно 16-го.
Раздел «что НЕ тестируем» — самый ценный и самый пропускаемый. Именно он превращает план из списка благих намерений в управленческое решение: команда сознательно приняла риск, и после релиза разговор идёт не «почему вы это не проверили», а «мы приняли этот риск, он реализовался, пересматриваем ли оценку».
Риск-ориентированное планирование
Тестировать всё одинаково — гарантированный способ потратить бюджет не туда. Приоритет проверки определяется двумя множителями: вероятностью дефекта и ущербом от него.
Вероятность выше там, где: код только что переписали, логика сложная, много интеграций, автор новый в проекте, область исторически багованная (смотрите статистику дефектов по компонентам — она у вас уже есть в трекере).
Практический приём: перед регрессом возьмите список изменённых файлов
(git diff --stat release/4.17..release/4.18), сопоставьте с компонентами
и потратьте 70% времени на то, что менялось, а не на равномерный обход всего приложения.
Это и есть основной механизм экономии — подробности про экономику автоматизации
разбираются в статье про стратегию автоматизации.
Баг-репорт: главный текст, который вы пишете
Тест-кейс читают несколько человек. Баг-репорт читают все: разработчик, тимлид, менеджер, поддержка, а через год — тот, кто расследует похожий инцидент. Это самый ценный текст тестировщика и главный источник репутации.
Ключевой критерий готовности один: разработчик должен воспроизвести баг, не задав вам ни одного вопроса. Каждый вопрос в комментариях — это переключение контекста ценой в полчаса и один потерянный день в цикле.
Заголовок по формуле «где — что — при каком условии»
Заголовок читают в списке из двухсот тикетов, у него есть три секунды.
| Плохо | Хорошо |
|---|---|
| Не работает промокод | [Checkout] Промокод не применяется при валюте EUR — итог остаётся без скидки |
| Ошибка на проде!!! | [Payments] 500 при оплате картой Mir на суммах свыше 100 000 ₽ |
| Кривая вёрстка | [Cart] На iPhone SE (375px) кнопка «Оплатить» уезжает за пределы экрана |
| Приложение падает | [Android] Краш при возврате из фоновой камеры на этапе загрузки аватара |
Шаги: атомарные, нумерованные, начинающиеся с известного состояния
Худшая формулировка шагов — «сделать как обычно». Вторая худшая — «повторить шаги из TC-142», потому что кейс завтра отредактируют и репорт потеряет смысл.
Проверьте свои шаги вопросом: сможет ли их выполнить человек, который открыл ваш продукт впервые? Если для шага 3 нужно догадаться, где находится кнопка — шаг не готов.
Severity против Priority: разные люди, разные шкалы
Это самое частое место конфликта тестировщика и менеджера.
- Severity (серьёзность) — техническая характеристика: насколько сильно сломана функциональность. Ставит тестировщик, объективно.
- Priority (приоритет) — бизнес-решение: когда чинить. Ставит владелец продукта или тимлид.
Комбинации, которые кажутся парадоксальными, но нормальны:
| Severity | Priority | Пример |
|---|---|---|
| Blocker | Low | Падает функция, которой пользуются 3 клиента, и есть обходной путь |
| Trivial | High | Опечатка в названии компании на главной странице перед конференцией |
| Critical | High | Потеря данных при сохранении черновика |
| Minor | Low | Тень у кнопки на 1px больше макета |
Ошибка новичка — завышать severity, чтобы «заметили». Это работает ровно два раза, после чего ваши оценки перестают учитывать вообще.
Жизненный цикл дефекта
Понимание маршрута тикета объясняет, почему определённые поля обязательны.
Две метрики этого цикла показывают качество ваших репортов:
- Доля Rejected / Not reproducible. Норма — до 5–7%. Выше 15% означает, что вы плохо описываете окружение или заводите баги на неутверждённые требования.
- Доля Reopened. Высокая — сигнал, что «ожидаемый результат» сформулирован неоднозначно и разработчик чинит не то.
Как писать так, чтобы починили
Пять приёмов, которые реально сокращают время до фикса:
- Сузьте область до минимума. Не «не работает чекаут», а «ломается только при валюте EUR, на USD и GBP всё в порядке, воспроизводится с любого аккаунта». Половина работы разработчика — локализация; сделав её, вы экономите часы.
- Приложите машиночитаемые доказательства. Скриншот показывает симптом,
а HAR-файл, запрос/ответ API, стектрейс и
traceIdпоказывают причину. ОдинtraceIdиз логов ценнее пяти скриншотов. - Отделяйте факт от гипотезы. «Похоже, курс не подтягивается» — гипотеза, пишите её в отдельный абзац «Наблюдения», а не в фактический результат. Ошибочная гипотеза в шапке уводит разработчика на ложный след.
- Один тикет — один дефект. Иначе половину починят, тикет закроют, вторая половина потеряется.
- Укажите регрессию явно. «На сборке 4.17.2 работает, на 4.18.0-rc3 сломано» —
это подарок: разработчик получает диапазон коммитов и делает
git bisect.
Автоматизировать часть сбора контекста легко — например, скрипт, который собирает окружение прямо в момент падения теста:
// playwright/fixtures/bugContext.ts
// Собирает контекст для баг-репорта при падении теста:
// скриншот, трейс, консоль браузера и traceId последнего запроса.
import { test as base, expect, type Page } from '@playwright/test';
import * as fs from 'node:fs/promises';
type BugContext = { traceIds: string[]; consoleErrors: string[] };
export const test = base.extend<{ bug: BugContext }>({
bug: async ({ page }: { page: Page }, use, testInfo) => {
const ctx: BugContext = { traceIds: [], consoleErrors: [] };
// Копим traceId из заголовков ответов — по нему разработчик найдёт запрос в логах.
page.on('response', (res) => {
const id = res.headers()['x-trace-id'];
if (id) ctx.traceIds.push(id);
});
page.on('console', (msg) => {
if (msg.type() === 'error') ctx.consoleErrors.push(msg.text());
});
await use(ctx);
// Всё интересное складываем только при падении — иначе засорим артефакты CI.
if (testInfo.status !== testInfo.expectedStatus) {
const report = [
`# ${testInfo.title}`,
``,
`## Окружение`,
`- base URL: ${process.env.BASE_URL ?? 'не задан'}`,
`- build: ${process.env.BUILD_VERSION ?? 'неизвестен'}`,
`- браузер: ${testInfo.project.name}`,
``,
`## traceId последних запросов`,
ctx.traceIds.slice(-5).map((t) => `- \`${t}\``).join('\n') || '- нет',
``,
`## Ошибки консоли`,
ctx.consoleErrors.slice(0, 10).map((e) => `- ${e}`).join('\n') || '- нет',
].join('\n');
const file = testInfo.outputPath('bug-report.md');
await fs.writeFile(file, report, 'utf-8');
testInfo.attachments.push({
name: 'bug-report',
path: file,
contentType: 'text/markdown',
});
}
},
});
export { expect };
Такой фикстур превращает падение автотеста в почти готовый репорт: остаётся дописать заголовок и severity. Про борьбу с хрупкостью самих E2E-тестов — в статье про E2E и UI.
Трассируемость: связь требований, кейсов и багов
Матрица трассируемости (RTM) отвечает на два вопроса: «покрыто ли требование хоть чем-нибудь» и «если это требование изменится, какие тесты чинить».
Полноценную RTM в отдельной таблице поддерживать дорого и почти всегда бессмысленно —
она устаревает за спринт. Работающий вариант: хранить связи там, где живут артефакты.
Тег REQ-412 в тест-кейсе, номер тикета в названии автотеста, ссылка на кейс в баге.
Тогда трассируемость восстанавливается запросом, а не ручной синхронизацией.
# Мини-отчёт покрытия требований: какие требования не упомянуты
# ни в одном тест-кейсе. Читает YAML-кейсы и список требований.
# Сложность: O(N * K) по времени, где N — число кейсов, K — среднее
# число требований в кейсе; O(R + N) по памяти (R — число требований).
import pathlib
from collections import defaultdict
import yaml
def coverage_gaps(cases_dir: str, requirements: set[str]) -> dict[str, list[str]]:
"""Возвращает {req_id: [case_id, ...]} и пустые списки для непокрытых."""
covered: dict[str, list[str]] = defaultdict(list)
for path in pathlib.Path(cases_dir).rglob("*.yaml"):
case = yaml.safe_load(path.read_text(encoding="utf-8"))
for req in case.get("requirements", []):
covered[req].append(case["id"])
# Требования без кейсов — то, ради чего отчёт и нужен.
return {req: covered.get(req, []) for req in sorted(requirements)}
if __name__ == "__main__":
result = coverage_gaps("tests/cases", {"REQ-412", "REQ-418", "REQ-501"})
for req, cases in result.items():
mark = "OK " if cases else "GAP"
print(f"{mark} {req}: {', '.join(cases) or 'нет кейсов'}")
Важная оговорка. Покрытие требований кейсами — не показатель качества, а показатель отсутствия явных дыр. Требование может быть покрыто одним поверхностным кейсом и всё равно содержать десяток дефектов. Про то, почему процент покрытия — плохая цель, подробно в статье про тесты в CI.
Честно про боль
Документация устаревает быстрее, чем вы её пишете. Набор из 3000 ручных тест-кейсов, который поддерживают два человека, — это фикция: реально живут и обновляются 200–300 из них, остальные проходят «по памяти» или проставляются пройденными не глядя. Лучше 300 честных кейсов, чем 3000 мёртвых.
Отчёт о прогоне часто пишется ради менеджера. Если единственный потребитель документа — слайд в презентации, документ можно заменить одной строкой в чате. Проверяйте: спросите через две недели, открывал ли его кто-нибудь.
Подробность кейса не гарантирует находки. Кейс на 15 шагов с точными данными проверяет ровно один заранее известный путь. Дефекты живут там, куда никто не догадался пойти, — поэтому формальные кейсы всегда идут в паре с исследовательским тестированием, а не вместо него.
Тест-кейс-менеджмент-системы (TestRail, Xray, Allure TestOps, Qase) — не решение проблемы, а перенос её в интерфейс с оплатой за место. Они полезны, когда есть регуляторное требование или большая распределённая команда. Если у вас пять человек и всё в Git — Markdown-файлы рядом с кодом работают лучше и версионируются вместе с фичей.
Мини-итог
- Выбирайте формат по трём осям: кто выполняет, сколько раз, какова цена ошибки.
- Чек-лист состоит из проверяемых утверждений, а не из существительных.
- В тест-кейсе — ожидаемый результат у каждого шага и точные данные вместо «любых».
- Тест-план на одну страницу с явным «что не тестируем» полезнее двадцати страниц по IEEE 829.
- Приоритет проверок = вероятность дефекта × ущерб; 70% времени идёт на изменённое.
- Баг-репорт готов, когда разработчик воспроизведёт его без единого вопроса.
- Severity ставит инженер, Priority — бизнес; путать их дорого.
- Метрики Rejected и Reopened — прямой отчёт о качестве вашей документации.
Источники
- ISO/IEC/IEEE 29119-3:2021 «Test documentation» — iso.org
- ISTQB Certified Tester Foundation Level Syllabus — istqb.org
- Cem Kaner, «Lessons Learned in Software Testing» — про формализацию и её цену
- James Bach, «Test Plan Evaluation Model» — satisfice.com
- Simon Tatham, «How to Report Bugs Effectively» — chiark.greenend.org.uk
- Документация Playwright по тестовым артефактам — playwright.dev
Что дальше
Ручное тестирование: исследовательское, смоук, регресс, приёмочное — как применять чек-листы и кейсы в реальных прогонах, чем хартия исследовательской сессии отличается от тест-плана и почему регресс без приоритизации превращается в бесконечный обход приложения.