圖片比較(視覺回歸測試)服務
有關使用 WebdriverIO 進行視覺測試的文件,請參閱文件。這個專案包含使用 WebdriverIO 執行視覺測試的所有相關模組。在 ./packages
目錄中,您會找到
@wdio/visual-testing
:用於整合視覺測試的 WebdriverIO 服務webdriver-image-comparison
:一個圖片比較模組,可用於支援 WebDriver 通訊協定的不同 NodeJS 測試自動化框架
Storybook 執行器 (BETA)
點擊以了解更多關於 Storybook 執行器 BETA 的文件
Storybook 執行器仍處於 BETA 階段,文件稍後將移至WebdriverIO 文件頁面。
此模組現在透過新的視覺執行器支援 Storybook。此執行器會自動掃描本地/遠端 Storybook 執行個體,並建立每個元件的元素螢幕截圖。這可以透過新增
export const config: WebdriverIO.Config = {
// ...
services: ["visual"],
// ....
};
至您的 services
並透過命令列執行 npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook
來完成。它將使用 Chrome 無頭模式作為預設瀏覽器。
[!NOTE]
- 大多數視覺測試選項也適用於 Storybook 執行器,請參閱WebdriverIO 文件。
- Storybook 執行器將覆蓋您的所有功能,並且只能在它支援的瀏覽器上執行,請參閱
--browsers
。- Storybook 執行器不支援使用多重遠端功能的現有設定,並且會擲回錯誤。
- Storybook 執行器僅支援桌面 Web,不支援行動 Web。
Storybook 執行器服務選項
服務選項可以這樣提供
export const config: WebdriverIO.Config = {
// ...
services: [
[
'visual',
{
// Some default options
baselineFolder: join(process.cwd(), './__snapshots__/'),
debug: true,
// The storybook options, see cli options for the description
storybook: {
clip: false,
clipSelector: ''#some-id,
numShards: 4,
// `skipStories` can be a string ('example-button--secondary'),
// an array (['example-button--secondary', 'example-button--small'])
// or a regex which needs to be provided as as string ("/.*button.*/gm")
skipStories: ['example-button--secondary', 'example-button--small'],
url: 'https://www.bbc.co.uk/iplayer/storybook/',
version: 6,
},
},
],
],
// ....
}
Storybook 執行器 CLI 選項
--browsers
- 類型:
string
- 強制: 否
- 預設:
chrome
,您可以從chrome|firefox|edge|safari
中選擇 - 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --browsers=chrome,firefox,edge,safari
- 注意: 僅透過 CLI 提供
它將使用提供的瀏覽器來擷取元件螢幕截圖
[!NOTE] 請確保您已在本機上安裝要執行的瀏覽器
--clip
- 類型:
boolean
- 強制: 否
- 預設:
true
- 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clip=false
停用時,它將建立視窗螢幕截圖。啟用時,它將根據 --clipSelector
建立元素螢幕截圖,這將減少元件螢幕截圖周圍的空白區域並減少螢幕截圖大小。
--clipSelector
- 類型:
string
- 強制: 否
- 預設: Storybook V7 為
#storybook-root > :first-child
,Storybook V6 為#root > :first-child:not(script):not(style)
,另請參閱--version
- 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clipSelector="#some-id"
這是將用來
- 選取要擷取螢幕截圖的元素的選取器
- 用於等待元素在擷取螢幕截圖之前可見
--devices
- 類型:
string
- 強制: 否
- 預設: 您可以從
deviceDescriptors.ts
中選擇 - 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --devices="iPhone 14 Pro Max","Pixel 3 XL"
- 注意: 僅透過 CLI 提供
它將使用符合 deviceDescriptors.ts
的所提供裝置來擷取元件螢幕截圖
[!NOTE]
- 如果您遺失裝置設定,請隨時提交功能要求
- 這僅適用於 Chrome
- 如果您提供
--devices
,則所有 Chrome 執行個體都將在行動裝置模擬模式下執行- 如果您還提供其他瀏覽器,例如
--devices --browsers=firefox,safari,edge
,它將自動在行動裝置模擬模式下新增 Chrome- Storybook 執行器預設會建立元素快照,如果您想查看完整的行動裝置模擬螢幕截圖,請透過命令列提供
--clip=false
- 例如,檔案名稱看起來會像
__snapshots__/example/button/desktop_chrome/example-button--large-local-chrome-iPhone-14-Pro-Max-430x932-dpr-3.png
- 來源: 使用行動裝置模擬在桌面上測試行動網站可能很有用,但測試人員應該注意許多細微的差異,例如
- 完全不同的 GPU,這可能會導致效能產生重大變化;
- 不會模擬行動裝置 UI(尤其是隱藏的 URL 列會影響頁面高度);
- 不支援消除歧義快顯視窗(您可以在其中選取幾個觸控目標之一);
- 許多硬體 API(例如,orientationchange 事件)都不可用。
--headless
- 類型:
boolean
- 強制: 否
- 預設:
true
- 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --headless=false
- 注意: 僅透過 CLI 提供
這將預設在無頭模式下執行測試(當瀏覽器支援時)或可以停用
--numShards
- 類型:
number
- 強制: 否
- 預設:
true
- 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --numShards=10
這將是將用於執行故事的平行執行個體數量。這將受限於您的 wdio.conf
檔案中的 maxInstances
。
[!IMPORTANT] 在
headless
模式下執行時,請勿將數字增加到 20 以上,以防止因資源限制而導致不穩定
--skipStories
- 類型:
string|regex
- 強制: 否
- 預設: null
- 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --skipStories="/.*button.*/gm"
這可以是
- 字串 (
example-button--secondary,example-button--small
) - 或正規表示式 (
"/.*button.*/gm"
)
以跳過某些故事。使用故事 URL 中可以找到的故事的 id
。例如,此 URL https://#:6006/?path=/story/example-page--logged-out
中的 id
是 example-page--logged-out
--url
- 類型:
string
- 強制: 否
- 預設:
http://127.0.0.1:6006
- 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --url="https://example.com"
您的 Storybook 執行個體所在的 URL。
--version
- 類型:
number
- 強制: 否
- 預設值 7
- 範例:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --version=6
這是 Storybook 的版本,預設為 7
。這用於判斷是否需要使用 V6 的 clipSelector
。
Storybook 互動測試
Storybook 互動測試允許您使用 WDIO 命令創建自訂腳本,與您的組件互動,使其進入特定狀態。例如,請參考以下程式碼片段
import { browser, expect } from "@wdio/globals";
describe("Storybook Interaction", () => {
it("should create screenshots for the logged in state when it logs out", async () => {
const componentId = "example-page--logged-in";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
await $("button=Log out").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
});
it("should create screenshots for the logged out state when it logs in", async () => {
const componentId = "example-page--logged-out";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
await $("button=Log in").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
});
});
在兩個不同的組件上執行兩個測試。每個測試首先設定一個狀態,然後截取螢幕快照。您也會注意到引入了一個新的自訂命令,可以在這裡找到。
上面的規格檔案可以儲存在一個資料夾中,並使用以下命令加入命令行
npm run test.local.desktop.storybook.localhost -- --spec='tests/specs/storybook-interaction/*.ts'
Storybook 執行器會先自動掃描您的 Storybook 實例,然後將您的測試加入需要比較的 stories。如果您不希望用於互動測試的組件被比較兩次,您可以添加一個篩選器,透過提供 --skipStories
篩選器,從掃描中移除「預設」的 stories。看起來會像這樣
npm run test.local.desktop.storybook.localhost -- --skipStories="/example-page.*/gm" --spec='tests/specs/storybook-interaction/*.ts'
新的自訂命令
一個名為 browser.waitForStorybookComponentToBeLoaded({ id: 'componentId' })
的新自訂命令將被添加到 browser/driver
物件中,它將自動載入組件並等待其完成,因此您不需要使用 browser.url('url.com')
方法。它可以使用如下
import { browser, expect } from "@wdio/globals";
describe("Storybook Interaction", () => {
it("should create screenshots for the logged in state when it logs out", async () => {
const componentId = "example-page--logged-in";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
await $("button=Log out").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
});
it("should create screenshots for the logged out state when it logs in", async () => {
const componentId = "example-page--logged-out";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
await $("button=Log in").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
});
});
選項如下
clipSelector
- 類型:
string
- 強制: 否
- 預設值: Storybook V7 為
#storybook-root > :first-child
,Storybook V6 為#root > :first-child:not(script):not(style)
- 範例
await browser.waitForStorybookComponentToBeLoaded({
clipSelector: "#your-selector",
id: "componentId",
});
這是將用來
- 選取要擷取螢幕截圖的元素的選取器
- 用於等待元素在擷取螢幕截圖之前可見
id
- 類型:
string
- 必要: 是
- 範例
await browser.waitForStorybookComponentToBeLoaded({ '#your-selector', id: 'componentId' })
使用 story 的 id
,可以在 story 的 URL 中找到。例如,在此 URL https://#:6006/?path=/story/example-page--logged-out
中的 id
為 example-page--logged-out
timeout
- 類型:
number
- 強制: 否
- 預設值: 1100 毫秒
- 範例
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
timeout: 20000,
});
我們希望在頁面載入後等待組件可見的最長逾時時間
url
- 類型:
string
- 強制: 否
- 預設:
http://127.0.0.1:6006
- 範例
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
url: "https://your.url",
});
您的 Storybook 執行個體所在的 URL。
貢獻
更新套件
您可以使用簡單的 CLI 工具來更新套件。請確保您已安裝所有依賴項,然後您可以執行
pnpm update.packages
這將觸發一個 CLI,它會問您以下問題
==========================
🤖 Package update Wizard 🧙
==========================
? Which version target would you like to update to? (Minor|Latest)
? Do you want to update the package.json files? (Y/n)
? Do you want to remove all "node_modules" and reinstall dependencies? (Y/n)
? Would you like reinstall the dependencies? (Y/n)
這將產生以下日誌
開啟以查看日誌範例
==========================
🤖 Package update Wizard 🧙
==========================
? Which version target would you like to update to? Minor
? Do you want to update the package.json files? yes
Updating root 'package.json' for minor updates...
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/package.json
[====================] 38/38 100%
@typescript-eslint/eslint-plugin ^8.7.0 → ^8.8.0
@typescript-eslint/parser ^8.7.0 → ^8.8.0
@typescript-eslint/utils ^8.7.0 → ^8.8.0
@vitest/coverage-v8 ^2.1.1 → ^2.1.2
vitest ^2.1.1 → ^2.1.2
Run pnpm install to install new versions.
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/ocr-service...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/ocr-service/package.json
[====================] 11/11 100%
All dependencies match the minor package versions :)
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-reporter...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-reporter/package.json
[====================] 11/11 100%
eslint-config-next 14.2.13 → 14.2.14
next 14.2.13 → 14.2.14
Run pnpm install to install new versions.
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-service...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-service/package.json
[====================] 5/5 100%
All dependencies match the minor package versions :)
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/webdriver-image-comparison...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/webdriver-image-comparison/package.json
[====================] 8/8 100%
All dependencies match the minor package versions :)
? Do you want to remove all "node_modules" and reinstall dependencies? yes
Removing root dependencies in /Users/wswebcreation/Git/wdio/visual-testing...
Removing dependencies in ocr-service...
Removing dependencies in visual-reporter...
Removing dependencies in visual-service...
Removing dependencies in webdriver-image-comparison...
? Would you like reinstall the dependencies? yes
Installing dependencies in /Users/wswebcreation/Git/wdio/visual-testing...
> @wdio/visual-testing-monorepo@ pnpm.install.workaround /Users/wswebcreation/Git/wdio/visual-testing
> pnpm install --shamefully-hoist
Scope: all 5 workspace projects
Lockfile is up to date, resolution step is skipped
Packages: +1274
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 1274, reused 1265, downloaded 0, added 1274, done
dependencies:
- @wdio/ocr-service 2.0.0 <- packages/ocr-service
- @wdio/visual-service 6.0.0 <- packages/visual-service
devDependencies:
- @changesets/cli 2.27.8
- @inquirer/prompts 5.5.0
- @tsconfig/node20 20.1.4
- @types/eslint 9.6.1
- @types/jsdom 21.1.7
- @types/node 20.16.4
- @types/react 18.3.5
- @types/react-dom 18.3.0
- @types/xml2js 0.4.14
- @typescript-eslint/eslint-plugin 8.8.0
- @typescript-eslint/parser 8.8.0
- @typescript-eslint/utils 8.8.0
- @vitest/coverage-v8 2.1.2
- @wdio/appium-service 9.1.2
- @wdio/cli 9.1.2
- @wdio/globals 9.1.2
- @wdio/local-runner 9.1.2
- @wdio/mocha-framework 9.1.2
- @wdio/sauce-service 9.1.2
- @wdio/shared-store-service 9.1.2
- @wdio/spec-reporter 9.1.2
- @wdio/types 9.1.2
- eslint 9.11.1
- eslint-plugin-import 2.30.0
- eslint-plugin-unicorn 55.0.0
- eslint-plugin-wdio 9.0.8
- husky 9.1.6
- jsdom 25.0.1
- npm-run-all2 6.2.3
- release-it 17.6.0
- rimraf 6.0.1
- saucelabs 8.0.0
- ts-node 10.9.2
- typescript 5.6.2
- vitest 2.1.2
- webdriverio 9.1.2
. prepare$ husky
└─ Done in 204ms
Done in 9.5s
All packages updated!
問題
如果您對貢獻此專案有任何疑問或問題,請加入我們的 Discord 伺服器。在 🙏-contributing
頻道中找到我們的貢獻者。
問題回報
如果您有問題、錯誤或功能請求,請提出問題回報。在提交問題回報之前,請先搜尋問題存檔以減少重複,並閱讀 FAQ。
如果您在那裡找不到答案,您可以提交一個問題回報,您可以在其中提交
- 🐛錯誤回報:建立報告以幫助我們改進
- 📖文件:建議改進或報告遺失/不明確的文件。
- 💡功能請求:為此模組提出一個想法。
- 💬問題:提出問題。
開發工作流程
要為此專案建立 PR 並開始貢獻,請按照此逐步指南
-
Fork 專案。
-
將專案複製到您電腦上的某個位置
$ git clone https://github.com/webdriverio/visual-testing.git
-
前往目錄並設定專案
$ cd visual-testing
$ corepack enable
$ corepack use pnpm@8.x
$ pnpm pnpm.install.workaround -
執行將自動轉換程式碼的監看模式
$ pnpm watch
要建置專案,請執行
$ pnpm build
-
請確保您的變更不會破壞任何測試,執行
$ pnpm test
此專案使用 changesets 自動建立變更日誌和發布。
測試
需要執行多個測試才能測試模組。新增 PR 時,所有測試至少必須通過本機測試。每個 PR 都會自動針對 Sauce Labs 進行測試,請參閱我們的 GitHub Actions 管道。在核准 PR 之前,核心貢獻者將針對模擬器/模擬器/真實裝置測試 PR。
本機測試
首先,需要建立本機基準。這可以使用以下命令完成
// With the webdriver protocol
$ npm run test.local.init
此命令將建立一個名為 localBaseline
的資料夾,其中將包含所有基準圖片。
然後執行
// With the webdriver protocol
npm run test.local.desktop
這將在 Chrome 上的本機執行所有測試。
本機 Storybook 執行器測試 (Beta)
首先,需要建立本機基準。這可以使用以下命令完成
npm run test.local.desktop.storybook
這將在無頭模式下使用 Chrome 針對位於 https://govuk-react.github.io/govuk-react/ 的 Demo Storybook 儲存庫執行 Storybook 測試。
要使用更多瀏覽器執行測試,您可以執行
npm run test.local.desktop.storybook -- --browsers=chrome,firefox,edge,safari
[!NOTE] 請確保您已在本機上安裝要執行的瀏覽器
使用 Sauce Labs 進行 CI 測試(PR 不需要)
以下命令用於在 GitHub Actions 上測試建置,它只能在那裡使用,而不能用於本機開發。
$ npm run test.saucelabs
它將針對許多配置進行測試,這些配置可以在這裡找到。所有 PR 都會自動針對 Sauce Labs 進行檢查。
發佈
要發佈上面列出的任何套件的版本,請執行以下操作
鳴謝
@wdio/visual-testing
使用 Sauce Labs 的開放原始碼授權。