Объектная модель страницы (POM) — это шаблон проектирования, широко используемый в автоматизации тестирования, который создает репозиторий объектов для элементов веб-интерфейса. Преимущество модели в том, что она уменьшает дублирование кода и улучшает сопровождение тестов.
Эта история представляет собой руководство по использованию Puppeteer, TypeScript и Jest для написания простого сквозного теста (E2E). В учебнике будет написано несколько тестов, чтобы охватить несколько простых тестовых случаев. В учебнике также используется модальный шаблон объекта страницы для выполнения этих тестовых случаев.
Мы будем использовать демо-сайт электронной коммерции — https://www.saucedemo.com/.
С помощью этого веб-сайта мы можем написать готовые примеры для страницы входа и добавить поток корзины.
Вход в систему: должно возвращать правильное сообщение об ошибке, если имя пользователя или пароль недействительны или учетная запись заблокирована.
Добавление товаров в корзину. На главной странице добавьте несколько товаров в корзину. Перейдите на страницу корзины, эти товары должны были появиться.
Проект E2E с Puppeteer, TypeScript и Jest
Первоначальный проект
В каталоге вашего проекта установите TypeScript и создайте файл tsconfig.json
:
$ npm init -y # Init nodejs project $ npm install typescript $ npx tsc --init # Create tsconfig.json file with default values
Установите пакеты зависимостей:
$ npm install jest jest-puppeteer puppeteer ts-jest @types/jest @types/jest-environment-puppeteer @types/puppeteer
- jest-puppeteer: предустановка Jest, упрощающая настройку безголового браузера puppeteer.
- @types/jest-environment-puppeteer: определение типа поддерживает TypeScript, когда вы пишете код TS с помощью Jest и Puppeteer.
Конфигурация TypeScript, Jest и Puppeteer:
tsconfig.json
:
{ "compilerOptions": { "target": "es5", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "rootDir": "./__tests__", "sourceMap": true, "types": [ "jest", "puppeteer", "jest-environment-puppeteer", ], "outDir": "dist", }, "include": [ "./__tests__", ] }
jest-puppeteer.config.js
:
module.exports = { launch: { dumpio: true, headless: process.env.HEADLESS === 'true', args: ['--disable-infobars', '--window-size=1200,800'], defaultViewport: null, }, browserContext: 'default', };
jest.config.js
:
module.exports = { testTimeout: 30000, testMatch: ['**/?(*.)+(spec|test).[t]s'], preset: 'jest-puppeteer', transform: { '^.+\\.ts$': 'ts-jest', }, testPathIgnorePatterns: ['/node_modules/', 'dist'], };
Создайте тестовый сценарий для проекта. Обновим файл package.json
:
... "scripts": { "test": "jest --runInBand" }, ...
Параметр --runInBrand
для последовательного запуска всех тестовых случаев.
Создайте простой тест
Создайте простой файл спецификаций в каталоге __test__
. И напишите простой тест «Зайдите на главную страницу Google и убедитесь, что заголовок страницы Google
».
google.spec.ts
describe("Google.com", () => { it('should get correct title when go to home page', async () => { await page.goto('https://google.com'); const title = await page.title(); expect(title).toEqual('Google'); }); });
С помощью @types/jest-environment-puppeteer
мы можем легко использовать объект page
в качестве объекта страницы Puppeteer в нашем файле TS.
Запустите тестовый скрипт:
# Run in normal mode $ npm run test # Or `npm test` or `npm t` # Run with headless mode $ HEADLESS=true npm run test
Вывод будет выглядеть следующим образом:
Determining test suites to run... DevTools listening on ws://127.0.0.1:63472/devtools/browser/6a96a46a-6fea-4511-9374-5d9511557abb PASS __tests__/google.spec.ts Google.com ✓ should get correct title when go to home page (859 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 2.649 s, estimated 3 s Ran all test suites.
Реализуйте объектные модели страницы
Создайте объект базовой страницы — объект включает в себя некоторые общие функции
./__test__/pages/base.po.ts
Это абстрактный класс с go
абстрактной функцией — функцией для перехода к правильному URL-адресу каждой страницы.
Сосредоточьтесь на нашем первом тестовом примере — странице входа на демонстрационный веб-сайт. Взгляните на страницу входа:
Тогда объектная модель страницы входа будет включать 4 элемента и 1 действие.
./__test__/pages/login.po.ts
У нас есть действие login
и вспомогательная функция getErrorMessage
для получения текущего сообщения об ошибке.
Теперь мы можем создать тестовую спецификацию для страницы входа:
./__test__/login.spec.ts
Мы используем синтаксис test.each
Jest для создания 3 «неудачных» тестовых случаев.
Теперь вы можете снова запустить тест npm run test
, и результат будет выглядеть так:
Determining test suites to run... DevTools listening on ws://127.0.0.1:64018/devtools/browser/ef8bc336-90ee-414b-bb1e-2df87fe8fe4c PASS __tests__/login.spec.ts Login ✓ should display "Epic sadface: Username and password do not match any user in this service" when username|password is "wrong_username|secret_sauce" (366 ms) ✓ should display "Epic sadface: Username and password do not match any user in this service" when username|password is "standard_user|wrong_password" (185 ms) ✓ should display "Epic sadface: Sorry, this user has been locked out." when username|password is "locked_out_user|secret_sauce" (150 ms) ✓ should go to inventory page when username and password are correct (193 ms) Test Suites: 1 passed, 1 total Tests: 4 passed, 4 total Snapshots: 0 total Time: 3.418 s Ran all test suites.
Это все, что касается страницы входа.
Спецификация добавления товара в корзину более сложна, чем спецификация входа. История спецификации будет такой:
GIVE: List of products on the inventory page WHEN: Click "Add to cart" button on some products THEN: Number of cart item (top-right badge) should be updated corectly. WHEN: Go to cart page THEN: The added products should be appeared
Давайте сначала cart.spect.ts
файл:
Мы получаем все продукты на странице инвентаря, выбираем 3 случайных товара, затем пытаемся добавить их в корзину. Подтвердите количество корзины.
Перейдите на страницу корзины, получите все товары на этой странице и сравните с 3 товарами.
Спецификация e2e может использовать один или несколько объектов страницы. Как и наша спецификация, она использует inventory page object
и cart page object
.
inventory.po.ts
cart.po.ts
Выполнить тестовый скрипт с опцией --verbose
:
$ npm run test -- --verbose # Result Determining test suites to run... DevTools listening on ws://127.0.0.1:56282/devtools/browser/61fb6612-de1f-4b08-8729-be984829f009 PASS __tests__/login.spec.ts Login ✓ should display "Epic sadface: Username and password do not match any user in this service" when username|password is "wrong_username|secret_sauce" (367 ms) ✓ should display "Epic sadface: Username and password do not match any user in this service" when username|password is "standard_user|wrong_password" (196 ms) ✓ should display "Epic sadface: Sorry, this user has been locked out." when username|password is "locked_out_user|secret_sauce" (147 ms) ✓ should go to inventory page when username and password are correct (181 ms) PASS __tests__/cart.spec.ts Cart ✓ should add correct products to cart (488 ms) Test Suites: 2 passed, 2 total Tests: 5 passed, 5 total Snapshots: 0 total Time: 3.92 s, estimated 5 s Ran all test suites.
Мы закончили учебник e2e, используя объектные модели страниц.
Вывод
- Объектная модель страницы TypeScript Puppeteer делает наш код тестирования e2e пригодным для сопровождения и повторного использования.
- С предустановкой jest-puppeteer мы можем «внедрять» объекты
page
иbrowser
в любое место проекта Jest, легко создавая классы объектов страницы.
Исходный код, используемый в этой статье, опубликован на Github.
Спасибо за чтение!
Дополнительные материалы на plainenglish.io