Сквозной пример: тестируем форму регистрации
Берём одну скромную форму на четыре поля и проходим по ней весь маршрут тестировщика — от вопросов аналитику до баг-репорта, который починят.
Сквозной пример (end-to-end) — прогон одной небольшой функции через весь цикл работы тестировщика: разбор требований, чек-лист, тест-дизайн, выполнение проверок и оформление найденных дефектов.
До сих пор техники жили по отдельности: в одном уроке классы эквивалентности, в другом — баг-репорт, в третьем — DevTools. На собеседовании и на работе от вас ждут другого: чтобы вы взяли требование и превратили его в набор проверок, а потом в понятный отчёт. Именно этот переход и вызывает ступор у новичков — техники вроде знакомы, а с чего начать на живой задаче, непонятно.
Поэтому давайте сделаем это вместе. Наш объект — форма регистрации в интернет-магазине. Четыре поля, одна кнопка. Кажется, там нечего тестировать. Сейчас увидим, что там прячется десяток багов и целая пачка неотвеченных вопросов.
Шаг 0. Читаем требования и ищем в них дыры
Вот всё, что нам передал аналитик. Такое требование — не карикатура, это типичный уровень детализации в реальном спринте.
ФТ-14. Форма регистрации
Поля: Email, Пароль, Возраст, чекбокс «Согласен с условиями».
1. Email обязателен, должен быть валидным.
2. Пароль: от 8 до 20 символов, минимум одна цифра и одна заглавная буква.
3. Возраст: от 18 до 65.
4. Кнопка «Зарегистрироваться» активна, только если поля заполнены.
5. После успешной регистрации пользователь получает письмо
и попадает в личный кабинет.
Первый рефлекс новичка — сразу открыть форму и начать кликать. Первый рефлекс инженера — задать вопросы. Тестирование начинается с требований, а не с приложения: если в требовании дыра, то и в ваших проверках будет ровно та же дыра, и баг спокойно доедет до продакшена — уже не как баг, а как «мы так и задумывали, наверное».
| Пункт | Что недосказано | Вопрос аналитику |
| 1. «Валидный email» | Валидный по какому правилу? Адреса вида ivan+shop@mail.ru, домены на кириллице, длина под 300 символов | Какие адреса считаем валидными? Регистр важен: Ivan@mail.ru и ivan@mail.ru — один пользователь или два? |
| 2. «От 8 до 20» | Границы включительно? Пробел — это символ? Что при вставке 25 символов: ошибка или обрезка? | 8 и 20 допустимы? Что делаем с пробелами в начале и конце? |
| 3. «Возраст 18–65» | 18 и 65 включительно? Пользователь вводит число или дату рождения (тогда возраст считает система)? | Границы включительно? Как ведём себя при вводе 17: блокируем кнопку или показываем ошибку? |
| 4. «Поля заполнены» | Чекбокс входит в «поля»? Кнопка активна при заполненных, но невалидных данных? | Согласие обязательно? Что показываем, если поля заполнены мусором? |
| 5. «Получает письмо» | Письмо уходит синхронно? Что если почтовый сервис недоступен? | Регистрация должна упасть, если письмо не ушло, или пройти и отправить письмо позже? |
| Нет вовсе | Повторная регистрация на существующий email; ограничение частоты попыток | Что показываем при регистрации на уже занятый email? |
Три вопроса, заданные до начала тестирования, экономят три дня переписки в баг-трекере. И, кстати, это ровно тот навык, который проверяют на собеседовании задачей «протестируй карандаш»: смотрят не на список проверок, а на то, спросите ли вы про контекст.
Шаг 1. Чек-лист: карта территории
Чек-лист отвечает на вопрос «что вообще будем проверять», без деталей. Он нужен, чтобы ничего не забыть и чтобы увидеть объём работы. Детали появятся на следующем шаге.
- Интерфейс: все поля на месте, подписи и плейсхолдеры без опечаток; вёрстка не разъезжается на 360px и при масштабе 200%; переход по Tab идёт сверху вниз; форму можно отправить с клавиатуры (Enter).
- Позитивный сценарий: валидные данные → аккаунт создан, письмо пришло, пользователь в личном кабинете, запись появилась в базе.
- Валидация полей: email, пароль, возраст, чекбокс — по классам эквивалентности и границам (шаг 2).
- Негатив и устойчивость: пустые поля, пробелы, спецсимволы, длинные строки, двойной клик, обрыв сети (шаг 3).
- Данные и интеграции: повторная регистрация того же email, письмо реально уходит, пароль не хранится и не передаётся в открытом виде, в ответе сервера нет лишних данных.
- Кросс-проверки: Chrome / Safari / мобильный браузер; автозаполнение и вставка из буфера; кнопка «Назад» после успешной регистрации.
Шесть строк — а работы уже на день. Это нормально: чек-лист честно показывает объём, и с ним можно идти к тимлиду обсуждать приоритеты.
Шаг 2. Классы эквивалентности и границы
Наивный перебор по трём полям даёт сотни комбинаций. Тест-дизайн сжимает их до осмысленного минимума: делим значения на классы, где система ведёт себя одинаково, берём по одному представителю от класса и отдельно щупаем границы — там живёт большинство багов.
| Поле | Класс | Представитель | Ожидаемое поведение |
| Возраст | Меньше минимума | 17 | Ошибка «Регистрация с 18 лет» |
| Возраст | Допустимый диапазон | 30 | Принять |
| Возраст | Больше максимума | 66 | Ошибка |
| Возраст | Не число / мусор | -5, 18.5, «тридцать» | Ошибка, форма не отправляется |
| Пароль | Короче 8 | Qwerty1 | Ошибка о длине |
| Пароль | Длина ок, но нет цифры | Qwertyuio | Ошибка о составе |
| Пароль | Длина ок, но нет заглавной | qwerty123 | Ошибка о составе |
| Пароль | Валидный | Qwerty123 | Принять |
| Валидный | ivan@mail.ru | Принять | |
| Нет собаки / нет домена | ivan.mail.ru, ivan@ | Ошибка | |
| Уже зарегистрирован | ivan@mail.ru (повторно) | Понятное сообщение, не 500-я ошибка |
Границы проверяются тремя точками: значение до границы, сама граница и значение сразу за ней. Одной точки мало — классическая ошибка разработчика if (len > 8) вместо if (len >= 8) ловится только так. Вот генератор таких точек для правила «пароль 8–20 символов» — можете нажать «Запустить» и посмотреть, какие ровно шесть проверок нужны на одно поле.
MIN_LEN, MAX_LEN = 8, 20
cases = [
("ниже границы", MIN_LEN - 1),
("нижняя граница", MIN_LEN),
("сразу после", MIN_LEN + 1),
("перед верхней", MAX_LEN - 1),
("верхняя граница", MAX_LEN),
("выше границы", MAX_LEN + 1),
]
for name, length in cases:
verdict = "принять" if MIN_LEN <= length <= MAX_LEN else "отклонить"
print(f"len={length:>2} — {name:<15} → ожидаем: {verdict}")
Результат:
len= 7 — ниже границы → ожидаем: отклонить
len= 8 — нижняя граница → ожидаем: принять
len= 9 — сразу после → ожидаем: принять
len=19 — перед верхней → ожидаем: принять
len=20 — верхняя граница → ожидаем: принять
len=21 — выше границы → ожидаем: отклонить
Шаг 3. Негативные сценарии: включаем «злого тестировщика»
Позитивный сценарий проверяет, что система работает, когда всё хорошо. Деньги компании теряются в другом месте — когда всё плохо. Здесь мы намеренно ведём себя не как примерный пользователь.
| Приём | Что вводим / делаем | Что на самом деле проверяем |
| Пустота и пробелы | Три пробела в поле email | Обрезаются ли пробелы (trim) или считаются заполнением |
| Длинная строка | Email на 1000 символов | Не рвётся ли вёрстка, нет ли ошибки 500 на сервере |
| Спецсимволы | ' OR 1=1 -- и <script>alert(1)</script> | Экранируются ли данные; не выполняется ли чужой код |
| Юникод | Эмодзи в пароле, кириллица в возрасте | Кодировка, подсчёт длины, адекватная ошибка вместо падения |
| Двойной клик | Быстро дважды жмём «Зарегистрироваться» | Не создастся ли два аккаунта и два письма |
| Обрыв сети | DevTools → Network → Offline в момент отправки | Понятная ошибка вместо вечного спиннера; можно ли повторить |
| Вставка из буфера | Копипастим пароль вместо набора | Работают ли валидация и ограничения при вставке (частый баг!) |
| Кнопка «Назад» | После регистрации возвращаемся браузером назад | Не отправится ли форма повторно |
Обратите внимание на строку про буфер обмена. Именно там мы сейчас и поймаем баг.
Шаг 4. Нашли баг — оформляем так, чтобы починили
Вставляем в поле пароля 25-символьную строку из менеджера паролей. Форма молча принимает её, показывает 20 символов-звёздочек, регистрация проходит успешно. А потом мы выходим и пытаемся войти с тем паролем, который вставляли, — и не можем. Смотрим в DevTools, вкладка Network, и видим в запросе к серверу уже обрезанное значение.
POST /api/v1/register → 201 Created
Запрос (Request payload):
{
"email": "ivan@mail.ru",
"password": "Qwerty1234567890Abcd", ← 20 символов вместо вставленных 25
"age": 30
}
Это не косметика: пользователь физически не может войти в свой аккаунт, и без обращения в поддержку он не поймёт почему. Оформляем.
Заголовок:
[Регистрация] Пароль длиннее 20 символов молча обрезается —
после регистрации вход с исходным паролем невозможен
Окружение:
Stage 2.14.0, Chrome 126, Windows 11, разрешение 1920x1080
Предусловие:
Пользователь не зарегистрирован, email ivan@mail.ru свободен
Шаги воспроизведения:
1. Открыть /register
2. Ввести email: ivan@mail.ru
3. Вставить из буфера пароль из 25 символов:
Qwerty1234567890AbcdEfghi
4. Указать возраст 30, отметить чекбокс согласия
5. Нажать «Зарегистрироваться»
6. Выйти из аккаунта и войти с паролем из шага 3
Фактический результат:
На шаге 3 поле принимает только первые 20 символов, ошибка не показана.
В запросе POST /api/v1/register уходит обрезанный пароль (см. вложение).
На шаге 6 вход не выполняется: «Неверный email или пароль».
Ожидаемый результат:
Либо форма показывает ошибку «Пароль не должен быть длиннее 20 символов»
и не отправляет данные, либо принимает пароль целиком (по ФТ-14 п.2 —
уточнено с аналитиком: показываем ошибку).
Severity: Critical — пользователь теряет доступ к созданному аккаунту
Priority: High — затрагивает всех, кто пользуется менеджером паролей
Вложения: скриншот формы, HAR-файл, скриншот вкладки Network
Дополнительно: на поле стоит атрибут maxlength=20 — обрезка происходит
на фронтенде, до отправки запроса.
Разберём, что делает этот репорт хорошим. В заголовке сразу видно, что сломано и чем это грозит — тимлид приоритизирует его, не открывая. Шаги воспроизведения точные, с конкретными данными: другой человек повторит их с первого раза. Фактический результат отделён от ожидаемого, и ожидаемый подкреплён ссылкой на требование — это защищает от спора «а так и должно быть». Severity Critical (техническая тяжесть: доступ потерян) и Priority High (бизнес-срочность) выставлены осознанно и по отдельности. А последняя строка про maxlength=20 — это уже подарок разработчику: вы не просто нашли симптом, вы показали, где искать причину.
Как это работает
Обратите внимание на форму всего процесса — это воронка, которая сужается на каждом шаге:
- Требования дают предмет разговора — и сразу порождают вопросы, а не тесты.
- Чек-лист отвечает на вопрос «ЧТО проверяем» и фиксирует объём.
- Техники тест-дизайна отвечают на «КАКИМИ значениями» и сжимают сотни комбинаций до пары десятков осмысленных.
- Прогон превращает кейсы в наблюдения — и обязательно с открытыми DevTools, иначе половина причин остаётся невидимой.
- Баг-репорт превращает наблюдение в задачу для разработчика.
Каждый следующий шаг опирается на предыдущий. Пропустите первый — и получите красивые тест-кейсы не на ту систему. Пропустите третий — утонете в бесконечном переборе. Пропустите последний — ваш баг просто не починят.
И ещё одно наблюдение, ради которого стоило проходить весь путь: баг мы нашли не в поле «возраст», где очевидные границы 18 и 65, а на стыке — при вставке из буфера. Так бывает почти всегда. Одиночные поля разработчик проверяет сам; ломается система там, где сходятся два механизма (валидация + буфер обмена, фронтенд + бэкенд, форма + повторная отправка). Именно поэтому негативные сценарии и стыки — самая доходная часть работы тестировщика.
Частые ошибки
- Начинать с кликов, а не с требований. Если требование дырявое, тесты унаследуют ту же дыру, и никто не заметит пропажу.
- Проверять границу одной точкой. Ввели 18 — работает, пошли дальше. Ошибка
>вместо>=при этом остаётся живой. - Тестировать «как пользователь», не открывая DevTools. Вы увидите симптом, но не поймёте, чья это вина — фронта или бэка, и репорт получится беспомощным.
- Верить интерфейсу. Надпись «Регистрация успешна» не означает, что запись появилась в базе, а письмо ушло. Проверяйте результат там, где он должен быть.
- Один баг на всё. Репорт «форма регистрации работает плохо» с пятью проблемами внутри невозможно ни приоритизировать, ни закрыть.
- Не фиксировать окружение и версию. Ответ «у меня не воспроизводится» стоит вам дня жизни.
- Останавливаться на позитивном сценарии. Он проверяет, что система умеет работать. Баги живут в том, чего вы ещё не пробовали.
Итоги
- Тестирование начинается с требований: сначала вопросы аналитику, потом проверки.
- Чек-лист отвечает на «что проверяем», тест-дизайн — на «какими значениями».
- Каждую границу щупаем тремя точками: до, на границе, сразу после.
- Негативные сценарии и стыки механизмов приносят больше багов, чем аккуратный позитивный путь.
- Хороший баг-репорт: говорящий заголовок, точные шаги, разделённые фактический и ожидаемый результат, окружение, осознанные severity и priority, подсказка о причине.
- Открытые DevTools во время прогона — разница между «что-то не работает» и «фронтенд обрезает пароль до отправки запроса».