Автоматизация тестирования на JavaScript

Этот курс предназначен для изучения основ и продвинутых техник автоматизации тестирования с использованием языка JavaScript. Вы освоите работу с популярными фреймворками, научитесь писать UI и API тесты, а также внедрять их в процессы непрерывной интеграции.

1. Основы JavaScript для QA: синтаксис, функции и асинхронное программирование

Основы JavaScript для QA: синтаксис, функции и асинхронное программирование

Добро пожаловать в курс «Автоматизация тестирования на JavaScript». Это первая статья нашего цикла, и мы начнем с фундамента. Почему именно JavaScript? Ответ прост: это язык веба. Если вы тестируете веб-приложения, знание JS позволяет вам не только писать автотесты, но и понимать, как работает приложение «под капотом».

Современные инструменты автоматизации, такие как Cypress, Playwright и Puppeteer, используют JavaScript (или TypeScript) как основной язык. Поэтому, прежде чем мы начнем кликать по кнопкам браузера с помощью кода, нам нужно научиться говорить на этом языке.

Переменные и типы данных

Любая программа начинается с хранения данных. В JavaScript для этого используются переменные. Представьте переменную как коробку, на которую вы наклеили этикетку с именем. В эту коробку можно положить значение.

Объявление переменных

В современном JavaScript (стандарт ES6 и новее) мы используем два ключевых слова для создания переменных:

  • let — для переменных, значение которых может меняться.
  • const — для переменных, значение которых задается один раз и не может быть переназначено.
  • В автоматизации мы часто используем const для селекторов элементов или конфигурационных данных, которые не должны меняться в процессе выполнения теста.

    Основные типы данных

    JavaScript — язык с динамической типизацией. Это значит, что вам не нужно указывать тип переменной при её создании, язык определит его сам.

    Вот основные типы, с которыми вы столкнетесь:

    * String (Строка): Текст, заключенный в кавычки. const message = "Test passed"; * Number (Число): Любые числа (целые и дробные). let timeout = 5000; * Boolean (Булево значение): Истина или ложь. let isVisible = true; * Null: Специальное значение, означающее «ничего» или «пусто». let error = null; * Undefined: Значение переменной, которая была объявлена, но ей ничего не присвоили.

    > В JavaScript есть старое ключевое слово var, но в современной разработке и автоматизации его использование считается плохой практикой из-за особенностей области видимости. Используйте только let и const.

    Объекты и массивы

    Часто данные приходят к нам в более сложных структурах.

    Объект (Object) — это коллекция пар «ключ-значение». В тестах объекты часто используются для описания тестовых данных или конфигураций.

    Массив (Array) — это упорядоченный список данных. Например, список найденных элементов на странице.

    Операторы сравнения

    В тестах мы постоянно что-то сравниваем: ожидаемый результат с фактическим. В JavaScript есть важный нюанс при сравнении.

    * == (нестрогое равенство): сравнивает значения, приводя их к общему типу. * === (строгое равенство): сравнивает и значения, и типы данных.

    Пример:

    Золотое правило QA: Всегда используйте строгое сравнение ===. Это убережет вас от неожиданных ошибок, когда тест проходит, хотя типы данных не совпадают.

    Функции

    Функция — это блок кода, который можно выполнять многократно. В автоматизации функции помогают нам переиспользовать код, например, функцию логина в систему.

    Классическое объявление

    Стрелочные функции (Arrow Functions)

    В современном JS чаще используется более лаконичный синтаксис — стрелочные функции. Они особенно популярны в таких фреймворках, как Mocha, Jest или Playwright.

    Если функция состоит из одной строки и возвращает значение, можно писать еще короче:

    Асинхронность: главный камень преткновения

    Это самая сложная, но самая важная тема для автоматизатора. Веб-браузеры работают асинхронно. Когда вы просите браузер открыть страницу или нажать кнопку, это действие происходит не мгновенно.

    Синхронный vs Асинхронный код

    Представьте, что вы в кофейне.

  • Синхронный подход: Вы заказываете кофе и стоите у кассы, глядя на бариста, пока он не нальет напиток. Вы не можете отойти, проверить телефон или поговорить с другом. Весь процесс заблокирован, пока кофе не будет готов.
  • Асинхронный подход: Вы заказываете кофе, вам дают пейджер (бипер) и вы идете за столик. Вы можете читать книгу или говорить по телефону. Когда кофе готов, пейджер пищит, и вы забираете заказ.
  • В JavaScript операции, такие как «загрузить страницу» или «найти элемент», подобны заказу кофе. Если бы они были синхронными, браузер бы «зависал» при каждом клике.

    !Сравнение синхронного (блокирующего) и асинхронного (неблокирующего) выполнения кода.

    Promise (Обещание)

    В JS результатом асинхронной операции является объект Promise (Промис). Это тот самый «пейджер» из кофейни. Промис может находиться в трех состояниях:

  • Pending (Ожидание): Запрос отправлен, ждем результат.
  • Resolved (Выполнено): Операция успешна (кофе готов).
  • Rejected (Отклонено): Произошла ошибка (кофемашина сломалась).
  • Async / Await

    Раньше для работы с промисами использовали цепочки .then(), но этот код было трудно читать. Современный стандарт ввел ключевые слова async и await, которые делают асинхронный код похожим на синхронный.

    * async — ставится перед объявлением функции. Говорит о том, что внутри функции будет асинхронность. * await — ставится перед вызовом асинхронной операции. Он говорит интерпретатору: «Подожди, пока этот промис не выполнится, прежде чем идти дальше».

    Пример теста на псевдокоде:

    Если убрать await, код попытается кликнуть по кнопке еще до того, как браузер успеет открыть сайт. Это приведет к ошибке Element not found.

    Условные конструкции и циклы

    Для управления потоком выполнения теста нам нужны условия и циклы.

    If / Else

    Используется для проверки условий. Например, если элемент виден — кликнуть, иначе — сделать скриншот.

    Циклы

    Циклы полезны, когда нужно обработать список элементов (например, проверить, что все товары в корзине имеют цену).

    Самый популярный цикл для работы с массивами — for...of:

    Заключение

    Мы разобрали базовые кирпичики JavaScript, необходимые для старта в автоматизации:

  • Переменные (let, const) хранят данные.
  • Типы данных определяют, с чем мы работаем (строки, числа, объекты).
  • Функции (особенно стрелочные) группируют логику.
  • async/await позволяют управлять временем выполнения команд в браузере.
  • В следующей статье мы перейдем к настройке окружения: установим Node.js и напишем наш первый скрипт, который запускается вне браузера.

    2. Настройка окружения и введение в тестовые раннеры Jest и Mocha

    Настройка окружения и введение в тестовые раннеры Jest и Mocha

    В предыдущей статье мы изучили синтаксис JavaScript, разобрались с переменными, функциями и асинхронностью. Теперь, когда мы умеем писать код, возникает вопрос: где и как его запускать?

    Браузерная консоль отлично подходит для экспериментов, но для серьезной автоматизации нам нужна стабильная среда выполнения на компьютере. В этой статье мы подготовим наш рабочий стол к работе: установим Node.js, разберемся с пакетным менеджером npm и познакомимся с инструментами, которые будут запускать наши тесты — тестовыми раннерами.

    Node.js: Двигатель вашего кода

    Изначально JavaScript жил только внутри браузеров. Чтобы запустить JS-код на сервере или на обычном компьютере, была создана платформа Node.js.

    Для QA-инженера Node.js — это фундамент. Именно на нем работают все современные инструменты автоматизации: Cypress, Playwright, WebdriverIO и тестовые раннеры.

    Установка Node.js

  • Перейдите на официальный сайт Node.js.
  • Скачайте версию LTS (Long Term Support). Это самая стабильная версия, рекомендованная для большинства пользователей.
  • Установите её как обычную программу, нажимая «Далее».
  • Чтобы проверить, что установка прошла успешно, откройте терминал (Command Prompt в Windows или Terminal в macOS/Linux) и введите команду:

    Если вы увидите версию (например, v18.16.0), значит, двигатель установлен и готов к работе.

    NPM: Ваш магазин инструментов

    Вместе с Node.js автоматически устанавливается npm (Node Package Manager). Это гигантская библиотека готового кода. Представьте, что вы строите дом. Вместо того чтобы самому изготавливать кирпичи, окна и двери, вы заказываете их в каталоге. В мире JavaScript этот каталог — npm.

    Любая библиотека для тестирования (будь то Jest, Mocha или Selenium) устанавливается одной командой через npm.

    Инициализация проекта

    Прежде чем устанавливать инструменты, нужно создать «паспорт» нашего проекта. Это файл package.json. В нем будет храниться информация о названии проекта, его версии и, самое главное, список всех используемых библиотек (зависимостей).

    Создайте новую папку для вашего проекта, откройте в ней терминал и введите:

    Флаг -y означает, что мы соглашаемся со всеми настройками по умолчанию. В папке появится файл package.json.

    Что такое тестовый раннер?

    Представьте, что вы написали 100 тестов. Запускать каждый файл вручную (node test1.js, node test2.js...) — это долго и неудобно. Вам нужен инструмент, который:

  • Найдет все файлы с тестами в проекте.
  • Запустит их (по очереди или параллельно).
  • Сравнит полученный результат с ожидаемым (Assertions).
  • Покажет красивый отчет: сколько тестов прошло, сколько упало и почему.
  • Этот инструмент называется Test Runner (Тестовый раннер).

    !Схематичное изображение того, как раннер берет файлы тестов, обрабатывает их и выдает отчет о результатах.

    Два самых популярных раннера в мире JavaScript — это Mocha и Jest. Давайте разберем их особенности.

    Mocha: Гибкий конструктор

    Mocha — это один из старейших и самых уважаемых инструментов. Его философия: «Делай одну вещь, но делай её хорошо». Mocha умеет только запускать тесты. Он не умеет делать проверки (assertions) или мокировать данные. Для этого к нему нужно подключать дополнительные библиотеки, чаще всего Chai.

    Установка Mocha и Chai

    В терминале в папке проекта введите:

    > Флаг --save-dev указывает, что эти библиотеки нужны только для разработки и тестирования, а не для работы самого приложения в продакшене.

    Структура теста на Mocha

    Mocha использует BDD-стиль (Behavior Driven Development), который читается как обычный английский текст.

    * describe — группирует тесты (например, «Тесты авторизации»). * it — конкретный тест-кейс (например, «должен успешно войти с правильным паролем»).

    Создадим файл math.test.js:

    Плюсы Mocha: * Полная свобода выбора инструментов для проверок. * Огромное сообщество и куча плагинов.

    Минусы: * Нужно настраивать и устанавливать дополнительные библиотеки (Chai, Sinon и т.д.).

    Jest: Всё включено

    Jest был создан компанией Facebook (Meta). Его философия противоположна Mocha: «Всё работает из коробки». Устанавливая Jest, вы получаете и раннер, и библиотеку утверждений, и инструмент для моков, и покрытие кода (code coverage).

    Сегодня Jest является стандартом де-факто для Unit-тестирования, но также широко используется и в автоматизации UI.

    Установка Jest

    Структура теста на Jest

    Синтаксис очень похож на Mocha, но импортировать ничего не нужно — функции describe, test (аналог it) и expect доступны глобально.

    Тот же пример на Jest:

    Плюсы Jest: * Не требует настройки (Zero config). * Параллельный запуск тестов (работает очень быстро). * Отличные отчеты об ошибках.

    Минусы: * Может быть «тяжеловесным» для очень маленьких проектов.

    Сравнение: Что выбрать?

    | Характеристика | Mocha | Jest | | :--- | :--- | :--- | | Философия | Конструктор (нужны плагины) | Комбайн (всё включено) | | Проверки (Assertions) | Нужна библиотека Chai | Встроены (expect) | | Скорость | Зависит от настройки | Высокая (параллельность) | | Популярность | Классика, стабильность | Современный стандарт |

    Для начинающего автоматизатора Jest часто является лучшим выбором, так как позволяет сразу начать писать тесты, не отвлекаясь на подбор библиотек для ассертов.

    Настройка запуска тестов

    Чтобы запустить тесты одной командой, нужно добавить скрипт в файл package.json. Найдите секцию "scripts" и измените её:

    Для Jest:

    Для Mocha:

    Теперь в терминале достаточно набрать:

    И раннер найдет все ваши файлы с тестами и выполнит их.

    Заключение

    Сегодня мы подготовили почву для будущих свершений:

  • Установили Node.js — среду выполнения.
  • Инициализировали проект с помощью npm.
  • Разобрали разницу между Mocha (гибкость) и Jest (удобство).
  • В следующих статьях мы начнем применять эти инструменты для реальной автоматизации действий в браузере. Убедитесь, что у вас установлен Node.js и VS Code, так как дальше начнется настоящая магия кода.

    3. UI-автоматизация: работа с селекторами и браузером в Cypress и Playwright

    UI-автоматизация: работа с селекторами и браузером в Cypress и Playwright

    В предыдущих статьях мы заложили фундамент: изучили синтаксис JavaScript, разобрались с асинхронностью и настроили рабочее окружение с Node.js. Теперь пришло время перейти к самому интересному — взаимодействию с браузером.

    UI-автоматизация (User Interface Automation) — это процесс, когда скрипт имитирует действия реального пользователя: открывает страницы, кликает по кнопкам, заполняет формы и проверяет, что приложение работает корректно. В этой статье мы разберем два самых популярных современных инструмента для этого: Cypress и Playwright, а также научимся находить элементы на странице с помощью селекторов.

    Что такое DOM и как браузер видит страницу

    Прежде чем писать код, нужно понять, как устроена веб-страница. Для нас страница — это красивая картинка с текстом и кнопками. Для браузера — это DOM (Document Object Model).

    DOM — это древовидная структура, где каждый элемент (кнопка, абзац, картинка) является узлом (объектом). Чтобы кликнуть по кнопке, наш автотест должен сначала найти этот конкретный узел в дереве DOM.

    !Структура DOM-дерева, показывающая иерархию элементов на странице.

    Селекторы: адрес элемента

    Селектор — это строка, которая указывает путь к элементу в DOM. Это как адрес на конверте: если адрес точный, письмо дойдет до получателя. Если адрес размытый (например, «деревня дедушке»), тест упадет с ошибкой.

    Основные типы селекторов

    Рассмотрим HTML-код кнопки:

    Мы можем найти эту кнопку разными способами:

  • По ID (#id): Самый быстрый способ, если ID уникален.
  • * Селектор: #submit-btn
  • По классу (.class): Используется часто, но классы могут повторяться у разных элементов.
  • * Селектор: .btn или .primary
  • По атрибутам ([attribute=value]): Очень мощный способ.
  • * Селектор: [type="submit"]
  • По тексту: Поиск элемента по его содержимому.
  • * Пример: кнопка с текстом «Войти».

    Золотое правило селекторов

    В современной автоматизации считается лучшей практикой использовать специальные тестовые атрибуты. Разработчики могут менять классы для стилизации, ID могут генерироваться динамически, но тестовый атрибут остается неизменным.

    > Лучший селектор — это тот, который не зависит от стилей (CSS) или структуры JS-кода. Используйте data-testid, data-cy или data-qa.

    Пример хорошего селектора: [data-testid="login-button"].

    Cypress: работа внутри браузера

    Cypress — это инструмент, который исполняет ваш код прямо внутри браузера, рядом с кодом вашего приложения. Это дает ему высокую скорость и стабильность.

    Поиск элементов в Cypress

    Основная команда для поиска — cy.get(). Она принимает CSS-селектор.

    Также в Cypress есть удобная команда cy.contains(), которая ищет элемент по тексту:

    Взаимодействие с элементами

    После того как элемент найден, мы можем совершить с ним действие. В Cypress это делается через цепочку команд (chaining).

    Обратите внимание: Cypress автоматически ждет появления элемента. Если кнопка появится через 2 секунды после загрузки, Cypress подождет эти 2 секунды, прежде чем кликнуть. Вам не нужно писать sleep или wait.

    Playwright: управление браузером снаружи

    Playwright от Microsoft использует другой подход. Он управляет браузером через протокол отладки (DevTools Protocol). Он поддерживает все современные браузеры (Chromium, Firefox, WebKit) и работает очень быстро.

    В Playwright мы используем async/await, о которых говорили в первой статье, так как все команды отправляются браузеру асинхронно.

    Локаторы в Playwright

    В Playwright вместо термина «селектор» чаще используют «локатор» (Locator). Философия Playwright гласит: «Тестируйте так, как это делает пользователь».

    Пользователь не ищет кнопку по CSS-классу .btn-primary. Он ищет кнопку по её роли («это кнопка») и названию («Войти»).

    Поэтому Playwright рекомендует использовать специальные методы:

    * page.getByRole('button', { name: 'Войти' }) — самый надежный способ. * page.getByText('Добро пожаловать') — поиск по тексту. * page.getByLabel('Имя пользователя') — поиск поля ввода по подписи. * page.getByPlaceholder('Введите пароль') — поиск по плейсхолдеру.

    Конечно, классические CSS-селекторы тоже поддерживаются через page.locator().

    Пример теста на Playwright

    Заметьте использование await перед каждым действием. Это обязательно, так как Playwright возвращает промисы.

    Сравнение подходов к поиску элементов

    | Характеристика | Cypress | Playwright | | :--- | :--- | :--- | | Основной метод | cy.get('css-selector') | page.locator('css') или page.getBy... | | Философия | Предпочитает data-testid атрибуты | Предпочитает доступность (Role, Label, Text) | | Ожидание | Автоматическое ожидание и повторные попытки (retries) | Автоматическое ожидание (auto-waiting) | | Синтаксис | Цепочки (.get().click()) | Асинхронный (await locator.click()) |

    Работа со списками элементов

    Часто нам нужно найти не один элемент, а список. Например, товары в корзине.

    В Cypress

    В Playwright

    Типичные ошибки новичков

  • Использование нестабильных селекторов.
  • Плохо:* div > div:nth-child(3) > span.active (сломается при любом изменении верстки). Хорошо:* [data-testid="status-badge"].

  • Принудительные паузы.
  • Плохо:* cy.wait(5000) или await page.waitForTimeout(5000). Хорошо:* Доверьтесь встроенным механизмам ожидания инструментов. Они сами подождут, пока элемент станет доступен для клика.

  • Зависимость от текста, который часто меняется.
  • * Если текст кнопки меняется с «Купить» на «Заказать», тест упадет. В таких случаях лучше использовать ID или data-атрибуты, либо выносить текст в переменные.

    Заключение

    Мы научились главному навыку автоматизатора UI — находить элементы на странице и взаимодействовать с ними.

    * Селекторы — это ваши карты для навигации по DOM-дереву. * Cypress предлагает удобный синхронный стиль написания тестов с мощным механизмом повторных попыток. * Playwright использует современные стандарты асинхронности и подталкивает к использованию селекторов, основанных на доступности (Accessibility).

    В следующей статье мы углубимся в тему проверок (Assertions) и узнаем, как убедиться, что приложение не просто кликается, а работает правильно.

    4. Автоматизация тестирования API: HTTP-запросы, валидация ответов и работа с JSON

    Автоматизация тестирования API: HTTP-запросы, валидация ответов и работа с JSON

    В предыдущих статьях мы научились настраивать окружение с Node.js и писать UI-тесты, которые кликают по кнопкам в браузере. Это важный навык, но UI-тесты имеют свои недостатки: они медленные и часто «падают» из-за незначительных изменений в верстке.

    Сегодня мы спустимся на уровень ниже и поговорим об API-тестировании. Представьте айсберг: UI — это лишь верхушка, видимая пользователю, а API — это огромная подводная часть, где происходит вся бизнес-логика. Тестирование API позволяет проверять работу приложения за считанные миллисекунды, не дожидаясь загрузки картинок и стилей.

    Что такое API и как это работает?

    API (Application Programming Interface) — это контракт, по которому одна программа общается с другой. В веб-разработке чаще всего используется архитектура REST, где общение происходит через протокол HTTP.

    Давайте вспомним аналогию с рестораном:

  • Клиент (Вы) — это ваш автотест или браузер.
  • Официант — это API. Он принимает ваш заказ и несет его на кухню.
  • Кухня — это Сервер (База данных и логика).
  • Вы не идете на кухню сами (не лезете в базу данных напрямую). Вы говорите официанту: «Принеси мне суп» (делаете запрос), и он возвращает вам тарелку (ответ).

    !Визуализация цикла запрос-ответ в протоколе HTTP.

    Анатомия HTTP-запроса

    Чтобы автоматизировать API, нужно понимать, из чего состоит общение. Любой HTTP-запрос состоит из нескольких ключевых частей:

    1. URL (Адрес)

    Куда мы стучимся. Например: https://api.example.com/users.

    2. Метод (Действие)

    Что мы хотим сделать. Основные методы, которые должен знать QA:

    * GET — Получить данные (дай мне список пользователей). * POST — Создать данные (создай нового пользователя). * PUT / PATCH — Обновить данные (измени имя пользователя). * DELETE — Удалить данные (удали пользователя).

    3. Headers (Заголовки)

    Служебная информация. Например, Authorization (пароль для входа) или Content-Type (в каком формате мы шлем данные).

    4. Body (Тело)

    Данные, которые мы отправляем (нужно только для POST, PUT, PATCH). В GET-запросах тела обычно нет.

    Статус-коды: язык светофора

    Сервер всегда отвечает числовым кодом. Знание этих кодов обязательно для автоматизатора:

    * 2xx (Успех): * 200 OK — всё прошло хорошо. * 201 Created — объект успешно создан (обычно после POST). * 4xx (Ошибка клиента): * 400 Bad Request — вы отправили некорректные данные. * 401 Unauthorized — вы не представились (нужен логин). * 403 Forbidden — вам сюда нельзя, даже если вы залогинены. * 404 Not Found — ресурс не найден. * 5xx (Ошибка сервера): * 500 Internal Server Error — сервер сломался, вы не виноваты.

    JSON: Универсальный формат данных

    В современном вебе данные передаются в формате JSON (JavaScript Object Notation). Это текстовый формат, который выглядит почти как объекты JavaScript, которые мы изучали в первой статье.

    Пример JSON:

    Работа с JSON в JavaScript

    Хотя JSON выглядит как объект, при передаче по сети это просто строка. Чтобы работать с ней в коде, нам нужны две встроенные функции:

  • JSON.parse() — превращает строку, полученную от сервера, в JavaScript-объект.
  • JSON.stringify() — превращает JavaScript-объект в строку, чтобы отправить её на сервер.
  • Инструменты: Axios и Jest

    Для автоматизации API на JavaScript нам понадобятся:

  • Jest — наш тестовый раннер (мы установили его во второй статье).
  • Axios — популярная библиотека для отправки HTTP-запросов. Она удобнее встроенного fetch, так как автоматически обрабатывает JSON и ошибки.
  • Установка Axios

    Откройте терминал в папке вашего проекта и введите:

    Пишем первый API-тест

    Для практики мы будем использовать бесплатный тестовый API JSONPlaceholder. Это сервис, который имитирует работу реального бэкенда.

    Создайте файл api.test.js.

    Тест 1: Получение данных (GET)

    Нам нужно проверить, что при запросе пользователя с ID 1 сервер возвращает статус 200 и правильное имя.

    Обратите внимание на использование async/await. HTTP-запросы — это асинхронные операции, они занимают время. Без await тест завершится раньше, чем придет ответ от сервера.

    Тест 2: Создание данных (POST)

    Теперь попробуем создать новый пост. Мы должны отправить данные и проверить, что сервер их принял.

    Валидация структуры ответа

    В реальных проектах проверять каждое поле (name, age, city...) вручную долго и ненадежно. Если API вернет 100 полей, ваш тест станет гигантским.

    Вместо этого часто проверяют типы данных. В Jest для этого есть удобные матчеры (matchers).

    Здесь мы говорим: «Я не знаю, какое точно имя придет, но это точно должна быть Строка. А ID точно должен быть Числом».

    Обработка ошибок

    Хороший тестировщик проверяет не только позитивные сценарии («всё работает»), но и негативные («что будет, если сломать»).

    Давайте проверим, что API возвращает 404, если мы запрашиваем несуществующего пользователя.

    Примечание: В Axios по умолчанию любой статус вне диапазона 2xx вызывает исключение catch block.

    Заключение

    Автоматизация API — это мощный инструмент, который позволяет:

  • Находить ошибки логики до того, как будет готов интерфейс.
  • Запускать тысячи тестов за минуты.
  • Проверять граничные значения и типы данных.
  • Мы изучили: * Основные методы HTTP (GET, POST). * Статус-коды (200, 201, 404, 500). * Формат JSON и его парсинг. * Библиотеку Axios для отправки запросов в связке с Jest.

    В следующей статье мы объединим наши знания и поговорим о том, как выстраивать архитектуру тестового проекта, используя паттерн Page Object Model, чтобы наши тесты были чистыми и поддерживаемыми.

    5. Паттерн Page Object Model и интеграция автотестов в CI/CD пайплайны

    Паттерн Page Object Model и интеграция автотестов в CI/CD пайплайны

    Поздравляю! Вы прошли большой путь: от изучения переменных в JavaScript до написания полноценных UI и API тестов. Теперь ваши скрипты умеют открывать браузер, кликать по кнопкам и проверять JSON-ответы сервера.

    Но есть одна проблема. Пока у вас 5–10 тестов, всё отлично. Но когда их становится 100 или 500, поддержка кода превращается в ад. Представьте: разработчики изменили id кнопки «Войти» на странице логина. Если вы писали селекторы прямо в тестах, вам придется открывать 50 файлов и менять одну и ту же строчку 50 раз.

    Сегодня мы изучим Page Object Model (POM) — паттерн проектирования, который спасет ваши нервы, и настроим CI/CD, чтобы тесты запускались сами, пока вы пьете кофе.

    Page Object Model: Разделяй и властвуй

    Page Object Model (POM) — это самый популярный паттерн в автоматизации тестирования. Его главная идея проста: отделите логику теста от структуры страницы.

    Представьте автомобиль. Водителю (тесту) не нужно знать, как устроен двигатель или где проходят провода (HTML/CSS). Ему нужен руль и педали (методы класса). Если механик заменит двигатель (изменится верстка), руль останется тем же, и водителю не придется переучиваться.

    !Схематичное изображение взаимодействия теста и страницы через прослойку Page Object.

    Проблема «Спагетти-кода»

    Давайте посмотрим на типичный тест новичка (на примере Playwright), который трудно поддерживать:

    Если класс .submit-btn изменится, этот тест упадет. И еще 10 других тестов, где используется эта кнопка, тоже упадут.

    Решение с помощью классов

    В JavaScript мы создаем Класс, который описывает страницу. В нем мы храним селекторы и методы взаимодействия.

    Создадим файл pages/LoginPage.js:

    Теперь перепишем наш тест:

    Преимущества:

  • Переиспользование: Метод login() можно использовать в сотне тестов.
  • Легкая поддержка: Если селектор кнопки изменится, мы поправим его только в файле LoginPage.js. Тесты трогать не нужно.
  • Читаемость: Код теста стал чище и понятнее.
  • Структура проекта

    С внедрением POM ваш проект должен выглядеть структурировано:

    * /tests — здесь лежат сами сценарии проверок (specs). * /pages — здесь лежат классы Page Objects. * /utils — вспомогательные функции (генераторы данных, хелперы). * /config — настройки окружения (URL, таймауты).

    CI/CD: Автоматизация запуска

    Вы написали идеальные тесты. Но запускать их вручную командой npm test перед каждым релизом — это человеческий фактор. Вы можете забыть, заболеть или запустить не те тесты.

    Здесь на сцену выходит CI/CD (Continuous Integration / Continuous Delivery) — непрерывная интеграция и доставка.

    Суть проста: где-то в облаке есть сервер, который следит за вашим кодом. Как только вы отправляете изменения в репозиторий (делаете git push), этот сервер просыпается, скачивает ваш код и запускает тесты.

    !Иллюстрация жизненного цикла кода в CI/CD: от коммита до отчета о тестировании.

    Headless Mode (Безголовый режим)

    Важный нюанс: на серверах CI/CD (обычно это Linux-контейнеры) нет монитора. Они не могут открыть визуальное окно браузера Chrome или Firefox.

    Поэтому тесты запускаются в режиме Headless. Браузер работает как процесс в оперативной памяти, выполняет все действия, но не отрисовывает интерфейс пользователю. Это работает быстрее и потребляет меньше ресурсов.

    В Playwright и Cypress режим headless включен по умолчанию при запуске в терминале.

    Настройка GitHub Actions

    Самый простой способ настроить CI для JS-проекта — использовать GitHub Actions. Это бесплатно для публичных репозиториев.

    Вам нужно создать в проекте файл по пути .github/workflows/test.yml.

    Пример конфигурации (YAML файл):

    Что здесь происходит?

  • Trigger (Триггер): Мы сказали GitHub'у следить за веткой main. Любое изменение там запустит этот сценарий.
  • Environment (Окружение): Мы арендуем виртуальную машину ubuntu-latest.
  • Steps (Шаги): Мы последовательно выполняем команды, как если бы вы вводили их в своем терминале: скачали код -> установили Node.js -> установили библиотеки -> запустили тесты.
  • Artifacts (Артефакты): Если тесты прошли (или упали), мы сохраняем отчет, который можно скачать и посмотреть в браузере.
  • Отчетность

    В CI/CD критически важно понимать, почему тест упал. Смотреть в консольный вывод (console.log) неудобно.

    Современные инструменты генерируют HTML-отчеты. В Playwright это встроенная функция, для других инструментов часто используют Allure Report — мощный инструмент для визуализации статистики тестов.

    Заключение

    Сегодня мы превратили наш код из любительского скрипта в профессиональный проект:

  • Page Object Model помог нам навести порядок в коде, убрать дублирование и облегчить поддержку.
  • CI/CD с GitHub Actions автоматизировал рутину. Теперь вы не «тестировщик, который запускает скрипты», а инженер, построивший систему контроля качества.
  • В этом курсе мы прошли путь от основ JS до архитектуры автотестов. Эти знания — база для работы на позиции QA Automation Engineer. Дальше вас ждет практика, изучение Docker и углубление в специфику вашего рабочего проекта. Удачи!