Функциональное и нефункциональное
Продукт можно провалить двумя способами: он делает не то, что нужно, — или делает ровно то, что нужно, но так, что пользоваться этим невозможно.
Функциональное тестирование отвечает на вопрос «что система делает». Нефункциональное — на вопрос «как она это делает».
Представьте банковское приложение. Перевод уходит на правильный счёт, сумма списывается копейка в копейку, история операций сходится. С функциональной точки зрения — идеально. А теперь детали: перевод подтверждается 40 секунд, кнопка «Подтвердить» на маленьком экране уезжает под кромку, сессия не истекает никогда, а в логах лежит номер карты целиком. Ни один функциональный тест этого не заметит: результат-то верный.
Вот ради этой слепой зоны деление и придумали. Функциональные проверки смотрят на результат, нефункциональные — на условия, в которых этот результат получается: скорость, нагрузка, устройство пользователя, злоумышленник по ту сторону формы.
Функциональное: проверяем результат
Источник проверок здесь — требования: техническое задание, user story с критериями приёмки, макеты, API-контракт. Плюс здравый смысл, потому что половина реальных требований нигде не записана.
Возьмём форму перевода денег: поле «сумма», поле «получатель», кнопка. Функциональные проверки распадаются на три группы.
| Группа | Что проверяем | Пример |
| Позитивные | система делает то, что должна, на корректных данных | перевод 500 ₽ на существующий счёт проходит, баланс уменьшился на 500 |
| Негативные | система корректно отказывает на некорректных данных | перевод 500 ₽ при балансе 100 ₽ отклонён, деньги не списаны, показана внятная ошибка |
| Граничные | поведение на краях диапазона | сумма 0, сумма 0.01, сумма ровно равная балансу, сумма на 1 копейку больше лимита |
Оформляется это обычным тест-кейсом — шаги, данные, ожидаемый результат:
ID: TR-014
Название: Перевод суммы, превышающей баланс
Предусловие: пользователь авторизован, баланс = 100.00 RUB
Шаги:
1. Открыть «Переводы» → «По номеру счёта»
2. Ввести счёт 40817810099910004312
3. Ввести сумму 500.00
4. Нажать «Перевести»
Ожидаемый результат:
- перевод отклонён;
- показано сообщение «Недостаточно средств. Доступно 100,00 ₽»;
- баланс остался 100.00 RUB;
- операция НЕ появилась в истории.
Заметьте: ожидаемый результат — это не только «показалась ошибка». Проверяется ещё и то, что не произошло побочных эффектов. Половина боевых багов живёт именно там: сообщение об ошибке пользователь видит, а деньги всё равно списались.
Нефункциональное: четыре главных семейства
Нефункциональных видов насчитывают десятки, но на реальном проекте новичок почти всегда сталкивается с четырьмя.
Производительность
Вопрос: сколько ждёт пользователь и сколько выдерживает система. Внутри — несколько разных проверок, которые часто путают:
- Нагрузочное — держим ожидаемую нагрузку (200 одновременных пользователей) и смотрим время ответа.
- Стрессовое — давим сверх ожидаемого, пока не сломается, и смотрим как сломается: аккуратно вернёт 503 или ляжет с потерей данных.
- Стабильности (soak) — держим среднюю нагрузку 8–12 часов и ловим утечки памяти: система работает, но к вечеру отвечает вдвое медленнее.
- Объёмное — не пользователей много, а данных: список из 200 000 записей, файл на 2 ГБ.
Ключевая величина — не «среднее время ответа», а перцентиль. Среднее в 300 мс прекрасно уживается с тем, что каждый двадцатый запрос идёт 9 секунд. Поэтому требования пишут так: p95 < 800 мс при 200 RPS. Инструменты: JMeter, k6, Locust.
Безопасность
Полноценный пентест делают специалисты, но базовый слой проверок — работа обычного QA. Минимум, который проходится руками и браузерным DevTools:
- Подставить в URL чужой идентификатор:
/orders/1043вместо своего/orders/1042. Если чужой заказ открылся — это IDOR, одна из самых частых дыр. - Скормить в поле поиска
' OR 1=1 --и посмотреть, не изменилась ли выдача (SQL-инъекция). - Вставить в комментарий текст с HTML-тегом скрипта и проверить, экранируется ли он (XSS).
- Ввести неверный пароль 20 раз подряд: есть ли блокировка или капча.
- Разлогиниться и повторить старый запрос со старым токеном — токен должен умереть.
- Посмотреть, что уходит в логи и в аналитику: пароли и номера карт там появляться не должны.
Ориентир на список OWASP Top 10 — это открытый перечень самых распространённых веб-уязвимостей, его удобно использовать как чек-лист.
Юзабилити
Здесь важно сразу отделить «мне не нравится цвет» от настоящей проблемы удобства. Юзабилити-баг формулируется через цель пользователя и препятствие на пути к ней:
- Сколько шагов до цели: оформление заказа занимает 9 экранов, из них 3 — необязательные.
- Понятность ошибки:
Error 500: transaction_failedвместо «Банк отклонил платёж. Попробуйте другую карту». - Обратная связь: пользователь жмёт «Оплатить», ничего не происходит 5 секунд, он жмёт ещё раз — и оплачивает дважды.
- Соответствие ожиданиям: кнопка «Назад» в браузере уносит из середины оформления заказа на главную и стирает корзину.
Настоящее юзабилити-исследование — это наблюдение за живыми людьми. Классическая практика: посадить пять человек, дать задачу «купите билет в Казань на завтра», молчать и записывать, где они запнулись. Пятерых обычно хватает, чтобы найти большинство грубых проблем.
Совместимость
Одно и то же приложение по-разному ведёт себя в Safari на iPhone и в Chrome на Windows. Проверять «все устройства мира» невозможно, поэтому строят матрицу приоритетов, опираясь на аналитику реального трафика:
| Конфигурация | Доля трафика | Глубина проверки |
| Chrome, Windows, 1920×1080 | 46% | полный регресс |
| Safari, iOS, 390×844 | 27% | полный регресс |
| Chrome, Android, 412×915 | 18% | полный регресс |
| Firefox, Windows | 5% | smoke: вход, поиск, оплата |
| Остальное | 4% | чиним по жалобам |
Совместимость — это не только браузеры. Ещё версии ОС, версии внешнего API, версия базы данных после апгрейда, старые версии мобильного приложения, которые пользователи не обновили и которые продолжают ходить в ваш новый бэкенд.
Как это работает
Нефункциональные требования (их называют NFR, non-functional requirements) живут в тех же документах, что и обычные: в ТЗ, в критериях приёмки, в SLA — соглашении об уровне обслуживания, где записано, что и с какой скоростью система обязана делать.
Проблема в том, что их почти всегда не пишут. Аналитик подробно опишет форму перевода и ни слова не скажет о том, за сколько она должна открываться. Тогда цифру вытягивает тестировщик — иначе проверять нечего: «медленно» нельзя ни подтвердить, ни опровергнуть.
Хорошее нефункциональное требование содержит четыре части: субъект, условие, метрику и порог.
Плохо: «Система должна работать быстро и надёжно.»
Хорошо: «При 200 одновременных пользователях 95% запросов к /api/search
возвращают ответ быстрее 800 мс; доля ошибок 5xx — не выше 0,1%.
Замер: k6, 15 минут, окружение stage с продовым объёмом данных.»
Ритм у этих проверок тоже разный. Функциональные тесты гоняют на каждый релиз. Нагрузочные — перед распродажей и после серьёзных изменений в базе. Аудит безопасности — по расписанию, раз в квартал или полгода. Юзабилити-исследование — на этапе прототипа, пока переделывать дёшево.
Частые ошибки
- Ждать, что NFR принесут на блюде. Не принесут. Если в требованиях нет цифр — идите к аналитику и продакту и добывайте их до старта тестирования, а не после жалоб с прода.
- Мерить производительность на своём ноутбуке. Через домашний Wi-Fi, на базе из 50 записей, с открытым Docker и десятком вкладок. Такие цифры не значат ничего: нужен стенд, похожий на боевой, и продовый объём данных.
- Смотреть на среднее время ответа. Оно прячет самые больные хвосты. Всегда p95 и p99.
- Заводить юзабилити-баг как «неудобно». Такой тикет закроют. Пишите: цель пользователя, где он застрял, сколько людей застряло, чем это грозит бизнесу.
- Считать безопасность чужой зоной. Подмена id в URL и отсутствие лимита на попытки входа проверяются за пять минут и находятся куда чаще, чем кажется.
- Тестировать совместимость «везде». Без матрицы приоритетов вы потратите неделю на браузер, которым пользуется 0,3% аудитории, и не откроете сайт на iPhone.
- Гонять нагрузочный тест по проду. Если очень надо — только по согласованию, в ночное окно и с планом отката. Иначе тест сам станет инцидентом.
Итоги
- Функциональное тестирование проверяет что система делает, нефункциональное — как: скорость, устойчивость, защищённость, удобство, поведение на разном железе.
- В функциональной проверке ожидаемый результат включает и побочные эффекты, которых быть не должно.
- Четыре семейства, которые встретятся первыми: производительность, безопасность, юзабилити, совместимость.
- Требование без метрики и порога непроверяемо. «Быстро» — не требование, «p95 меньше 800 мс при 200 RPS» — требование.
- Производительность меряют перцентилями, безопасность начинают с OWASP Top 10, юзабилити — с наблюдения за живыми людьми, совместимость — с матрицы по реальному трафику.