
Масштабирование автотестов — закономерный этап развития любого растущего проекта. С увеличением количества автотестов меняются требования к архитектуре, инфраструктуре и процессам разработки. Репозиторий становится сложнее, возрастает время выполнения прогонов, увеличиваются затраты на поддержку и диагностику падений. На каждом этапе проекту требуются новые инструменты и подходы, которые позволяют сохранить скорость разработки и устойчивость всей системы автоматизации.
Меня зовут Михаил, в Ozon занимаюсь тестированием и автоматизацией финансовых сервисов маркетплейса. До этого за шесть лет мне довелось поработать в шести компаниях и получить опыт в проектах разного масштаба. Многие из них проходили нижеописанные этапы развития, хотя различались продуктами, командами и технологическим стеком. В этой статье я разделю этот путь на четыре условных уровня и покажу, какие метрики сигнализируют о необходимости роста, а также разберём этот процесс на всех уровнях: от архитектуры фреймворка до выстраивания процессов и TestOps.
Четыре уровня развития проекта
Границы между ними могут быть гибкими, поскольку масштаб проекта определяется не количеством автотестов, а архитектурой фреймворка, зрелостью процессов и степенью интеграции с инфраструктурой.
Начальный уровень — локальная автоматизация. Инициатива живёт внутри одной команды на основе личного видения AQA‑инженера. Отсутствует стандартизация стека, подходов. Базовые инфраструктурные интеграции.
Продвинутый уровень — стандартизация и кодогенерация. Разработка и использование общих инструментов переходят на уровень отдела или направления. Замещение рутины автоматизацией, отслеживание метрик.
Масштабный уровень — кросс‑командная унификация. Внедрение сложных инфраструктурных решений и единых конвенций. Децентрализация и повышение эффективности за счёт переиспользования и параллелизации.
Платформенный уровень — корпоративный стандарт. Отдельная команда по разработке внутренних инструментов в компании и повышение эффективности на каждом этапе создания автотестов.
Далее подробно разберём каждый уровень, характерные для него задачи и решения, которые помогают проекту перейти к следующему этапу развития.
Уровень «Начальный»: закладка фундамента
Если это ваш первый проект, а вы и есть команда, масштабы сервиса невелики, а основная мотивация для автоматизации — сократить время регресса или расширить инженерную экспертность, то вашим выбором будет «Начальный». На этом этапе закладывается фундамент будущего проекта. Архитектурные решения, принятые в самом начале, влияют на поддержку, развитие и масштабирование репозитория на протяжении всего его жизненного цикла.
Выбор технологий
Выбор языка программирования — одно из первых инженерных решений для автоматизации. Если специфика продукта жёстко диктует технологический стек, например мобильные, десктоп‑автоматизации, где есть безусловный лидер, берите его смело. Там, где ситуация не такая однозначная, я бы рекомендовал поискать информацию о самых популярных языках программирования в вашей области, а также тренды по годам и уже из итогового списка выбирать свой предпочтительный. Чем выше процент используемости, тем легче найти такого же специалиста для сопровождения, тем развитее будут инструменты для автоматизации и просто больше информации о решении каких‑либо нестандартных проблем. Эти правила минимизируют риск легаси‑коллапса и необходимости полного переписывания кодовой базы. После языка программирования следует выбор основополагающего фреймворка для самих тестов. Рекомендую руководствоваться теми же принципами, что и при выборе языка.
Первые архитектурные принципы
Чтобы поддержка кодовой базы не усложнялась со временем, следуйте простым правилам DRY (don’t repeat yourself), и KISS (keep it simple, stupid), в переводе на русский «не повторяйся и делай проще». Если что‑то используется больше чем один раз, с большой долей вероятности его нужно выносить на уровень выше и переиспользовать.
Помимо этих простых правил, при проектировании, следуйте правилу герметичности тестов. То есть каждый следующий тест не должен использовать данные, создаваемые прошлым. Иначе падение одного вызовет лавинообразное падение следующих, а также обяжет запускать его для запуска остальных.
Работа с тестовыми данными
Тест должен быть полностью изолирован от внешних факторов и следовать парадигме ААА (Arrange, Act, Assert) — самостоятельная подготовка уникального состояния, выполнение целевого действия, проверка результата. Немаловажно после выполнения тестов подчищать сгенерированные сущности и записи, чтобы:
сохранять независимость тестов, чтобы артефакты прошлого запуска не влияли на следующий или тестирование коллегами;
избегать случайных повторений в генерируемых данных;
не захламлять БД, снижая её производительность;
позволять легче отлаживать тесты.
Интеграция в процесс разработки
После успешного локального запуска базовых тестов следующим этапом развития становится полная интеграция с git и пайплайном разработки, чтобы ваши тесты не только запускались локально, но ещё и приносили пользу при каждом изменении в master/main. Для этого разработчикам необходимо перейти с разработки на локальных машинах на разработку с развёртыванием на стенде, предварительно его подготовив. Стенд — это изолированная среда, которая копирует реальную систему для взаимодействия с кодом. В классическом варианте их минимум два, тестовый (staging) и продакшен (prod), иногда разворачивают дополнительный для разработчиков (development) и препродакшен (preprod). Главное отличие staging от preprod заключается в назначении и чистоте тестовых данных. На staging могут параллельно проверяться несколько релизов или допускается временная поломка некоторых сервисов. На preprod условия должны быть максимально приближенными к реальным. Именно на этом стенде чаще всего происходит финальное регрессионное тестирование перед выпуском новой версии в продакшен.

При первых запусках в пайплайне вы можете столкнуться с неожиданными падениями тестов, которые не воспроизводятся локально. Скорее всего, вы столкнулись с гонкой состояний (Race conditions). Избегать её, устанавливая статические задержки, будет антипаттерном, ведущим к лишним задержкам в выполнении. Поэтому ожидания стоит закладывать неявные с экспоненциально увеличивающейся задержкой. Это гарантирует детерминированность выполнения вне зависимости от производительности или нагруженности тестируемого сервиса. Возможны и ситуации, когда локально ваши тесты прогонялись последовательно, а в пайплайне параллельно и падают из‑за использования общего блокирующего состояния системы. В этом случае стоит использовать инструмент группировки параллельных тестов, например как в Pytest @pytest.mark.xdist_group, что позволит гарантировать выполнение определённого набора тестов последовательно, чтобы они не мешали друг другу.
Уже на этом этапе стоит следить за временем выполнения тестов, их стабильностью и удобством сопровождения репозитория. Эти показатели станут первыми сигналами того, что проект начинает перерастать первоначальную архитектуру.
Код‑ревью
Что касается ревью кода коллегами: если таких нет, можно попросить разработчиков; желательно чтобы они знали используемый вами ЯП. Но всегда стоит делать оговорки про целеполагание автотестирования. Многократно сталкивался с тем, как разработчики требовали на ревью микрооптимизаций, нерелевантных для тестов, и избыточных архитектурных усложнений, инкапсуляций. Первое время стоит подсказывать, где оптимизации и упрощения имеют место, а где в этом нет необходимости. Если взаимопонимания достичь не удаётся, лучше остановиться на самостоятельной разработке, так как вред такого ревью превышает пользу.
Один из первых подобных проектов появился в компании со штатом 200–500 IT‑специалистов. На момент моего прихода контроль качества обеспечивал один ручной тестировщик. После покрытия основного функционала тесткейсами я принялся на добровольных началах их автоматизировать. Создал с нуля репозиторий, писал первые автотесты, приглашал своих коллег python‑разработчиков на ревью. Мы успешно встроили наши тесты в пайплайн, и, пока продукт активно развивался, благодаря интеграции с CI/CD было найдено множество багов уже на ранней стадии разработки. В рамках получения опыта удалось даже написать несколько UI‑автотестов и провести пару нагрузочных испытаний, но об этом подробнее в следующий раз.
Со временем появляются новые автоматизаторы, количество переиспользуемого кода растёт, а поддержка начинает занимать всё больше времени. Эти изменения становятся хорошим сигналом к пересмотру архитектуры фреймворка и переходу на следующий этап развития.
Уровень «Продвинутый»: архитектура, кодогенерация и TestOps
Планируете создать крупный фреймворк автотестирования, ориентированный на несколько команд или множество сервисов? Имеете об этом базовое представление и уже был опыт в автоматизации? Ваш выбор — «Продвинутый».

Понимание архитектурных слоёв
При проектировании такой системы с нуля необходимо базовое понимание слоёв в архитектуре фреймворка автотестирования:
Слой тестов. Содержит непосредственно тестовые сценарии и проверки (assertions).
Слой бизнес‑логики. Группировка нескольких отдельных действий (запросов) в логический блок. Например, когда нужно добавить товар в корзину, перед этим вы авторизуетесь, выбираете случайный товар, затем добавляете его в корзину. Инкапсуляция последовательности атомарных действий (API‑вызовов или UI‑взаимодействий) в переиспользуемые бизнес‑шаги.
Слой взаимодействия с приложением. Тут описывается структура вашего приложения для взаимодействия с ним. Уровень API, экранов (в случае с UI), взаимодействие с БД, брокерами сообщений и другими сущностями, с которыми нужно взаимодействовать в рамках наших автотестов.
Слой инфраструктуры и вспомогательных инструментов. Содержит взаимодействие с TMS, CI/CD, логированием и так далее
Эти слои должны быть разделены между собой.
Интеграция с Test Management System
Помимо выстраивания архитектуры, критически важна интеграция с инфраструктурой. Например, нужно настроить интеграцию с TMS.
TMS — Test Management System (система управления тестированием), в которой вы будете хранить свои автоматизированные тесткейсы, отслеживать динамику их запуска, детализацию по падениям и так далее. Это удобно не только вам, но и вашим коллегам, которые хотят самостоятельно диагностировать причину падений автотестов.
Уведомления и прозрачность
Далее, обязательная интеграция отправки результатов отчётов в систему, где вы общаетесь с коллегами по рабочим вопросам. Обычно это происходит так: обращаетесь с запросом к своему руководителю или девопсу за сервисной учётной записью и просите их реализовать это на уровне пайплайна или делаете это самостоятельно. Важно вовремя уведомлять о падении для оперативного реагирования. Позитивным опытом для себя отметил назначение конкретных ответственных за тот или иной сервис, которые будут подставляться в этот отчёт при падении их сервиса. Примерный формат отчёта:
Обнаружены проваленные автотесты - Сервис и версия: Send-api-SND-345 - Стенд: Stage - Версия автотестов: AUT-346 - Стадия автотестов: Component - Успешно: 300 - Неуспешно: 67 - Пропущено: 22 - Баги на исправлении: 52 - Исправленные баги: 7 - Всего: 448 - Время выполнения: 1 м 45 сек - Ответственный AQA: @petya.petrov - Ответственный разработчик: @vasya.vasin - Детальный отчёт (кликабельный текст, ведущий в TMS на этот конкретный отчёт) - Пайплайн (кликабельный текст со ссылкой, ведущий в CI/CD)
Представленный формат отчёта является рекомендуемым и необязательным. Вы можете реализовать его как вам удобно. Главное, передать как можно больше информации:
Что произошло?
Где произошло?
С каким сервисом, стендом?
Остальная информация добавляется для улучшения удобства, информативности и, как следствие, скорости решения проблем. На одном из проектов, например, ответственный разработчик подставлялся исходя из того, кто внёс последний коммит в разрабатываемую ветку, а не просто фиксированный. Предлагаемый мной формат улучшался эволюционно от проекта к проекту, пока не обрёл свой конечный вид, который обеспечивает высокую информативность. Он позволяет за несколько секунд локализовать проблему и определить ответственных. На успешные прогоны сообщения не отправлялись, так как они не требуют реагирования.
Избавление от рутины. Кодогенерация
Следующим очень рекомендуемым атрибутом будет кодогенерация API клиента. В случае с gRPC‑реализацией она существует из коробки. А вот с более распространённым REST API — нет. Из‑за этого автоматизаторам приходилось вручную обновлять модели при каждом изменении API. Это кратно увеличивало время на поддержку и требовало расширения штата. Безусловным лидером на момент написания статьи является openapi‑generator.
Openapi‑generator — opensourсe‑проект, поддерживающий генерацию клиентских SDK на основе спецификации (OpenAPI Specifications). Поддерживает более 50 языков программирования.
В нескольких компаниях встречал его реализацию и сам внедрял его как основной инструмент. Он невероятно гибок благодаря mustache‑шаблонам, которые позволяют вам кастомизировать генерацию под свои нужды. Главной сложностью будет повышение версий. В моменты его интеграции инструмент активно развивался и часто менялся, переворачивая прошлую реализацию. Из‑за этого переносить все свои кастомные фичи было невероятно сложно. А не повышать версию — лишь оттягивать неизбежное, но с более тяжёлыми последствиями.
Секреты держим в секрете
Немаловажной интеграцией будет скрытие токенов, логинов и паролей в системе хранения секретов, например в системе Vault.
Vault — это система управления секретами и доступом. Она обеспечивает безопасное хранение и выдачу различной конфиденциальной информации, такой как токены, логины, пароли, и контроль доступа к ней. Позволяет улучшить безопасность DevOps‑архитектуры.
Не тратим время на мелочи
Добавление линтера со стандартизацией подходов в написании кода — ещё одно обязательное условие успешного развития репозитория автотестирования на этом этапе.
Автоматизируем и упрощаем подготовку тестовых данных
Отдельного внимания заслуживает тема комплексных сценариев подготовки тестовых данных. Если у вас не выстроена система дампа базы или состояние системы может негативно влиять на другие проверки, то следует или силами разработки подготовить технические эндпойнты, или самостоятельно развернуть сервис, который будет гарантированно создавать и подчищать тестовые данные. Ещё одним из вариантов работы с тестовыми данными и БД является разворачивание небольшого экземпляра БД в CI/CD конкретно под текущий тестовый запуск с последующим удалением.
Нестабильных на карантин
Дополнительно требуется выстроить работу с нестабильными (flaky) тестами и не игнорировать их существование. Внедрение карантинов с последующим детальным разбором и исправлением не только сможет сохранить доверие к автотестам, но и значительно сократит время поддержки в будущем.
Мой опыт и подводные камни
Мне удалось застать этот этап в одной компании (500–800 сотрудников) и с нуля успешно построить в двух других с общим количеством ≈1000 сотрудников и ≈10 000 сотрудников, где моя зона ответственности была распространена не на всю компанию, а лишь на один из больших стримов, автотестированием которого я занимался. В первой компании, когда я пришёл, активно внедряли openapi‑generator, где нам приходилось адаптировать сгенерированный код к архитектуре репозитория и решать нестандартные проблемы при мажорных обновлениях инструмента. Основной потребностью были кастомные параметры, валидировать которые обязан был клиент. Например, по умолчанию в него не была встроена возможность работы с негативными тесткейсами. А именно клиент выбрасывал ошибку, если статус‑код ответа был не равен 2хх. Это было неудобно в использовании, и было решено доработать шаблон, добавив возможность передать свой ожидаемый статус‑код.
В другой компании основным вызовом стало масштабирование моих наработок на весь остальной проект. Так получилось, что все мы занимались одним большим процессом в бизнесе, который разделён на множество комплексных этапов, следующих друг за другом, представляющим из себя распределённый монолит без возможности мокирования ввиду глубокой связности процессов и сервисов. Моя команда была в середине этого большого пути, и необходимость проходить пять других команд в автотестах с постоянной поддержкой новой логики накладывала на меня большие расходы на поддержку. В связи с этим пришлось агитировать других коллег за объединение усилий и максимальное переиспользование компонентов. Отдельным «весельем» было убедить бизнес, что команда из четырёх автотестировщиков Java, четырёх на Python, одного на PHP может собраться воедино и консолидировать усилия. Хорошо, что многие java‑тестировщики знали Python и готовы были познавать новое. В силу отсутствия значительного прогресса автотестов других команд отказаться от прошлого решения и перейти на мою платформу, предполагающую лёгкое как горизонтальное, так и вертикальное масштабирование, было несложно. Успешным примером автоматизации подготовки данных стала моя инициативная интеграция фреймворка Flet с привязкой UI‑кнопок к реальным действиям, использующим тестовый репозиторий, о чём я рассказывал на Python Meetup в 2024 году. Выбор в пользу UI‑инструмента был продиктован высоким отношением числа ручных тестировщиков к числу автоматизаторов. И нужно было просто и быстро предоставить большому количеству коллег доступ к быстрой генерации тестовых данных без сложного локального запуска автотестов в IDE.
Когда и как переходить
В случае если вы переходите на этот уровень, вам в первую очередь нужно провести ревизию своих текущих наработок: соответствуют ли они вышеописанной тестовой архитектуре? Если нет, начать с этого. Затем внедрить интеграцию в CI/CD и TMS с отчётами в корпоративный мессенджер. Затем задуматься о переходе на кодогенерацию. Хорошим сигналом о необходимости перехода на новый этап будет чрезмерно сложная или долгая поддержка текущих автотестов, диагностика падений. Все эти улучшения помогут вам перейти на следующую ступень возможностей.
Уровень «Масштабный»: оркестрация и Test Impact Analysis
Если монорепозиторий становится перегруженным, часто встречаете мердж‑конфликты? Тесты выполняются долго, а каждый билд занимает много времени из‑за обилия зависимостей и веса репозитория? Вам пора переходить на «Масштабный» уровень.
Децентрализация. Унификация
Если вышеописанная проблема про вас, то вам требуется децентрализация репозитория, унификация используемых вспомогательных инструментов и переиспользование их на уровне выше. Чтобы большому количеству репозиториев и коллег можно было двигаться в общем русле, рекомендуется создать общую документацию относительно подходов в автоматизации, а также инструментов. Иногда её называют «конвенция о тестировании».
Оркестрация
Увеличить скорость доставки и уменьшить зависимость от фиксированных стендов нам поможет Kubernetes.
Kubernetes — это портативная расширяемая платформа с открытым исходным кодом для управления контейнеризованными рабочими нагрузками и сервисами, которая облегчает как декларативную настройку, так и автоматизацию. Успех этого этапа зависит от синхронизации с командой разработки и DevOps.
Техдолг — ваш злейший враг
Жизненно необходимо договориться с бизнесом об окне для проведения полноценного рефакторинга: наведения порядка в кодовой базе, а также обновления версии ЯП и используемых библиотек. Это то, что чаще всего игнорируется в угоду результату «здесь и сейчас», что неизбежно приведёт к накоплению технического долга. Практика показывает, что отсутствие обновлений приводит к потере мотивации инженеров и невозможности использования современных инструментов. Неоднократно слышал от ребят, которые приходили на собеседование, что они выгорали на проекте с автотестами с версией Python 2.x, когда никакие новые библиотеки не поддерживаются, а все старые уже никто не знает как работают. Или, что ещё хуже, когда есть группы автотестов, которые выполняются по несколько дней.
Сокращение проверок и параллелизация
Стоит уделить внимание возможности параллельного запуска группы автотестов в рамках одного сервиса, если это допустимо. В случае большого количества end‑to‑end‑тестов и частых релизов, из‑за которых создаётся очередь в CI/CD, рассмотрите внедрение TIA (test impact analysis) на основе графов зависимостей, которое позволит уменьшить количество запускаемых автотестов от 10 до 90% в зависимости от конкретного коммита.
Мой опыт
На этом этапе расскажу про свой последний опыт работы вне Ozon, это компания с масштабом ≈1000 сотрудников. Из вышеперечисленного списка удалось «пощупать» переход на Kubernetes и создать конвенцию для нагрузочного тестирования. Большого опыта в переходе на кубы ни у меня, ни у коллеги DevOps не было, поэтому пришлось провести ряд встреч, с тем чтобы разобраться, как теперь будет работать сервис, какой хост передаваться, как работать с базой данных и как её наполнять, как происходит взаимодействие с другими сервисами. После нескольких встреч реализовали роадмап, и буквально за неделю‑две коллега успешно перевёл сервис на Kubernetes, я адаптировал автотесты и их логику под новую чистую базу данных с выполненными миграциями и успешно отладили пайплайн, представив готовый рабочий результат. Далеко не каждая компания и команда готова потратить значительные ресурсы на переход на Kubernetes, поэтому нужно осторожно подходить к аргументации о необходимости расширения как неизбежного процесса и планировать переход заблаговременно. Это довольно длительный процесс, и он зависит от объёма переводимых сервисов и свободных ресурсов.
Когда и как переходить
Если вы чувствуете влияние монорепозитория, которое выражается в значительном увеличении времени поддержки, то это сигнализирует о необходимости планирования децентрализации. Параллельно с этим обсудите перспективы перехода на Kubernetes в вашей компании и аргументируйте свою позицию. Борьба с техдолгом и параллелизация — довольно недорогие и эффективные инструменты. А вот TIA будет более затратным процессом с большой дистанцией окупаемости вложений, к нему бы я переходил, когда все прочие методы уже исчерпаны.
Уровень «Платформенный»: формирование выделенной команды
Когда ваша команда начинает выделять целых отдельных специалистов на обслуживание, доработку, обновление и разработку новых вспомогательных инструментов, тут однозначно вам пора переходить на последний «Платформенный» уровень.
Платформенная команда
Следуя названию, вам требуется создание команды платформы. Это отдельная команда, занимающаяся исключительно внутренними инструментами, которые используют другие команды. Единая аутентификация, генерация клиентов для запросов, CI/CD пайплайн, балансировщики, mesh‑версии сервисов, подключения к БД, брокерам сообщений, vault, телеметрия по уникальному trace‑id. Команда платформы берёт на себя поддержку инфраструктурного бойлерплейта. Это высвобождает ресурсы AQA для фокуса на бизнес‑логике, избавляя от необходимости поддерживать низкоуровневые клиенты и коннекты.
Реализацию этого этапа можно увидеть в Ozon в виде фреймворка для автотестирования Nuke (Python) или Testo (Go).
С чего начать?
Если у вас исчерпаны все или почти все инструменты для повышения эффективности, то выделенная команда поможет облегчить работу. Начните с самого популярного и изнуряющего — генерации клиентов для запросов, затем аутентификация и работа с сертификатами. Далее работа с БД, брокерами. Внедрите телеметрию. Потенциал выноса и объединения подходов очень высок и окупается только на длинных дистанциях.
Дальнейшие перспективы
Кажется, мне удалось последовательно рассказать вам обо всех известных этапах эволюции, которые прошли проверку временем и доказали свою эффективность. Но прогресс не стоит на месте, и уже сейчас есть заделы на ещё большее увеличение эффективности с помощью AI. Думаю, уже скоро подходы стандартизируются и пройдут боевые испытания в реальных компаниях, чтобы сделать нашу работу ещё менее рутинной.
Заключение
Помните, что на длинной дистанции итог — придёт ваш репозиторий автотестирования к упадку и бесконечной поддержке или к результативному масштабированию — зависит не только от хорошего кода, команды, но и от грамотного понимания роадмапа развития проекта и навыков аргументации при защите инфраструктурных инвестиций перед бизнесом. Успехов!