Как имитировать камеру для сквозного теста, требующего захвата видеопотока.
Недавно мы добавили функцию чтения QR-кода в NNS-dapp, децентрализованное приложение, которое позволяет взаимодействовать с сетевой нервной системой Интернет-компьютера. Чтобы обеспечить его ремонтопригодность, мы создали сквозной тест с использованием Playwright для имитации захвата видео для целей автоматизации. Поскольку для этого нам пришлось собирать информацию из разных источников, я решил поделиться своими мыслями в одном сообщении в блоге, чтобы помочь другим, которые могут столкнуться с похожими проблемами.
Демо
Вот как работает один из наших тестов: он открывает модальное окно, которое использует считыватель QR-кода для чтения и декодирования видеопотока. Затем декодированный результат анализируется в текстовом поле и в конечном итоге проверяется с помощью сравнения скриншотов на основе пикселей.
Ограничения
Прежде чем двигаться дальше, я хотел бы выделить различные технические ограничения, необходимые для настройки такого теста. Обратите внимание, что на момент написания этой статьи 30 апреля 2023 года драматург мог измениться с тех пор. Поэтому всегда рекомендуется сначала перепроверить документацию.
только хром
Невозможно издеваться над камерой в Safari. Как указано в этой проблеме GitHub, можно имитировать захват видео в Firefox, но невозможно предоставить конкретный видеофайл. Поэтому можно с уверенностью предположить, что издевательство над камерой, как мы собирались сделать с Playwright, работает только в Google Chrome.
ЮВ4МПЕГ2
Основываясь на моих экспериментах, оказалось, что единственный формат видео, который Chrome может использовать для передачи тестового файла в getUserMedia()
вместо ввода с камеры в реальном времени, — это формат файла .y4m.
Этот формат файла предназначен для хранения несжатых кадров, поэтому также стоит отметить, что видео может быть довольно большого размера.
Конфигурация драматурга
В конфигурации Playwright особо нечего настраивать, если только вы не решите использовать Chrome в качестве движка для своих тестов по всему миру. В нашем случае мы сделали это в нашей библиотеке набора пользовательского интерфейса с открытым исходным кодом под названием gix-components, которая создана с помощью SvelteKit, и вот как мы настроили ее в нашем файле playwright.config.ts
.
import type { PlaywrightTestConfig } from "@playwright/test"; import { devices } from "@playwright/test"; const config: PlaywrightTestConfig = { webServer: { command: "npm run build && npm run preview", port: 4173, }, testDir: "e2e", testMatch: ["**/*.e2e.ts"], use: { testIdAttribute: "data-tid", trace: "on", }, projects: [ { name: "Google Chrome", use: { ...devices["Desktop Chrome"], channel: "chrome" }, }, ], }; export default config;
Тест
Чтобы подделать захват видео для сквозного теста, вам нужно передать Chromium три аргумента во время запуска.
--use-fake-ui-for-media-stream
: устраняет необходимость предоставления разрешений для камеры и микрофона во время теста.--use-fake-device-for-media-stream
: вводит тестовый шаблон вgetUserMedia()
вместо использования ввода с камеры в реальном времени.--use-file-for-fake-video-capture=./your-file.y4m
: путь к видеофайлу, который следует использовать для имитации видеопотока с камеры.
Кроме этих аргументов, нет необходимости устанавливать что-либо еще. Вот пример простого теста, использующего этот подход.
test("Read QR code with camera", async () => { const browser = await chromium.launch({ args: [ "--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream", "--use-file-for-fake-video-capture=./samples/qrcode.y4m", ], }); const context = await browser.newContext({ permissions: ["camera"], }); const page = await context.newPage(); // Navigate await page.goto("/"); // e.g. open the element that uses the QR code reader const modal = page.getByTestId("qr-code-modal"); await modal.click(); // Optimistically wait process to end await page.waitForTimeout(2000); await expect(page).toHaveScreenshot(); });
Стоит отметить, что явный запрос разрешения на использование доступа к камере с помощью BrowserContext Playwright не является абсолютно необходимым, поскольку мы уже предоставляем такое разрешение с помощью аргумента запуска. Никогда нельзя быть слишком уверенным, не так ли 😉?
Спасибо за чтение! Подписывайтесь на меня в Твиттере, чтобы не пропустить больше интересного контента по программированию.