Как имитировать камеру для сквозного теста, требующего захвата видеопотока.

Недавно мы добавили функцию чтения 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 не является абсолютно необходимым, поскольку мы уже предоставляем такое разрешение с помощью аргумента запуска. Никогда нельзя быть слишком уверенным, не так ли 😉?

Спасибо за чтение! Подписывайтесь на меня в Твиттере, чтобы не пропустить больше интересного контента по программированию.