•20 min read

Kiểm thử hồi quy hình ảnh Playwright ở quy mô lớn: Docker Baselines, Pixelmatch & Flaky CI Shields

Kiểm thử hồi quy hình ảnh Playwright ở quy mô lớn: Docker Baselines, Pixelmatch & Flaky CI Shields

Kiểm thử hồi quy hình ảnh (VRT) là một thành phần quan trọng của quy trình CI/CD mạnh mẽ, đảm bảo tính nhất quán của giao diện người dùng (UI) giữa các lần triển khai. Tuy nhiên, việc triển khai VRT ở quy mô lớn, đặc biệt trong một monorepo như Turborepo, đặt ra những thách thức riêng: sự không nhất quán về môi trường, nội dung động và tính không ổn định vốn có của việc so sánh cấp độ pixel. Hướng dẫn này trình bày chi tiết một phương pháp tiếp cận cấp độ sản xuất sử dụng Playwright, Docker và pixelmatch để giảm thiểu các vấn đề này, cung cấp một hệ thống VRT ổn định và đáng tin cậy.

Audio Briefing
0:00 / 0:00

Vấn đề cơ bản: Tính xác định của môi trường

Một thách thức cơ bản trong VRT là thiết lập một đường cơ sở nhất quán. Ảnh chụp màn hình được chụp trên máy macOS của nhà phát triển chắc chắn sẽ khác với ảnh chụp trong môi trường CI dựa trên Linux do sự khác biệt trong kết xuất phông chữ, khử răng cưa và thậm chí cả tăng tốc GPU. Những khác biệt này dẫn đến các lỗi dương tính giả, làm xói mòn niềm tin vào hệ thống VRT.

Giải pháp là tính xác định của môi trường: đảm bảo ảnh chụp màn hình đường cơ sở được tạo ra trong chính xác cùng một môi trường với quy trình CI/CD. Docker cung cấp sự cô lập này.

Tạo đường cơ sở bằng Docker

Chúng ta sẽ sử dụng một ảnh Docker phản ánh môi trường CI của chúng ta để tạo và cập nhật các đường cơ sở. Ảnh này nên bao gồm các phụ thuộc trình duyệt của Playwright.

Đầu tiên, định nghĩa một Dockerfile cho môi trường VRT của bạn:

# Dockerfile for Playwright VRT baseline generation and CI execution
FROM mcr.microsoft.com/playwright/chromium:v1.45.0-jammy

# Set working directory
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Copy package.json and pnpm-lock.yaml for dependency installation
COPY package.json pnpm-lock.yaml ./
# If using Turborepo, copy workspace root package.json and pnpm-workspace.yaml
# COPY pnpm-workspace.yaml ./
# COPY apps/web/package.json apps/web/
# COPY packages/ui/package.json packages/ui/

# Install dependencies
# For Turborepo, you might need to install dependencies at the root
# RUN pnpm install --frozen-lockfile
# Or, if installing within a specific app/package:
# RUN pnpm install --frozen-lockfile --filter=@your-org/web

# Copy the rest of the application code
COPY . .

# Expose any ports if your application needs to run inside the container
# For VRT, typically the app runs externally, and Playwright connects to it.
# EXPOSE 3000

# Define a default command (optional, can be overridden)
CMD ["pnpm", "test:visual"]

Xây dựng ảnh này:

docker build -t playwright-vrt-env .

Bây giờ, để tạo hoặc cập nhật các đường cơ sở, hãy chạy Playwright bên trong container này:

# Example: Running Playwright tests to update baselines
# Assuming your Playwright config points to 'test-results' for diffs
# and 'screenshots' for baselines.
docker run --rm -v "$(pwd):/app" playwright-vrt-env pnpm playwright test --update-snapshots

-v "$(pwd):/app" gắn thư mục dự án cục bộ của bạn vào container, cho phép Playwright đọc/ghi các đường cơ sở trực tiếp vào hệ thống tệp máy chủ của bạn. Điều này đảm bảo các đường cơ sở được commit vào kho Git của bạn.

Advertisement

Cấu hình Playwright cho VRT

expect(page).toHaveScreenshot() của Playwright là khẳng định cốt lõi cho VRT. Cấu hình đúng đắn là rất quan trọng.

playwright.config.ts

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
import path from 'path';

// Determine if running in CI
const isCI = !!process.env.CI;

export default defineConfig({
  testDir: './e2e', // Directory where your visual tests reside
  outputDir: './test-results', // Directory for test artifacts (screenshots, videos, traces)
  snapshotDir: './e2e/snapshots', // Directory for baseline screenshots

  fullyParallel: true, // Run tests in parallel
  forbidOnly: isCI, // Forbid .only in CI
  retries: isCI ? 2 : 0, // Retry tests in CI to mitigate flakiness
  workers: process.env.CI ? 1 : undefined, // Limit workers in CI for stability, or use all available

  reporter: 'html', // Use HTML reporter for easy review

  use: {
    baseURL: 'http://localhost:3000', // Base URL of your application under test
    trace: 'on-first-retry', // Capture trace on first retry failure
    screenshot: 'only-on-failure', // Only capture screenshots on failure
    video: 'on-first-retry', // Capture video on first retry failure

    // Playwright's default browser context options
    // Ensure consistent viewport for screenshots
    viewport: { width: 1280, height: 720 },

    // Emulate a consistent color scheme
    colorScheme: 'light',

    // Use a consistent timezone to prevent date/time rendering differences
    timezoneId: 'America/Los_Angeles',

    // Use a consistent locale
    locale: 'en-US',

    // Use a consistent user agent for consistent font rendering
    userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',

    // Playwright's default browser options
    // headless: true, // Always run headless in CI
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    // Add other browsers if needed, but for VRT, consistency is key.
    // Often, one browser (e.g., Chromium) is sufficient for visual baselines.
  ],

  // Web server to run before tests.
  // This assumes your app is a Next.js app running on port 3000.
  webServer: {
    command: 'pnpm --filter=@your-org/web dev', // Command to start your web app
    url: 'http://localhost:3000',
    reuseExistingServer: !isCI, // Reuse server locally, but start fresh in CI
    timeout: 60 * 1000, // 60 seconds timeout for server to start
  },
});

Ví dụ kiểm thử hình ảnh

// e2e/home.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Home Page Visual Regression', () => {
  test('should match the home page screenshot', async ({ page }) => {
    await page.goto('/');

    // Mask dynamic elements like timestamps, user avatars, or ads
    // This prevents false positives due to content changes.
    await page.locator('.dynamic-timestamp').evaluate(node => node.style.visibility = 'hidden');
    await page.locator('.user-avatar').evaluate(node => node.style.visibility = 'hidden');

    // Wait for fonts to load, if applicable, to prevent FOUT/FOIT issues
    await page.waitForLoadState('networkidle');

    // Take a full page screenshot
    await expect(page).toHaveScreenshot('home-page.png', {
      fullPage: true,
      maxDiffPixelRatio: 0.01, // Allow 1% of pixels to differ
      threshold: 0.1, // Pixelmatch threshold (0-1, lower is stricter)
      // You can also specify a custom diff algorithm if needed,
      // but Playwright's default (based on pixelmatch) is usually sufficient.
      // diffPixels: 100, // Max number of differing pixels
    });
  });

  test('should match the login form screenshot', async ({ page }) => {
    await page.goto('/login');

    // Mask the input field for password, as its content might be dynamic (e.g., autofill)
    await page.locator('input[type="password"]').evaluate(node => node.style.visibility = 'hidden');

    await page.waitForLoadState('networkidle');

    await expect(page).toHaveScreenshot('login-form.png', {
      maxDiffPixelRatio: 0.02, // Slightly more lenient for forms
      threshold: 0.05,
      // You can also specify a specific region to screenshot
      // clip: { x: 0, y: 0, width: 800, height: 600 },
    });
  });
});

Che giấu các phần tử động

Nội dung động (dấu thời gian, nội dung do người dùng tạo, quảng cáo, hoạt ảnh) là nguồn chính gây ra sự không ổn định của VRT. Playwright cung cấp một số chiến lược:

  1. locator.evaluate(node => node.style.visibility = 'hidden'): Ẩn phần tử, làm cho nó trong suốt và không ảnh hưởng đến bố cục.
  2. locator.evaluate(node => node.remove()): Xóa hoàn toàn phần tử khỏi DOM. Sử dụng cẩn thận vì nó có thể ảnh hưởng đến bố cục.
  3. mask: [page.locator('.dynamic-element')]: Tùy chọn che giấu tích hợp của Playwright trong toHaveScreenshot. Đây thường là cách tiếp cận sạch nhất.
// Using mask option
await expect(page).toHaveScreenshot('home-page.png', {
  mask: [
    page.locator('.dynamic-timestamp'),
    page.locator('.user-avatar'),
  ],
  maxDiffPixelRatio: 0.01,
});

Ngưỡng pixelmatch

Playwright sử dụng pixelmatch nội bộ để so sánh. Tùy chọn threshold (0-1) trong toHaveScreenshot kiểm soát độ nhạy. Giá trị thấp hơn có nghĩa là khớp pixel nghiêm ngặt hơn. maxDiffPixelRatio (0-1) hoặc maxDiffPixels (số) xác định sự khác biệt tối đa cho phép trước khi một kiểm thử thất bại.

  • threshold: Độ nhạy của so sánh pixel. 0.1 là một điểm khởi đầu phổ biến.
  • maxDiffPixelRatio: Phần trăm pixel tối đa có thể khác nhau. 0.01 có nghĩa là 1% pixel có thể khác nhau.
  • maxDiffPixels: Số lượng pixel tuyệt đối tối đa có thể khác nhau.

Thử nghiệm với các giá trị này. Bắt đầu nghiêm ngặt và chỉ nới lỏng chúng nếu được biện minh bởi các biến thể hình ảnh chấp nhận được.

Tích hợp Turborepo

Trong một monorepo Turborepo, định nghĩa các kiểm thử Playwright của bạn trong một không gian làm việc apps/e2e hoặc packages/e2e chuyên dụng.

Các script package.json (root)

// package.json (root)
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "scripts": {
    "test:visual": "pnpm --filter=@your-org/e2e test",
    "test:visual:update": "pnpm --filter=@your-org/e2e test --update-snapshots"
  }
}

apps/e2e/package.json

// apps/e2e/package.json
{
  "name": "@your-org/e2e",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "test": "playwright test",
    "test:ci": "playwright test --reporter=github --forbid-only --retries=2"
  },
  "devDependencies": {
    "@playwright/test": "^1.45.0",
    "@types/node": "^20.14.9"
  }
}

Quy trình làm việc CI/CD của GitHub Actions

Quy trình CI điều phối việc thực thi VRT và quản lý tạo phẩm.

# .github/workflows/visual-regression.yml
name: Visual Regression Tests

on:
  pull_request:
    branches:
      - main
  push:
    branches:
      - main

jobs:
  visual-regression:
    runs-on: ubuntu-latest
    container:
      # Use the same Docker image as for baseline generation
      image: mcr.microsoft.com/playwright/chromium:v1.45.0-jammy
      options: --user 0:0 # Run as root inside container for permissions

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup pnpm
        uses: pnpm/action-setup@v3
        with:
          version: 8
          run_install: false # We'll run install manually in the container

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "PNPM_CACHE_DIR=$(pnpm store path)" >> $GITHUB_ENV

      - name: Cache pnpm dependencies
        uses: actions/cache@v4
        with:
          path: ${{ env.PNPM_CACHE_DIR }}
          key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build application (if necessary)
        # Replace with your actual build command for the app under test
        run: pnpm --filter=@your-org/web build

      - name: Run Playwright Visual Regression Tests
        run: pnpm --filter=@your-org/e2e test:ci

      - name: Upload Playwright Test Report
        if: always() # Upload even if tests fail
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

      - name: Upload Playwright Test Results (screenshots, videos, traces)
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-test-results
          path: test-results/
          retention-days: 30

Quy trình làm việc này:

  1. Sử dụng ảnh Docker mcr.microsoft.com/playwright/chromium, đảm bảo tính nhất quán của môi trường.
  2. Lưu trữ các phụ thuộc pnpm để chạy nhanh hơn.
  3. Xây dựng ứng dụng.
  4. Thực thi các kiểm thử Playwright.
  5. Tải lên báo cáo HTML và bất kỳ hình ảnh/video khác biệt nào được tạo ra dưới dạng tạo phẩm. Các tạo phẩm này rất quan trọng để xem xét các lỗi.
Advertisement

Những điều cần lưu ý và khắc phục sự cố trong sản xuất

1. Sự khác biệt về kết xuất phông chữ (Dương tính giả)

Triệu chứng: VRT liên tục thất bại trong CI nhưng vượt qua cục bộ, với sự khác biệt cho thấy các biến thể phông chữ tinh tế. Nguyên nhân: Các hệ điều hành khác nhau (macOS so với Linux) và thậm chí các phiên bản/bản dựng trình duyệt khác nhau kết xuất phông chữ khác nhau do sự khác biệt trong gợi ý phông chữ, thuật toán khử răng cưa và các phông chữ hệ thống có sẵn. Khắc phục:

  • Đường cơ sở bằng Docker (Khắc phục chính): Tạo và cập nhật tất cả các đường cơ sở trong cùng một môi trường container Docker chạy trong CI. Đây là giải pháp mạnh mẽ nhất.
  • Ngăn xếp phông chữ nhất quán: Đảm bảo CSS của bạn sử dụng một ngăn xếp phông chữ nhất quán, ưu tiên các phông chữ web (ví dụ: Google Fonts) được tải nhất quán, hoặc các phông chữ hệ thống có sẵn rộng rãi và kết xuất tương tự trên các nền tảng (ví dụ: system-ui).
  • font-display: optional: Đối với phông chữ web, hãy cân nhắc font-display: optional để ngăn chặn sự dịch chuyển bố cục (FOIT/FOUT) có thể gây ra sự khác biệt hình ảnh nếu phông chữ tải vào các thời điểm khác nhau.
  • page.waitForLoadState('networkidle'): Đảm bảo tất cả các yêu cầu mạng, bao gồm các tệp phông chữ, đã hoàn tất trước khi chụp ảnh màn hình.

2. Sự không ổn định của nội dung động

Triệu chứng: VRT thất bại không liên tục do thay đổi dấu thời gian, hình đại diện người dùng, biểu ngữ quảng cáo hoặc các thành phần dựa trên dữ liệu. Nguyên nhân: Các phần tử UI vốn dĩ là động và không có nghĩa là phải nhất quán đến từng pixel. Khắc phục:

  • Che giấu: Sử dụng mask: [locator] trong toHaveScreenshot để bỏ qua các phần tử cụ thể trong quá trình so sánh.
  • Ẩn/Xóa: locator.evaluate(node => node.style.visibility = 'hidden') hoặc node.remove() để che giấu mạnh mẽ hơn.
  • Giả lập dữ liệu: Đối với các thành phần dựa trên dữ liệu, giả lập các phản hồi API để đảm bảo dữ liệu nhất quán được kết xuất trong quá trình kiểm thử. page.route() của Playwright rất tuyệt vời cho việc này.
// Example of mocking API response
await page.route('**/api/users/*', async route => {
  await route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify({ name: 'Test User', avatar: 'mock-avatar.png' }),
  });
});
await page.goto('/profile');
await expect(page).toHaveScreenshot('profile-page.png');

3. Dịch chuyển bố cục / Điều kiện tranh chấp

Triệu chứng: Ảnh chụp màn hình hiển thị các phần tử ở các vị trí hơi khác nhau, hoặc nội dung xuất hiện được tải một phần. Nguyên nhân: Các hoạt động không đồng bộ (tải hình ảnh, thực thi JavaScript, hoạt ảnh) hoàn thành vào các thời điểm khác nhau, dẫn đến trạng thái DOM không ổn định khi ảnh chụp màn hình được chụp. Khắc phục:

  • page.waitForLoadState('networkidle'): Chờ cho đến khi không còn quá 0-2 kết nối mạng trong ít nhất 500 ms.
  • page.waitForSelector(selector, { state: 'visible' }): Chờ rõ ràng cho các phần tử quan trọng hiển thị.
  • page.waitForTimeout(ms): Một phương sách cuối cùng, nhưng đôi khi cần thiết cho các hoạt ảnh hoặc chuyển đổi phức tạp. Sử dụng một cách tiết kiệm.
  • Tắt hoạt ảnh: Trong môi trường kiểm thử của ứng dụng, tắt các chuyển đổi và hoạt ảnh CSS.
/* In your app's test CSS or a global style */
body.test-env * {
  transition: none !important;
  animation: none !important;
}

4. Tạo phẩm khác biệt lớn & Giới hạn lưu trữ CI

Triệu chứng: Các lần chạy GitHub Actions thất bại do vượt quá giới hạn lưu trữ tạo phẩm, hoặc các khác biệt quá lớn để xem xét dễ dàng. Nguyên nhân: Playwright tạo ảnh chụp màn hình toàn trang, hình ảnh khác biệt và có thể cả video cho mỗi lần thất bại. Khắc phục:

  • screenshot: 'only-on-failure': Cấu hình Playwright chỉ chụp ảnh màn hình khi một kiểm thử thất bại.
  • maxDiffPixelRatio / threshold: Điều chỉnh các giá trị này. Mức dung sai cao hơn một chút có thể giảm số lượng khác biệt "dương tính giả", do đó giảm việc tạo tạo phẩm.
  • Ảnh chụp màn hình có mục tiêu: Thay vì fullPage: true, chụp ảnh màn hình các thành phần hoặc vùng cụ thể bằng cách sử dụng clip hoặc bằng cách nhắm mục tiêu một locator.
  • Giữ lại tạo phẩm: Đặt retention-days cho upload-artifact thành một giá trị hợp lý (ví dụ: 7-30 ngày) để tự động cắt bỏ các tạo phẩm cũ.

So sánh kiến trúc: Tạo đường cơ sở

Tính năngĐường cơ sở cục bộ (Máy của nhà phát triển)Đường cơ sở bằng Docker (CI/Môi trường chuyên dụng)
Tính nhất quánThấp (Sự khác biệt về hệ điều hành, trình duyệt, kết xuất phông chữ)Cao (Xác định về môi trường)
Độ phức tạp thiết lậpThấp (Chỉ cần chạy playwright test --update-snapshots)Trung bình (Dockerfile, tích hợp CI)
Độ tin cậyThấp (Thường xuyên dương tính giả)Cao (Giảm thiểu sự khác biệt về môi trường)
Bảo trìCao (Cập nhật đường cơ sở thường xuyên do sự trôi dạt môi trường)Thấp (Đường cơ sở ổn định sau khi được tạo trong môi trường mục tiêu)
Khả năng mở rộngKém (Máy của nhà phát triển khác nhau)Tốt (Nhất quán trên tất cả các tác nhân CI)
Được khuyến nghị choCác dự án nhỏ, cá nhân; khám phá ban đầuCác ứng dụng cấp độ sản xuất, monorepo, nhóm

Các câu hỏi thường gặp

Q1: Làm thế nào để xử lý các thiết kế đáp ứng với VRT?

A1: Tạo các dự án Playwright hoặc tệp kiểm thử riêng biệt cho các khung nhìn khác nhau. Trong playwright.config.ts, định nghĩa nhiều dự án với các cài đặt viewport khác nhau:

// playwright.config.ts
projects: [
  {
    name: 'chromium-desktop',
    use: { ...devices['Desktop Chrome'], viewport: { width: 1280, height: 720 } },
  },
  {
    name: 'chromium-mobile',
    use: { ...devices['Pixel 5'], viewport: { width: 390, height: 844 } }, // Example mobile viewport
  },
],

Sau đó, chạy playwright test --project=chromium-desktop hoặc playwright test --project=chromium-mobile.

Q2: Các kiểm thử VRT của tôi vẫn không ổn định ngay cả với Docker và che giấu. Tôi có thể kiểm tra thêm điều gì?

A2:

  1. Độ trễ mạng: Đảm bảo ứng dụng đang được kiểm thử đã được tải hoàn toàn. Sử dụng page.waitForLoadState('networkidle') và các lệnh gọi page.waitForSelector() cụ thể cho các phần tử quan trọng.
  2. Hoạt ảnh/Chuyển đổi: Tắt rõ ràng tất cả các hoạt ảnh và chuyển đổi CSS trong môi trường kiểm thử của bạn. Ngay cả các hoạt ảnh tinh tế cũng có thể gây ra sự dịch chuyển pixel.
  3. Các script của bên thứ ba: Nếu ứng dụng của bạn tải các script của bên thứ ba (phân tích, quảng cáo, tiện ích trò chuyện), chúng có thể đưa vào các phần tử không xác định. Cân nhắc chặn chúng trong quá trình VRT bằng cách sử dụng page.route('**/*.js', route => route.abort()) cho các miền đã biết, hoặc giả lập hành vi của chúng.
  4. Phiên bản trình duyệt: Đảm bảo phiên bản trình duyệt Playwright trong ảnh Docker của bạn khớp với phiên bản được Playwright sử dụng cục bộ (nếu bạn vẫn đang gỡ lỗi cục bộ). Các ảnh Docker của Playwright được gắn với các phiên bản trình duyệt cụ thể.

Q3: Làm thế nào để xem xét các khác biệt hình ảnh một cách hiệu quả trong CI?

A3:

  1. Tạo phẩm GitHub Actions: Bước upload-artifact trong quy trình làm việc CI làm cho các thư mục playwright-report và test-results có sẵn để tải xuống.
  2. Báo cáo HTML của Playwright: Tải xuống tạo phẩm playwright-report. Giải nén nó và mở index.html trong trình duyệt của bạn. Báo cáo này hiển thị rõ ràng các hình ảnh đường cơ sở, thực tế và khác biệt cạnh nhau.
  3. Các công cụ VRT chuyên dụng: Đối với các dự án rất lớn, hãy cân nhắc tích hợp với các nền tảng VRT chuyên dụng (ví dụ: Chromatic, Percy, Applitools). Các công cụ này cung cấp các thuật toán khác biệt nâng cao, giao diện người dùng để xem xét các thay đổi và quy trình phê duyệt. Tuy nhiên, chúng làm tăng chi phí và độ phức tạp.

Q4: Tôi có nên chạy VRT trên mọi yêu cầu kéo (pull request) không?

A4: Đối với các ứng dụng quan trọng, có. VRT trên mọi PR cung cấp phản hồi tức thì về các thay đổi hình ảnh không mong muốn. Đối với các monorepo rất lớn hoặc các dự án có thời gian xây dựng dài, bạn có thể cân nhắc:

  • VRT chọn lọc: Chỉ chạy VRT cho các thay đổi trong các gói hoặc ứng dụng liên quan đến UI cụ thể. dependsOn và outputs của Turborepo có thể giúp tối ưu hóa điều này.
  • VRT theo lịch trình: Chạy một bộ VRT đầy đủ hàng đêm hoặc theo lịch trình, ngoài một bộ nhẹ hơn trên các PR.
  • VRT môi trường staging: Chạy VRT chống lại một môi trường staging đã triển khai sau khi xây dựng thành công, thay vì chống lại một máy chủ dev được khởi động cục bộ trong CI. Điều này kiểm thử tạo phẩm đã triển khai thực tế.

Q5: Tác động của maxDiffPixelRatio so với threshold là gì?

A5:

  • threshold (Độ nhạy của Pixelmatch): Giá trị này (0-1) xác định mức độ khác biệt của hai pixel để được coi là một "khác biệt". Một threshold thấp hơn có nghĩa là ngay cả những khác biệt màu sắc rất tinh tế cũng sẽ được gắn cờ. Nó liên quan đến chất lượng của sự khác biệt.
  • maxDiffPixelRatio (Dung sai khác biệt tổng thể): Giá trị này (0-1) đại diện cho phần trăm pixel tối đa trong toàn bộ hình ảnh có thể khác nhau (dựa trên độ nhạy threshold) trước khi kiểm thử thất bại. Nó liên quan đến số lượng của sự khác biệt.

Bạn thường điều chỉnh threshold để bỏ qua các thay đổi màu sắc không thể nhận thấy (ví dụ: 0.05 đến 0.1) và maxDiffPixelRatio để cho phép các biến thể bố cục nhỏ, chấp nhận được hoặc các phần tử động nhỏ, không thể tránh khỏi mà không thể che giấu (ví dụ: 0.001 đến 0.02). Bắt đầu với các giá trị nghiêm ngặt và tăng chúng dần dần nếu bạn gặp phải các khác biệt chấp nhận được gây ra lỗi.

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement