Всем привет, меня зовут Сергей Прощаев, и в этой статье я расскажу про виды тестирования и лучшие практики, которые реально работают в полевых условиях.
За годы работы в IT я пересмотрел сотни планов тестирования, десятки раз участвовал в разрешении конфликтов между «тестированием по инструкции» и «тестированием по здравому смыслу». И знаете, что меня всегда удивляло? Теоретически все знают про статическое и динамическое тестирование, про уровни и методы. Но на практике 80% команд начинают тестировать только тогда, когда код уже написан. А баги, которые можно было бы поймать на уровне требований или документации, уходят в прод и выливаются в ночные деплои и горящие глаза заказчика.
Мы разберем, как на самом деле выстроить процесс тестирования, чтобы он не был тормозом, а становился двигателем качества. Я покажу вам не картинку из учебника, а реальный рабочий подход: где найти дефекты до того, как они превратятся в проблему, как не запутаться в уровнях тестирования и почему иногда лучшее тестирование — это то, которого вы не заметили.
Статическое и динамическое: две стороны одной медали
Самый большой прорыв в осознании качества для меня случился, когда я перестал воспринимать тестирование как «запустил тесты и посмотрел, что падает». Оказывается, половину дефектов можно и нужно находить до того, как вы вообще выполните код.
Статическое тестирование — это то, что мы проводим без запуска программы. Это как проверка чертежа до того, как начать строить дом. Требования, проектная документация, исходный код — всё это можно и нужно анализировать. И здесь кроется главная суперсила: чем раньше мы находим проблему, тем дешевле ее исправить. Исправить ошибку в требовании стоит копейки. Исправить ту же ошибку, но уже в продовой версии — может стоить миллионов.
Например, во время статического ревью требований команда может обнаружить противоречие: в спецификации указано, что пароль должен содержать спецсимволы, а в user story это требование отсутствует. Проблема усугубляется тем, что разработчики уже приступают к реализации интерфейса без учёта этого условия. Если бы ошибку не выявили на этапе ревью, впоследствии пришлось бы переделывать и фронтенд, и бэкенд, а также обновлять автотесты. Благодаря своевременному обнаружению проблема решилась быстро — всего за пять минут, простой правкой строки в документе.
Статическое тестирование бывает разным, и его виды удобно представить в виде схемы, изображенной на рисунке 1.

Неформальное ревью — когда коллега глянул твои тест-кейсы или тимлид пробежался по результатам. Просто, быстро, но эффективность зависит от того, насколько рецензент в теме.
Пошаговый разбор — мы часто используем для черновиков. Например, когда команда обсуждает новый подход к дизайну, это помогает всем понять логику и накидать улучшения.
Техническое ревью — уже посерьезнее. Четкий процесс, фиксация ошибок, назначение координатора. Ревьюеры должны быть технически подкованы в своей области.
Инспекция — самый формальный вид. Это метод Фэгана, который еще в 70-х в IBM показал, как сильно можно улучшить качество. Здесь важны модератор, четкие критерии входа и выхода, сбор метрик. Инспекция не просто находит баги, она помогает оптимизировать процессы.
Динамическое тестирование — это то, к чему мы привыкли. Запустили код, проверили, как работает. Но важно понимать: оно не заменяет статику. Динамика проверяет корректность функционирования, а статика ищет проблемы на более глубоком уровне. Они не конкуренты, а партнеры.
Уровни тестирования: от компонента до прода
Многие новички считают, что тестирование — это просто «нажать кнопку и посмотреть». Но чем больше проектов проходило через мои руки, тем яснее становилось: тестирование должно быть многоуровневым. Каждый уровень отвечает на свои вопросы и требует своей среды.
Уровни динамического тестирования можно представить как пирамиду или последовательность, где каждый следующий уровень базируется на предыдущем (см. рис.2):

Компонентное тестирование (или модульное)
Это тестирование отдельного модуля в изоляции. Разработчик написал компонент Login и проверяет его отдельно от Usage и Logout. Здесь мы смотрим и на функциональные вещи (правильность расчетов), и на нефункциональные (нет ли утечек памяти), и даже на структуру кода.
Главная цель — убедиться, что код компонента соответствует спецификации, до того как мы начнем его интегрировать с другими. Обычно это зона ответственности разработчика, и баги фиксятся тут же, в процессе написания.
Тестирование интеграции компонентов
А вот тут начинается самое интересное. Отдельные модули мы протестировали, а теперь нужно соединить их и проверить, как они общаются. Цель — выявить ошибки взаимодействия.
И здесь есть три стратегии, и выбор одной из них может сэкономить или, наоборот, сжечь кучу времени:
«Большой взрыв» — все модули пилятся отдельно, а потом в один момент соединяются в готовую систему. Звучит просто, но на практике это часто приводит к аду. Потому что когда всё падает одновременно, понять, кто виноват, крайне сложно.
Сверху вниз — начинаем с верхних компонентов (которые вызывают другие). Если нижний компонент еще не готов, мы используем заглушку (stub) — пассивную имитацию, которая возвращает заранее известные ответы. Например, для тестирования Login нам достаточно, чтобы заглушка Usage отвечала «успешно» или «ошибка». Этого достаточно, чтобы проверить логику входа.
Снизу вверх — полная противоположность. Начинаем с нижних компонентов, а для еще не готовых верхних используем драйвер (driver) — активный компонент, который вызывает тестируемый модуль. Драйверы сложнее заглушек, но они позволяют глубже проверить логику нижних уровней.
По моему мнению самый стабильный подход — инкрементальная интеграция. Мы не ждем, пока всё будет готово, а интегрируем и тестируем постепенно, снижая риски и упрощая локализацию дефектов.
Системное тестирование
После того как компоненты собраны, мы переходим к системному тестированию. Здесь мы проверяем поведение системы в целом. Тесты строятся на основе бизнес-требований, которые обычно формулируют бизнес-аналитики. Мы смотрим сквозные сценарии, функциональные и нефункциональные требования. Системное тестирование обычно проводят тестировщики в выделенной тестовой среде.
Цель — валидация поведения системы как единого целого. Именно на этом уровне мы отвечаем на вопрос: «Делает ли система то, что нужно бизнесу?»
Системное интеграционное тестирование (SIT)
Если системное тестирование проверяет одну систему, то SIT оценивает взаимодействие междуразными системами. Наше приложение E-SYSTEM передает данные в систему Billing для выставления счетов. Проверка того, что эти данные ушли правильно и Billing их корректно обработал — это и есть SIT.
И здесь нас часто ждет сюрприз: внешняя система может быть не готова к тестированию. Тогда мы используем симуляторы (simulators) — специальные программы, которые имитируют поведение внешних систем. Симулятор дает нам контроль над входными данными и позволяет предсказуемо проверить реакцию нашей системы.
Приемочное тестирование (UAT)
Финальный аккорд. Цель UAT — проверить, пригодна ли система для использования реальными пользователями. Тестирование проводят заказчик или его представители (бизнес-команда) в среде, максимально похожей на продакшен. Тест-кейсы пишутся на основе исходных требований заказчика, а не технических спецификаций.
Был свидетелем проектов, где UAT превращалось в «шоу ужасов», потому что никто заранее не позаботился о том, чтобы тестовая среда UAT была изолирована и стабильна. Помните: UAT-среда должна быть отдельной от среды системного тестирования, иначе вы никогда не поймете, чей баг вы ловите — свой или чужой.
Функциональное и нефункциональное: что важнее?
Функциональное тестирование — это проверка того, что система делает. Поиск рейса на сайте авиакомпании, проверка баланса в банкомате — это функции. Они специфичны для каждой системы и описываются в требованиях.
Нефункциональное тестирование — это проверка того, как хорошо система это делает. Здесь вопросы становятся универсальными:
Сколько пользователей система может обслуживать одновременно?
Как быстро загружается страница?
Сколько транзакций можно провести за определенный промежуток времени?
Как долго хранятся данные локально?
Нефункциональные требования часто недооценивают. Так в одном проекте команда сделала отличный функционал, но на нагрузочном тестировании выяснилось, что система падает при 50 одновременных пользователях. А по бизнесу нужно было 500. Пришлось переписывать архитектуру. Поэтому всегда вовремя следует задавать вопрос: «А какая у нас производительность? А как мы будем масштабироваться?»
Методы тестирования: черный, белый, серый и… опыт
Классическое деление на «черный ящик» и «белый ящик» все еще работает.
Черный ящик — мы проверяем входы и выходы, не глядя на внутреннюю структуру. Что получили на входе, то и проверили на выходе. Условия тестирования формируются на основе требований, спецификаций, вариантов использования. Это удел тестировщиков.
Белый ящик — мы смотрим на структуру: код, архитектуру, детали проекта. Это зона ответственности разработчиков. Здесь мы проверяем, например, что все ветки кода покрыты тестами.
Но есть еще один метод, который все чаще применяю в реальной работе — тестирование на основе опыта.
Оно использует знания разработчиков, тестировщиков и пользователей. Когда нет четкого базиса для тестирования (или он неполный), опытные специалисты могут предсказать, где скорее всего будут дефекты. Они знают типичные ошибки, знают, где разработчики чаще всего косячат. Например, тестировщик, опираясь на опыт, может проверить, разрешен ли ввод спецсимволов в поле «Имя», даже если в требованиях это не прописано.
Как можно что-то долго делать что потом будет никому не нужно?
В сети полно историй про то как команда разрабатывает какой-нибудь внутренний портал для сотрудников. В ТЗ при этом написано: «Админка для управления пользователями». Команда с энтузиазмом берется за дело: проектируют красивый интерфейс с 20 полями для фильтрации, настройками ролей, детальным просмотром логов. Тратят на это месяц.
Потом выясняется, что IT-отдел, который будет этой админкой пользоваться, на 90% использует только одну функцию — разблокировку аккаунта по звонку. Всё остальное им просто не нужно. В итоге команда сделала мощный инструмент, который оказался мертвым грузом.
Знакомо?
Читая подобные истории начинаешь понимать, что перед тем, как что-то проектировать, всегда неплохо бы задать пару (или чуть больше) вопросов:
Кто реально будет этим пользоваться?
Какие именно операции им нужны?
Как часто они это делают?
Иногда лучшее решение — не создавать сложную админку, а дать техподдержке простую кнопку и понятный лог. Это экономит месяцы разработки.
Лучшие практики, которые работают
На основе всего вышесказанного выделил для себя несколько практик, которые реально повышают качество:
Тестирование начинается на этапе анализа требований. Не ждите кода. Участвуйте в ревью документации, задавайте неудобные вопросы. Ошибка в требовании, исправленная на этапе анализа, стоит в сотни раз дешевле, чем исправление в проде.
Используйте инкрементальную интеграцию. Интегрируйте и тестируйте постепенно, а не «большим взрывом». Это снижает риски и упрощает локализацию дефектов.
Разделяйте среды тестирования. ST, SIT, UAT — это разные среды. Перемешивать их — значит гарантированно получить путаницу и ложные срабатывания.
Не забывайте про нефункциональные требования. Нагрузка, безопасность, доступность — это не «опционально», это критично для успеха продукта.
Используйте опыт команды. Иногда лучший тест-кейс не вытекает из документа, а рождается в голове опытного тестировщика, который знает, где обычно закрадываются ошибки.
Документируйте, но не переусердствуйте. Документ ради документа — мертвый документ. Создавайте живые, атомарные артефакты, которые легко актуализировать.
Вместо заключения
Тестирование — это не скучная обязанность «в конце конвейера». Это система мышления, которая пронизывает весь процесс разработки. Статика и динамика, разные уровни и методы — всё это инструменты, которые помогают нам строить качественные продукты.
Хороший тестировщик — это не тот, кто находит больше багов. Это тот, кто помогает команде создавать продукт, в котором багов изначально мало. Он задает вопросы на этапе требований, продумывает интеграции, проверяет не только функции, но и производительность, и безопасность.

Когда ручных проверок уже не хватает, а качество начинает упираться в повторяемость и глубину сценариев, приходится переходить от «проверить руками» к системной автоматизации. Курс «Инженер по автоматизации тестирования» как раз про этот переход: автотесты на Java, проверка интерфейса и API, работа с Selenium, JUnit и шаблонами, которые помогают выстроить внятный и поддерживаемый контур тестирования. Это хороший способ дойти от отдельных проверок до роли специалиста, который влияет на качество продукта уже на уровне процесса, а не только отдельных багов.
Если хотите понять формат обучения — записывайтесь на бесплатные уроки от преподавателей курсов:
14 апреля в 19:00. «Внедрение автотестирования с участием искусственного интеллекта». Записаться
16 апреля в 20:00. «ИИ для тестировщика: инструменты, которые уже меняют профессию». Записаться
28 апреля в 20:00. «Первый нагрузочный тест в Apache JMeter». Записаться
