«В этом посте я кратко расскажу о часто используемых подходах в автоматизации QA: Объектная модель страницы (POM), Тестирование, управляемое данными (DDT) и Разработка, ориентированная на поведение (BDD). Я также предоставлю примеры реализации этих подходов в Playwright.
Чтобы помочь вам лучше понять эти реализации, я создала репозиторий с примерами. Вы можете клонировать репозиторий с помощью команды ниже, чтобы посмотреть и запустить его:
git clone https://github.com/senakorkmaz/Test-automation-architecture.git
Структура репозитория:
Test-automation-architecture/ │ ├── tests/ # Тестовые сценарии Playwright │ ├── bddTests/ # Примеры BDD в Cucumber │ │ ├── features/ # Тестовые сценарии на Gherkin │ │ │ └── login.feature # Сценарий логина │ │ ├── steps/ # Описания шагов │ │ │ └── loginSteps.js # Шаги логина │ │ ├── world.js # Класс Cucumber World │ │ └── cucumber.js # Конфиг-файл Cucumber │ ├── ddtTests/ # Примеры Data-Driven Testing │ │ └── loginDDT.spec.js # Тест логина │ ├── pomTests/ # Примеры Page Object Model │ │ └── loginPOMTest.spec.js # Тест логина │ ├── pages/ # Классы Page Object Model │ └── loginPage.js # Класс POM страницы логина │ ├── testData/ # Тестовые данные для Data-Driven Testing │ └── users.json # Данные пользователя для логина │ ├── playwright.config.js # Конфиг-файл Playwright ├── package.json # Зависимости и конфиг-файл └── README.md # Описание проекта и документация
Теперь рассмотрим, как работает реализация.
Что такое тестирование, управляемое данными (DDT)
Или тестирование на основе данных — это подход, при котором один и тот же тестовый сценарий выполняется с разными наборами данных. Вместо того чтобы каждый раз писать тестовый сценарий вручную, мы можем динамически запускать тесты, используя данные из внешних источников (JSON, CSV, Excel и т. д.).
Например, мы можем использовать JSON-файл, содержащий различные имена пользователей и пароли, для повторения тестов на вход в систему. Такой подход ускоряет процесс, упрощает обслуживание и позволяет проводить более полные тесты.
→ loginDDT.spec.js
const { test, expect } = require('@playwright/test'); const LoginPage = require('../../pages/loginPage'); const users = require('../../testData/users.json').users; test.describe('Data-Driven Login Tests', () => { users.forEach(data => { test(`Login test for ${data.username}`, async ({ page }) => { const loginPage = new LoginPage(page); await loginPage.navigate(); await loginPage.login(data.username, data.password); await expect(page).toHaveURL(/inventory/); }); }); });
В тестовом коде Playwright, написанном для DDT:
- Информация о пользователе считывается из файла JSON.
- Тест автоматически выполняется для каждого пользователя.
- Управление страницами осуществляется с помощью объектной модели страницы (POM).
- URL, на который перенаправляется страница, проверяется в случае успешного логина.
Что такое объектная модель страницы (POM)
Объектная модель страницы (POM) — это шаблон проектирования (дизайн-паттерн), используемый для абстрагирования и управления взаимодействием страниц в тестовых сценариях. При таком подходе каждая веб-страница моделируется как объект (класс), и все действия, связанные с этой страницей (заполнение форм, нажатие кнопок), определяются внутри этого объекта.
Например, вместо того чтобы прописывать действия по входу в систему в каждом тестовом файле, мы можем определить их в классе LoginPage.
→ loginPage.js
class LoginPage { constructor(page) { this.page = page; this.usernameField = '#user-name'; this.passwordField = '#password'; this.loginButton = '#login-button'; } async navigate() { await this.page.goto('https://www.saucedemo.com/'); } async login(username, password) { await this.page.fill(this.usernameField, username); await this.page.fill(this.passwordField, password); await this.page.click(this.loginButton); } } module.exports = LoginPage;
- Constructor:
constructor
класса принимает объект page и определяет CSS-селекторы для элементов на странице входа (имя пользователя, пароль, кнопка входа). - navigate(): Эта функция перенаправляет пользователя на страницу входа с помощью метода
goto
. - login(username, password): Эта функция выполняет операцию входа в систему с указанными именем пользователя и паролем. Она заполняет поля в форме входа и нажимает кнопку входа.
Этот класс централизованно управляет взаимодействием страниц в соответствии с архитектурой Page Object Model (POM), что делает его пригодным для повторного использования в тестах.
→ loginPOMTest.spec.js
const { test, expect } = require('@playwright/test'); const LoginPage = require('../../pages/loginPage'); test('User should be able to login', async ({ page }) => { const loginPage = new LoginPage(page); await loginPage.navigate(); await loginPage.login('standard_user', 'secret_sauce'); await expect(page).toHaveURL(/inventory/); });
В тестовом коде Playwright, написанном для POM:
- Из класса
LoginPage
создается объект. Этот класс содержит все взаимодействия, связанные со страницей входа в систему. - Функция
navigate
используется для перехода на страницу. Она открывает страницу входа в систему. - Функция
login
вызывается для выполнения входа в систему с помощью имени пользователя и пароля. Информация о пользователе задается в тестовом коде. - Выполняется проверка успешности входа в систему. Когда страница перенаправляется на правильный URL-адрес, это подтверждает, что операция входа прошла успешно.
Что такое поведенчески-ориентированная разработка (BDD)
Это подход, используемый для написания тестов, управляемых поведением (behavior-driven), в процессе разработки ПО. BDD облегчает коммуникацию между бизнес-юнитами (бизнес-аналитиком, менеджером продукта, владельцем продукта и т. д.) и разработчиками, поскольку тестовые сценарии напрямую выражают бизнес-требования. Сценарии обычно пишутся в формате Given-When-Then («задано-если-тогда» и описываются на языке Gherkin.
Теперь посмотрим на наш пример кода.
→ loginSteps.js
const { Given, When, Then } = require('@cucumber/cucumber'); const { expect } = require('@playwright/test'); const LoginPage = require('../../../pages/loginPage'); let loginPage; Given('User is on the login page', async function () { loginPage = new LoginPage(this.page); await loginPage.navigate(); }); When('User enters {string} and {string}', async function (username, password) { await loginPage.login(username, password); }); Then('User should see the product inventory page', async function () { await expect(this.page).toHaveURL(/inventory/); });
Он используется для реализации шагов в feature-файле (файле разрабатываемой функции), написанном на Gherkin. Шаги Given, When и Then соответствуют утверждениям в Gherkin-сценарии. Эти шаги реализуются с помощью функций объектной модели страницы (POM). Например, функция navigate() используется на шаге Given для перехода на страницу, функция login() используется на шаге When для выполнения входа, а функция expect() используется на шаге Then для проверки URL. Таким образом, мы устанавливаем последовательную связь между сценариями Gherkin и тестами.
→ login.feature
const { Given, When, Then } = require('@cucumber/cucumber'); const { expect } = require('@playwright/test'); const LoginPage = require('../../../pages/loginPage'); let loginPage; Given('User is on the login page', async function () { loginPage = new LoginPage(this.page); await loginPage.navigate(); }); When('User enters {string} and {string}', async function (username, password) { await loginPage.login(username, password); }); Then('User should see the product inventory page', async function () { await expect(this.page).toHaveURL(/inventory/); });
Шаги Given, When и Then соответствуют релевантным функциям в файле loginSteps.js. Такой подход обеспечивает соответствие тестов сценариям Gherkin, делая их понятными для нетехнических сотрудников.
Вы можете добавлять новые feature-файлы для создания новых сценариев и тестирования различных ситуаций. Например, вы можете протестировать эти ситуации с помощью таких файлов, как login-invalid-credentials.feature (некорректные имя или пароль) или login-locked-out.feature (блокировка пользователя после серии неудачных попыток входа).
Когда используются эти подходы:
- POM (Page Object Model): Используется для средне- и крупномасштабных тестов пользовательского интерфейса, повышает читабельность, предотвращая дублирование кода.
- BDD (Behavior-Driven Development): Предпочтителен в проектах, ориентированных на тесное сотрудничество, позволяя писать тесты даже нетехническим специалистам.
- DDT (Data-Driven Testing): Используется при тестировании с большим количеством наборов данных, удобно добавлять и изменять данные.»