(Эта статья первоначально появилась на TechBeacon.com) Перекладывание игральных карт колоды в свою пользу называется «подтасовать колоду». За пределами карточной игры этот термин используют в более широком смысле для обозначения решения ситуации таким образом, чтобы увеличить шансы на благоприятный исход. Когда речь идет об автоматизации тестирования, смысл не отличается. В частности, вы хотите выстроить архитектуру, имплементацию и шаблоны использования таким образом, чтобы они подходили для всего предполагаемого жизненного цикла вашего приложения. Один из подходов к обеспечению будущей работы — меньше сосредотачиваться на фреймворке автоматизации и больше на стеке автоматизации. Стек автоматизации — это многоуровневая архитектура автоматизации, в которой каждый уровень опирается на предыдущий и предоставляет соответствующий аудитории интерфейс к возможностям нижних уровней. Такой многоуровневый подход помогает продлить долгосрочную жизнь проекта, повышая его совместимость с различными платформами и инструментами. Далее представлены уровни, которые могут быть ценной частью реализации автоматизации, а также некоторые предостережения, которые следует учитывать перед созданием архитектуры. Создавая стек автоматизации, не забывайте, что вы занимаетесь программированием; вы создаете программное обеспечение и должны относиться к этой задаче как к разработке программного обеспечения. Это означает — вы должны следовать практике разработки и поставки программного обеспечения, соответствующей тому, что вы разрабатываете. Два мощных принципа разработки для создания стека автоматизации — это инкапсуляция и абстракция. Инкапсуляция — это практика сокрытия деталей реализации и данных программной конструкции. Такое сокрытие ценно тем, что позволяет разработчику изменять имплементацию, структуры данных или и то, и другое, не заставляя при этом пользователя вносить излишние изменения в код. Инкапсулированный код позволяет исправлять ошибки, повышать производительность и добавлять возможности по мере необходимости. Однако необходимо позаботиться о надлежащем сохранении существующего поведения инкапсуляции, чтобы имеющиеся пользователи этой инкапсуляции не пострадали и не нуждались в изменении действующего кода. В качестве примера инкапсуляции рассмотрим базовую структуру данных, называемую очередью. Предположим, что вы имплементируете очередь с помощью связанного списка, что является подходящей имплементацией очереди во многих случаях. Предположим, однако, что требования изменились, и вам нужно добавить в очередь функцию, позволяющую осуществлять поиск из ее конца. Связанные списки по умолчанию являются односвязными, это означает, что поиск из конца списка неэффективен, особенно если они очень длинные или для сравнения элементов списка требуется много времени. Структура данных, в которой поиск с конца является более эффективным, — это двусвязный список. Инкапсулированная имплементация означает, что переход на двусвязный список не окажет влияния на существующих пользователей имплементации очереди, и при этом позволит осуществлять более эффективный обратный поиск. Абстрагирование — это практика переноса определенных атрибутов структур данных в более общую структуру; она может затем использоваться при составлении специфических структур данных. Абстракцию лучше всего объяснить на классическом примере, связанном с животными. Собаки, нутрии и утконосы имеют несколько общих черт: у них есть некоторое количество ног, они могут слышать и видеть и т.д. Вы можете определить эти общие черты, эти атрибуты, в структуре данных, которая является общей для всех этих или других животных. Одним из возможных названий для этой абстракции может быть «животные, у которых есть ноги»; для краткости в программировании вы можете назвать эту структуру данных LeggedMammals или любым другим именем, которое будет соответствовать вашей области применения. Для определенных животных (собак, нутрий и утконосов) можно добавить свою специфическую имплементацию атрибутов или сохранить общую имплементацию, используя механизм, соответствующий вашим парадигмам проектирования и программирования. Абстрактная имплементация позволяет определить общие атрибуты в одном месте и обеспечивает более универсальный интерфейс при работе с произвольной LeggedMammal. [ Специальный выпуск: STPCon Fall Boston 2019 ]. Применение инкапсуляции и абстракции в имплементации автоматизации позволяет распределить компоненты автоматизации по уровням — дискретным разделам с четко определенными возможностями. Кроме того, вы можете построить эти уровни таким образом, чтобы каждый из них опирался на возможности предыдущего; таким образом вы создаете стек автоматизации. На рисунке ниже показана концептуальная модель этого стека. Каждый уровень имеет определенное назначение. Данный уровень не требует пояснений; он представляет фактические инструменты, которые вы используете для управления тестируемой системой (system under test, SUT). Примерами необработанных инструментов являются Selenium, Watir и REST Assured. Необработанные инструменты могут также представлять собой API, которые управляют аппаратным обеспечением сторонних производителей и встроенным оборудованием, которое может быть как вендорным, так и проприетарным. Этот уровень оборачивает необработанные инструменты; к уровню необработанных инструментов нет доступа ни у одного уровня, кроме абстракции и инкапсуляции. Этот уровень дополняет собственные возможности уровня необработанных инструментов и защищает его от изменений в имплементации, включая возможные изменения в используемом необработанном инструменте. Он также может защитить от изменений в исходных инструментах, которые могут негативно повлиять на более высокие уровни. Он предоставляет специфичные для конкретной области атомарные и почти атомарные действия, которые напрямую соответствуют операциям, необходимым для манипулирования тестируемой системой. Например, если вы автоматизируете взаимодействие с браузером, действием может быть «найти ссылку для входа и нажать на нее», что может привести к программному вызову типа: browser.LoginLink.Click(). Если вы автоматизируете конечную точку REST, действие может быть таким: «выполнить GET для получения номера телефона пользователя», что может привести к программному вызову, например: endpoint.GetPhoneNumber(UserData). Как правило, это сгруппированные последовательности действий и других видов поведения. Эти последовательности представляют собой шаги, которые пользователь тестируемой системы будет выполнять как часть этого пользовательского поведения. Примером может служить поведение при входе в систему. Оно может состоять из следующих шагов: Кликнуть на ссылку входа в систему Ввести имя пользователя Ввести пароль Нажать кнопку ввода и  Проверить успешный вход  В результате программный вызов может выглядеть следующим образом: Это тестовые скрипты, которые традиционно ассоциируются с автоматизацией тестирования. Они вызывают действия и модели поведения для автоматизации этих действий. Преимущества этого многоуровневого подхода те же самые, которые разработчики приложений получают от применения таких же основных принципов разработки программного обеспечения. Они предусматривают защиту от будущих изменений в  имплементации инкапсуляций, наличие одного или очень небольшого количества мест для модификации конкретного алгоритма или потока, а также повторное использование кода. Каждое из этих преимуществ помогает снизить стоимость сопровождения, на которое тратится основная часть усилий по внедрению автоматизации. Имплементация стека автоматизации также обеспечивает совместимость с различными фреймворками. Если вы не привязываете нижние части стека автоматизации к определенному фреймворку, то ваш стек можно использовать в нескольких фреймворках. Это дает пользователям фреймворка больше возможностей при выборе подходящей имплементации для автоматизации. Отсутствие привязки позволяет вам использовать свой стек и вне традиционной автоматизации на основе тестовых примеров. Стеки, которые мы используем в Magenic, построены именно таким образом. Поскольку ничто не идеально, есть одна большая оговорка. Создание программного обеспечения таким способом предварительно потребует от вас значительных затрат времени и усилий; в противном случае вы рискуете получить необслуживаемую массу кода. Если вам нужна быстрая победа или необходимо показать результаты "в ближайшее время", то следует попытаться сузить фокус вашего стека или использовать другой подход, по крайней мере, на начальном этапе. Важно отметить, что стековый подход не является подходом, ориентированным только на графический интерфейс (GUI-only); это распространенное заблуждение. Если вы просмотрите примеры, приведенные выше для каждого уровня концептуальной модели, то увидите примеры как с графическим интерфейсом, так и без него. Представленная здесь модель развивалась в течение последних 20 лет. Стековый подход использовался для автоматизации в телекоммуникациях, электронной коммерции, здравоохранении, финансовых технологиях и производстве; и в каждой из этих моделей доказал свою концептуальную состоятельность. При этом данная модель не претендует на то, чтобы быть предписывающей. Я призываю вас ее изучить, использовать там, где она уместна, и модифицировать, чтобы сделать более подходящей для ваших собственных целей. Материал подготовлен в рамках курса "JavaScript QA Engineer". Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь. Переводчик, редактор