Миграция с ApplitoolsРанний доступ

Перенос набора тестов Playwright с Applitools Eyes на Delta-QA

Набор тестов Playwright, написанный для Applitools Eyes, работает в Delta-QA после двух изменений: импорта и переменных окружения. Его eyes.open, check, close, BatchInfo, addBrowser и регионы остаются на месте.

Установите и замените импорт

Eyes API в @delta-qa/vision сохраняет имена и смысл Applitools Eyes для Playwright. Требуются Node.js 22 или новее и @playwright/test 1.62 или новее.

Vision SDK сначала доступен в раннем доступе: свяжитесь с нами, чтобы использовать его в своём наборе тестов. Запросить доступ к Vision

ApplitoolsDelta-QA
import { test } from "@applitools/eyes-playwright/fixture";import { test } from "@delta-qa/vision/eyes/fixture";
import type { EyesFixture } from "@applitools/eyes-playwright/fixture";import type { EyesFixture } from "@delta-qa/vision/eyes/fixture";
import { Eyes, Target, … } from "@applitools/eyes-playwright";import { Eyes, Target, … } from "@delta-qa/vision/eyes";

eyesConfig в playwright.config остаётся как есть. С фикстурой в тесте меняется только импорт:

// import { test } from "@applitools/eyes-playwright/fixture";
import { test } from "@delta-qa/vision/eyes/fixture";

test("checkout", async ({ page, eyes }) => {
  await page.goto("https://shop.example/cart");
  await eyes.check("Cart", { fully: true });
}); // opened before the test, closed by the fixture

Задайте переменные окружения

ПеременнаяЧитается для
DELTAQA_API_KEYAPI-ключ вашего рабочего пространства Delta-QA (dqa_…) с ролью «Can edit», созданный в Settings → Workspace → API keys. Сохраните его в секрете вашего CI.
APPLITOOLS_API_KEYЧитается, если DELTAQA_API_KEY не задана: оставьте переменную, но укажите в ней ключ Delta-QA.
DELTAQA_SERVER_URLВаш сервер Delta-QA для установки On-Premise; если переменная не задана — облако Delta-QA. APPLITOOLS_SERVER_URL никогда не читается.
APPLITOOLS_BATCH_IDТестируемая версия — коммит. id пакета, заданный в коде, имеет приоритет.
APPLITOOLS_BRANCHВетка. setBranchName в коде имеет приоритет.
APPLITOOLS_PARENT_BRANCH
APPLITOOLS_BASELINE_BRANCH
Базовая ветка, эталон которой используется, пока у ветки нет своего. APPLITOOLS_BASELINE_BRANCH имеет приоритет над APPLITOOLS_PARENT_BRANCH; код — над обеими.

Формы _NAME переменных ветки (APPLITOOLS_BRANCH_NAME, APPLITOOLS_PARENT_BRANCH_NAME, APPLITOOLS_BASELINE_BRANCH_NAME) тоже читаются. Пустая переменная считается незаданной. Без ключа открытие теста завершается ошибкой, в которой названа переменная, которую нужно задать.

Эти переменные Applitools не читаются и не вызывают предупреждения: APPLITOOLS_SERVER_URL, APPLITOOLS_BATCH_NAME, APPLITOOLS_DONT_CLOSE_BATCHES, APPLITOOLS_SHOW_LOGS.

Настройте CI

SDK не читает ни git, ни переменные вашего CI: строки ниже берут из них ветку, базовую ветку и коммит и записывают их в три переменные Applitools.

GitHub Actions

При push github.head_ref пуст: веткой тогда служит github.ref_name. В pull request github.sha — это merge-коммит, который создаёт GitHub, а не запушенный коммит: head-коммит имеет приоритет.

env:
  APPLITOOLS_BRANCH: ${{ github.head_ref || github.ref_name }}
  APPLITOOLS_PARENT_BRANCH: ${{ github.base_ref || github.event.repository.default_branch }}
  APPLITOOLS_BATCH_ID: ${{ github.event.pull_request.head.sha || github.sha }}

GitLab CI

В пайплайне merge request CI_MERGE_REQUEST_TARGET_BRANCH_NAME — целевая ветка; в пайплайне ветки она пуста.

script:
  - export APPLITOOLS_BRANCH="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-$CI_COMMIT_REF_NAME}"
  - export APPLITOOLS_PARENT_BRANCH="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-$CI_DEFAULT_BRANCH}"
  - export APPLITOOLS_BATCH_ID="$CI_COMMIT_SHA"
  - npx playwright test

Bitbucket Pipelines

BITBUCKET_PR_DESTINATION_BRANCH задаётся только в пайплайне pull request.

script:
  - export APPLITOOLS_BRANCH="$BITBUCKET_BRANCH"
  - export APPLITOOLS_PARENT_BRANCH="$BITBUCKET_PR_DESTINATION_BRANCH"
  - export APPLITOOLS_BATCH_ID="$BITBUCKET_COMMIT"
  - npx playwright test

Azure Pipelines

Переменные System.PullRequest задаются только в сборке pull request, в виде refs/heads/… для Azure Repos. Build.SourceBranchName сохраняет только последний сегмент имени ветки (feature/cart даёт cart), поэтому ветка читается из полного ref.

- script: |
    branch="${SYSTEM_PULLREQUEST_SOURCEBRANCH:-$BUILD_SOURCEBRANCH}"
    base="${SYSTEM_PULLREQUEST_TARGETBRANCH:-}"
    export APPLITOOLS_BRANCH="${branch#refs/heads/}"
    export APPLITOOLS_PARENT_BRANCH="${base#refs/heads/}"
    export APPLITOOLS_BATCH_ID="${SYSTEM_PULLREQUEST_SOURCECOMMITID:-$BUILD_SOURCEVERSION}"
    npx playwright test

Базовая ветка, совпадающая с веткой, не используется: на ветке по умолчанию эти строки не дают базовой ветки.

Закрывайте в teardown, никогда в теле теста

С фикстурой eyes закрывается в teardown теста. Без неё вызывайте eyes.close() в afterEach, а runner.getAllTestResults() — в afterAll.

Никогда не закрывайте в теле теста: ожидание вердикта расходует время теста — по умолчанию 30 секунд в Playwright Test, — а шаг, упавший до close(), оставляет тест открытым. У teardown собственный таймаут.

import { test } from "@playwright/test";
import { Eyes, Target, VisualGridRunner } from "@delta-qa/vision/eyes";

const runner = new VisualGridRunner();
let eyes: Eyes;

test.beforeEach(async ({ page }) => {
  eyes = new Eyes(runner);
  await eyes.open(page, "Shop", test.info().title);
});
test("checkout", async ({ page }) => {
  await page.goto("https://shop.example/cart");
  await eyes.check("Cart", Target.window().fully());
});
test.afterEach(async () => {
  await eyes.close(); // throws DiffsFoundError when a difference awaits a judgment
});
test.afterAll(async () => {
  await runner.getAllTestResults();
});

Каждая настройка Applitools и во что она превращается

Принимается любая настройка Applitools Eyes: набор тестов компилируется и выполняется. Каждая либо применяется Delta-QA, либо принимается без эффекта, с предупреждением. Нескольких вызовов нет.

Применяются

НастройкаВ Delta-QA
appNameПриложение теста; вместе с именем теста оно идентифицирует тест. В eyesConfig, если не задано, — My App, как в фикстуре Applitools.
testNameИмя теста, его ключ: изменённое имя — это новый тест. В eyesConfig это может быть и функция от теста; без него — путь заголовков теста без файла (describe > test), как в фикстуре Applitools.
apiKey
setApiKey
Ключ вместо DELTAQA_API_KEY или APPLITOOLS_API_KEY — ключ Delta-QA. Он никогда не появляется ни в сообщении, ни в логе, ни в ссылке.
branchNameВетка запуска; без неё — APPLITOOLS_BRANCH, затем APPLITOOLS_BRANCH_NAME.
parentBranchName
baselineBranchName
Базовая ветка: baselineBranchName раньше parentBranchName; без них — их переменные в том же порядке.
batchЕго id — тестируемая версия, то есть коммит; без него — APPLITOOLS_BATCH_ID; без обоих — одна версия на процесс (см. отличия ниже).
saveNewTestsСтановятся ли страницы нового теста его эталоном; если не задано — true.
viewportSizeРазмер, который задаётся странице при открытии теста.
browsersInfo
addBrowser(width, height)
Каждый размер — это окружение, для Chrome или без имени браузера. Язык, часовой пояс, тема и плотность экрана берутся из браузера теста.
fully
fully(true)
Вся страница — то, что Delta-QA проверяет в любом случае.
withName
name
Имя проверки.
Target.windowСтраница теста.
Target.region
CheckSettings.region
checkRegion
checkRegionBy
checkRegionByElement
checkElement
checkElementBy
Единственная сравниваемая часть страницы: первый элемент, на который указывает локатор, селектор или хэндл элемента, как в Applitools; побеждает последний заданный регион. Игнорируемые регионы внутри него исключаются.
ignoreRegions
ignoreRegion
ignore
ignores
Каждый элемент, на который указывает регион — локатор, селектор, { selector, type }, хэндл элемента, — исключается из сравнения: каждый элемент локатора, как в Applitools. Также форма { region } и ключ ignoreRegions в объектной форме.
eyesConfig.failTestsOnDiffЧто роняет вердикт, отличный от PASSED, в фикстуре: 'afterEach' роняет тест в его teardown; 'afterAll' роняет воркер после завершения его тестов; false ничего не роняет, но вердикт всё равно ожидается. Без него — 'afterAll', если задана переменная CI, и 'afterEach' в остальных случаях, как это решает код фикстуры Applitools.
eyesConfig.afterAllВызывается после завершения тестов воркера, с результатом каждого.

Вызовы

ВызовВ Delta-QA
open(page, appName, testName, viewportSize?)Тест идентифицируется по приложению и имени: изменённое имя — это новый тест. Размер viewport задаётся странице.
check(name?, Target.window())
checkWindow(tag?)
Проверяет страницу в текущем виде в каждом окружении. Проверка без имени сопоставляется по адресу своей страницы; две проверки с одинаковым именем допускаются. Возвращает MatchResult без вердикта, как check в Applitools: вердикт приходит при закрытии.
close(throwErr = true)Ожидает вердикт: DiffsFoundError при различии, требующем решения, NewTestError при новом тесте, требующем решения (saveNewTests(false)), TestFailedError при различии, признанном багом, или при сбое. Сообщение содержит ссылку на версию в Delta-QA.
closeAsync()
runner.getAllTestResults(throwErr = true)
closeAsync() закрывает без ожидания; runner ждёт каждый вердикт, закрывает оставшийся открытым тест и выбрасывает ошибку для теста, который не прошёл, — ошибка closeAsync() сохраняется для него.
abort()
abortIfNotClosed()
abortAsync()
Закрывает, не дожидаясь вердикта, и ничего не роняет: результаты помечаются как прерванные, без результата; null, если открытого теста нет. Delta-QA всё равно сравнивает запуски, и версия показывает их результат.

Принимаются без эффекта

Настройка, которую Delta-QA не применяет, не роняет тест: тест выполняется без неё. При первом использовании в процессе выдаётся предупреждение Node.js с её именем и кодом DELTAQA_IGNORED_SETTING; последующие использования проходят молча, а node --disable-warning=DELTAQA_IGNORED_SETTING отключает такие предупреждения. Пустое значение — setX(process.env.VARIABLE) вне CI — считается незаданной настройкой и не вызывает предупреждения. Ниже приведены имена в том виде, в каком их выдаёт предупреждение.

Настройки сравнения

Уровни совпадения, регионы по уровню совпадения, плавающие регионы и смещения настраивают сравнение Applitools. Delta-QA сравнивает страницу так, как это сделал бы человеческий глаз, без уровня допуска, который нужно настраивать: каждое различие показывается, и человек оценивает его в Delta-QA.

  • matchLevel
  • defaultMatchSettings
  • enablePatterns
  • ignoreDisplacements
  • ignoreCaret
  • useDom
  • sendDom
  • CheckSettings.matchLevel
  • CheckSettings.layout
  • CheckSettings.exact
  • CheckSettings.strict
  • CheckSettings.content
  • CheckSettings.ignoreColors
  • CheckSettings.dynamic
  • CheckSettings.enablePatterns
  • CheckSettings.ignoreDisplacements
  • CheckSettings.ignoreCaret
  • CheckSettings.ignoreMismatch
  • CheckSettings.useDom
  • CheckSettings.sendDom
  • CheckSettings.layoutRegion
  • CheckSettings.layoutRegions
  • CheckSettings.strictRegion
  • CheckSettings.strictRegions
  • CheckSettings.contentRegion
  • CheckSettings.contentRegions
  • CheckSettings.floating
  • CheckSettings.floatings
  • CheckSettings.floatingRegion
  • CheckSettings.floatingRegions
  • CheckSettings.dynamicRegion
  • CheckSettings.dynamicRegions

Настройки снимка

Склейка, прокрутка, обрезка, ожидания и отладочные снимки определяют снимок Applitools. Delta-QA проверяет всю страницу в том виде, в каком её оставил тест в момент вызова check: чтобы дождаться контента или загрузить ленивую секцию, сделайте это в тесте, до проверки.

  • hideCaret
  • hideScrollbars
  • forceFullPageScreenshot
  • stitchMode
  • stitchOverlap
  • scrollRootElement
  • cut
  • rotation
  • waitBeforeScreenshots
  • waitBeforeCapture
  • matchTimeout
  • saveDebugScreenshots
  • debugScreenshotsPath
  • debugScreenshotsPrefix
  • fully(false)
  • CheckSettings.fully(false)
  • CheckSettings.scrollRootElement
  • CheckSettings.stitchMode
  • CheckSettings.timeout
  • CheckSettings.waitBeforeCapture
  • CheckSettings.lazyLoad
  • CheckSettings.useSystemScreenshot

Браузеры, устройства и окружения

Delta-QA рендерит в Chromium: учитывается размер, переданный в addBrowser, а не названный браузер, поэтому два браузера одного размера — это одно окружение. Устройство из грида Applitools (DeviceName, IosDeviceName, эмуляция, мультиустройства) не добавляет окружения. Язык, часовой пояс, тема и плотность экрана берутся из браузера теста, а метки окружений ничего не меняют. ClassicRunner и VisualGridRunner ведут себя одинаково.

  • addBrowser(chrome-one-version-back)
  • addBrowser(chrome-two-versions-back)
  • addBrowser(firefox)
  • addBrowser(firefox-one-version-back)
  • addBrowser(firefox-two-versions-back)
  • addBrowser(safari)
  • addBrowser(safari-one-version-back)
  • addBrowser(safari-two-versions-back)
  • addBrowser(edgechromium)
  • addBrowser(edgechromium-one-version-back)
  • addBrowser(edgechromium-two-versions-back)
  • addBrowser(edgelegacy)
  • addBrowser(ie)
  • addBrowser(ie10)
  • addBrowser(device)
  • addDeviceEmulation
  • addMultiDeviceTarget
  • mobileOptions
  • captureStatusBar
  • layoutBreakpoints
  • CheckSettings.layoutBreakpoints
  • environmentName
  • envName
  • baselineEnvName
  • deviceInfo
  • hostApp
  • hostAppInfo
  • hostOS
  • hostOSInfo
  • scaleRatio
  • CheckSettings.densityMetrics
  • eyesConfig.type

Грид рендеринга Applitools

Опции рендеринга, хуки, загрузка ресурсов, кеши и параллелизм грида Applitools не имеют аналогов: страница проверяется в том виде, в каком её оставил тест. Скрипт, который вы запускали в хуке, запускается в тесте, до проверки.

  • visualGridOptions
  • CheckSettings.ufgOption
  • CheckSettings.ufgOptions
  • CheckSettings.visualGridOption
  • CheckSettings.visualGridOptions
  • CheckSettings.variationGroupId
  • CheckSettings.hook
  • CheckSettings.beforeRenderScreenshotHook
  • CheckSettings.webHook
  • disableBrowserFetching
  • CheckSettings.disableBrowserFetching
  • disableNMLUrlCache
  • autProxy
  • bypassCSP
  • skipRootHtmlResource
  • concurrentSessions
  • RunnerOptions.testConcurrency
  • RunnerOptions.fetchConcurrency
  • RunnerOptions.removeDuplicateTests

Пакеты, эталоны и результаты

Версия несёт коммит: у неё нет ни имени, ни последовательности, ни свойств, ни уведомлений, и закрывать её не нужно. Эталон меняется, только когда человек оценивает различие в Delta-QA; тест без эталона — «Новый». Проверки сопоставляются по имени, иначе по адресу своей страницы. isDisabled: тест, который должен выполняться без проверки, не открывает Eyes.

  • BatchInfo.name
  • BatchInfo.sequenceName
  • BatchInfo.startedAt
  • BatchInfo.notifyOnCompletion
  • BatchInfo.properties
  • BatchInfo.buildId
  • dontCloseBatches
  • BatchClose
  • properties
  • removeSession
  • saveDiffs
  • saveFailedTests
  • ignoreBaseline
  • displayName
  • sessionType
  • CheckSettings.pageId
  • isDisabled

Git

SDK не читает git: передайте базовую ветку через parentBranchName или baselineBranchName, а коммит — через id пакета или APPLITOOLS_BATCH_ID.

  • compareWithParentBranch
  • ignoreGitMergeBase
  • gitMergeBaseTimestamp
  • latestCommitInfo

Сервер, подключение и логи

Они относятся к серверу Applitools, подключению к нему и его логам. Сервер Delta-QA читается из DELTAQA_SERVER_URL; SDK не пишет логов Applitools и не генерирует событий Applitools.

  • serverUrl
  • proxy
  • agentId
  • httpVersion
  • connectionTimeout
  • Eyes.on
  • Eyes.setLogHandler
  • Eyes.addSessionEventHandler
  • eyesConfig.logConfig
  • RunnerOptions.maskLog

Функции вне Delta-QA

Delta-QA не проверяет доступность, не читает Figma и не имеет проверки на естественном языке; у страницы Playwright нет web view.

  • accessibilityValidation
  • CheckSettings.accessibilityRegion
  • CheckSettings.accessibilityRegions
  • figmaBaselines
  • figmaOptions
  • nlpOptions
  • Target.webview
  • CheckSettings.webview

Регионы без элемента

Delta-QA находит элементы, которые отличаются. У региона, заданного координатами ({ x, y, width, height }, { left, top, width, height }), нет аналога: страница сравнивается без него — целиком, если это Target.region. Зона — это сам элемент, без отступов; regionId именует регион в дашборде Applitools. С Target.frame или Target.shadow страница сравнивается целиком, а регион, заданный затем селектором, роняет проверку с TypeError: зона — это элемент самой страницы.

  • CheckSettings.ignoreRegions(coordinates)
  • Target.region(coordinates)
  • CodedRegion.padding
  • CodedRegion.regionId
  • Target.frame
  • Target.shadow
  • CheckSettings.frame
  • CheckSettings.shadow

Неизвестный ключ в объектной форме конфигурации или проверки вызывает предупреждение со своим именем (CheckSettings.<key> в проверке).

Отсутствуют: что не компилируется

Это не настройки: они возвращают данные, которых у Delta-QA нет, или проверяют изображение, а не страницу. Набор тестов, который их использует, не компилируется — вместо того чтобы получить выдуманное значение.

ОтсутствуетПочему
eyes.locate
eyes.extractText
eyes.extractTextRegions
Они возвращают регионы или текст, которые Applitools считывает со своего снимка.
eyes.checkImage
Target.image
Target.buffer
Target.base64
Target.path
Target.url
Delta-QA проверяет страницы, а не изображения.
eyes.getLogger
eyes.logger
Лог Applitools.
eyes.runВ фикстуре Applitools — её проверка на естественном языке.

Отличия от Applitools

Осознанные решения Delta-QA, о которых стоит знать до первого запуска.

СитуацияDelta-QA
Сопоставление проверки с эталономПо имени проверки, если каждое имя уникально в тесте; иначе по порядку, по имени, а при его отсутствии — по адресу страницы: добавленная или удалённая проверка не сдвигает остальные.
Изменение, принятое на веткеЭталоны не сливаются автоматически из одной ветки в другую. Когда то же различие появляется на другой ветке, Delta-QA предлагает «Already intended on … — apply?».
Принятие различия«Ожидаемо» действует на отмеченные вами ветки.
Нет ни APPLITOOLS_BATCH_ID, ни id пакетаОдна версия на процесс: каждый воркер Playwright Test — отдельный процесс, поэтому несколько воркеров дают несколько версий — и с фикстурой тоже. Задайте в APPLITOOLS_BATCH_ID коммит вашего CI, чтобы получить одну общую версию.
Игнорируемый регион, которому не соответствует ни один элементИсключается, и проверка отправляется без него, как в Applitools, — а предупреждение Node.js с кодом DELTAQA_IGNORED_REGION называет его, один раз на регион и процесс (node --disable-warning=DELTAQA_IGNORED_REGION его отключает). Проверяемый регион, которому ничего не соответствует, роняет проверку с ZoneNotFoundError, как в Applitools.
runner.getAllTestResults() и тест, оставшийся открытымТест закрывается, и выносится его вердикт; Applitools его прерывает.
Фикстура: eyesConfig на верхнем уровне playwright.config и в проектеКонфигурация проекта заменяет верхнеуровневую — так Playwright Test передаёт опцию; test.use добавляет свои ключи к конфигурации проекта. Фикстура Applitools объединяет обе по ключам.
Фикстура: type: 'classic' с browsersInfoКаждый размер — это окружение, как с ClassicRunner вне фикстуры; фикстура Applitools отбрасывает размеры. type вызывает предупреждение.
Фикстура: expect(page).toHaveScreenshot()Собственный метод Playwright Test: expect — тот, что из @playwright/test. Фикстура Applitools превращает его в проверку Eyes.
Тест, оставшийся без проверки 30 минутDelta-QA закрывает его; затем close() читает его вердикт.

Данные, которые вы отправляете

То, что отправляет SDK, — страницы, которые проверяют ваши тесты, и файлы, которые они используют, — служит только для их сравнения. Ответственность за тестирование на персональных данных production лежит на вас: запускайте набор тестов на тестовых данных.

Vision SDK: проверки Delta-QA в ваших тестах Playwright

Applitools, Applitools Eyes и Eyes являются товарными знаками Applitools Ltd. Delta-QA не связана с Applitools, не одобрена и не спонсируется ею.

Запустите свой набор тестов Eyes в Delta-QA

Чтобы использовать Vision, свяжитесь с нами: сначала он доступен в раннем доступе. Расскажите, какие тесты вы хотите проверять, и мы откроем вам доступ.