Визуальное тестирование
Что оно может делать?
WebdriverIO предоставляет сравнение изображений экранов, элементов или полной страницы для
- 🖥️ Настольных браузеров (Chrome / Firefox / Safari / Microsoft Edge)
- 📱 Мобильных / Планшетных браузеров (Chrome на эмуляторах Android / Safari на iOS-симуляторах / Симуляторах / реальных устройствах) через Appium
- 📱 Нативных приложений (эмуляторы Android / iOS-симуляторы / реальные устройства) через Appium (🌟 НОВОЕ 🌟)
- 📳 Гибридных приложений через Appium
через @wdio/visual-service
, который является легковесным сервисом WebdriverIO.
Это позволяет вам:
- сохранять или сравнивать экраны/элементы/полные страницы с эталоном
- автоматически создавать эталон, когда его нет
- блокировать пользовательские области и даже автоматически исключать статус и/или панели инструментов (только для мобильных) во время сравнения
- увеличивать размеры скриншотов элементов
- скрывать текст во время сравнения веб-сайтов для:
- улучшения стабильности и предотвращения проблем с рендерингом шрифтов
- концентрации только на макете веб-сайта
- использовать различные методы сравнения и набор дополнительных матчеров для лучшей читаемости тестов
- проверять, как ваш веб-сайт поддерживает навигацию с помощью клавиши Tab на клавиатуре), см. также Навигация по сайту с помощью Tab
- и многое другое, смотрите опции сервиса и методов
Сервис представляет собой легковесный модуль для получения необходимых данных и скриншотов для всех браузеров/устройств. Мощь сравнения обеспечивается ResembleJS. Если вы хотите сравнивать изображения онлайн, вы можете проверить онлайн-инструмент.
Методы saveScreen
, saveElement
, checkScreen
, checkElement
и матчеры toMatchScreenSnapshot
и toMatchElementSnapshot
могут использоваться для нативных приложений/контекста.
Пожалуйста, используйте свойство isHybridApp:true
в настройках сервиса, если вы хотите использовать его для гибридных приложений.
Установка
Самый простой способ - сохранить @wdio/visual-service
в качестве dev-зависимости в вашем package.json
, через:
npm install --save-dev @wdio/visual-service
Использование
@wdio/visual-service
можно использовать как обычный сервис. Вы можете настроить его в вашем конфигурационном файле следующим образом:
import path from "node:path";
// wdio.conf.ts
export const config = {
// ...
// =====
// Setup
// =====
services: [
[
"visual",
{
// Некоторые опции, подробнее в документации
baselineFolder: path.join(process.cwd(), "tests", "baseline"),
formatImageName: "{tag}-{logName}-{width}x{height}",
screenshotPath: path.join(process.cwd(), "tmp"),
savePerInstance: true,
// ... дополнительные опции
},
],
],
// ...
};
Дополнительные опции сервиса можно найти здесь.
После настройки в вашей конфигурации WebdriverIO, вы можете приступить к добавлению визуальных проверок в ваши тесты.
Capabilities
Для использования модуля визуального тестирования вам не нужно добавлять никаких дополнительных опций к вашим capabilities. Однако в некоторых случаях вы можете захотеть добавить дополнительные метаданные к своим визуальным тестам, такие как logName
.
logName
позволяет вам присвоить пользовательское имя каждому capability, которое затем может быть включено в имена файлов изображений. Это особенно полезно для различения скриншотов, сделанных в разных браузерах, устройствах или конфигурациях.
Чтобы включить это, вы можете определить logName
в разделе capabilities
и убедиться, что опция formatImageName
в сервисе визуального тестирования ссылается на него. Вот как вы можете настроить это:
import path from "node:path";
// wdio.conf.ts
export const config = {
// ...
// =====
// Setup
// =====
capabilities: [
{
browserName: 'chrome',
'wdio-ics:options': {
logName: 'chrome-mac-15', // Пользовательское имя для Chrome
},
}
{
browserName: 'firefox',
'wdio-ics:options': {
logName: 'firefox-mac-15', // Пользовательское имя для Firefox
},
}
],
services: [
[
"visual",
{
// Некоторые опции, подробнее в документации
baselineFolder: path.join(process.cwd(), "tests", "baseline"),
screenshotPath: path.join(process.cwd(), "tmp"),
// Формат ниже будет использовать `logName` из capabilities
formatImageName: "{tag}-{logName}-{width}x{height}",
// ... дополнительные опции
},
],
],
// ...
};
Как это работает
-
Настройка
logName
:- В разделе
capabilities
назначьте уникальныйlogName
каждому браузеру или устройству. Например,chrome-mac-15
идентифицирует тесты, запущенные на Chrome на macOS версии 15.
- В разделе
-
Пользовательское именование изображений:
-
Опция
formatImageName
интегрируетlogName
в имена файлов скриншотов. Например, еслиtag
- homepage, а разрешение -1920x1080
, итоговое имя файла может выглядеть так:homepage-chrome-mac-15-1920x1080.png
-
-
Преимущества пользовательского именования:
- Различение скриншотов из разных браузеров или устройств становится намного проще, особенно при управлении эталонами и отладке расхождений.
-
Примечание о значениях по умолчанию:
- Если
logName
не установлен в capabilities, опцияformatImageName
будет отображать его как пустую строку в именах файлов (homepage--15-1920x1080.png
)
- Если
WebdriverIO MultiRemote
Мы также поддерживаем MultiRemote. Для корректной работы убедитесь, что вы добавили wdio-ics:options
к вашим
capabilities, как вы можете видеть ниже. Это обеспечит уникальное имя для каждого скриншота.
Написание ваших тестов не будет отличаться по сравнению с использованием testrunner
// wdio.conf.js
export const config = {
capabilities: {
chromeBrowserOne: {
capabilities: {
browserName: "chrome",
"goog:chromeOptions": {
args: ["disable-infobars"],
},
// ЭТО!!!
"wdio-ics:options": {
logName: "chrome-latest-one",
},
},
},
chromeBrowserTwo: {
capabilities: {
browserName: "chrome",
"goog:chromeOptions": {
args: ["disable-infobars"],
},
// ЭТО!!!
"wdio-ics:options": {
logName: "chrome-latest-two",
},
},
},
},
};
Запуск программно
Вот минимальный пример того, как использовать @wdio/visual-service
через опции remote
:
import { remote } from "webdriverio";
import VisualService from "@wdio/visual-service";
let visualService = new VisualService({
autoSaveBaseline: true,
});
const browser = await remote({
logLevel: "silent",
capabilities: {
browserName: "chrome",
},
});
// "Запускаем" сервис, чтобы добавить пользовательские команды в `browser`
visualService.remoteSetup(browser);
await browser.url("https://webdriver.io/");
// или используйте это ТОЛЬКО для сохранения скриншота
await browser.saveFullPageScreen("examplePaged", {});
// или используйте это для проверки. Оба метода не обязательно должны быть объединены, см. FAQ
await browser.checkFullPageScreen("examplePaged", {});
await browser.deleteSession();
Навигация по сайту с помощью Tab
Вы можете проверить, доступен ли веб-сайт с помощью клавиши TAB на клавиатуре. Тестирование этой части доступности всегда было трудоемкой (ручной) работой и довольно сложной для автоматизации.
С помощью методов saveTabbablePage
и checkTabbablePage
вы теперь можете рисовать линии и точки на вашем веб-сайте, чтобы проверить порядок табуляции.
Имейте в виду, что это полезно только для настольных браузеров и НЕ для мобильных устройств. Все настольные браузеры поддерживают эту функцию.
Работа вдохновлена постом в блоге Viv Richards о "АВТОМАТИЗАЦИИ ПРОВЕРКИ НАВИГАЦИИ ПО СТРАНИЦЕ С ПОМОЩЬЮ КЛАВИШИ TAB (ЭТО ВООБЩЕ СЛОВО?) С ПОМОЩЬЮ ВИЗУАЛЬНОГО ТЕСТИРОВАНИЯ".
Способ выбора элементов для навигации основан на модуле tabbable. Если есть какие-либо проблемы с табуляцией, проверьте README.md и особенно раздел Дополнительные сведения.
Как это работает
Оба метода создадут элемент canvas
на вашем веб-сайте и нарисуют линии и точки, чтобы показать вам, куда будет перемещаться ваш TAB, если конечный пользователь будет его использовать. После этого он создаст полностраничный скриншот, чтобы дать вам хороший обзор потока.
**Используйте saveTabbablePage
только когда вам нужно создать скриншот и ВЫ НЕ хотите сравнивать его с эталонным изображением.
Когда вы хотите сравнить поток табуляции с эталоном, вы можете использовать метод checkTabbablePage
. Вы НЕ нуждаетесь в использовании двух методов вместе. Если уже есть эталонное изображение, которое может быть автоматически создано путем указания autoSaveBaseline: true
при инициализации сервиса,
метод checkTabbablePage
сначала создаст текущее изображение, а затем сравнит его с эталоном.
Опции
Оба метода используют те же опции, что и saveFullPageScreen
или
compareFullPageScreen
.
Пример
Вот пример того, как работает табуляция на нашем тестовом веб-сайте:
Автоматическое обновление неудачных визуальных снимков
Обновляйте эталонные изображения через командную строку, добавляя аргумент --update-visual-baseline
. Это
- автоматически скопирует фактически сделанный скриншот и поместит его в папку с эталонами
- если есть различия, тест пройдет успешно, потому что эталон был обновлен
Использование:
npm run test.local.desktop --update-visual-baseline
При запуске с уровнем логирования info/debug вы увидите следующие добавленные логи
[0-0] ..............
[0-0] #####################################################################################
[0-0] INFO:
[0-0] Updated the actual image to
[0-0] /Users/wswebcreation/Git/wdio/visual-testing/localBaseline/chromel/demo-chrome-1366x768.png
[0-0] #####################################################################################
[0-0] ..........
Поддержка TypeScript
Этот модуль включает поддержку TypeScript, что позволяет вам пользоваться преимуществами автодополнения, типовой безопасности и улучшенного опыта разработчика при использовании сервиса визуального тестирования.
Шаг 1: Добавление определений типов
Чтобы убедиться, что TypeScript распознает типы модуля, добавьте следующую запись в поле types в вашем tsconfig.json:
{
"compilerOptions": {
"types": ["@wdio/visual-service"]
}
}
Шаг 2: Включение типовой безопасности для опций сервиса
Чтобы обеспечить проверку типов для опций сервиса, обновите вашу конфигурацию WebdriverIO:
// wdio.conf.ts
import { join } from 'node:path';
// Импортируйте определение типа
import type { VisualServiceOptions } from '@wdio/visual-service';
export const config = {
// ...
// =====
// Setup
// =====
services: [
[
"visual",
{
// Опции сервиса
baselineFolder: join(process.cwd(), './__snapshots__/'),
formatImageName: '{tag}-{logName}-{width}x{height}',
screenshotPath: join(process.cwd(), '.tmp/'),
} satisfies VisualServiceOptions, // Обеспечивает типовую безопасность
],
],
// ...
};