並行處理
介紹
Playwright Test 以並行方式執行測試。為了實現這一點,它會同時執行多個工作程序。預設情況下,測試檔案會並行執行。單一檔案中的測試會依序在同一個工作程序中執行。
- 您可以使用
test.describe.configure
配置測試,以並行方式執行單一檔案中的測試。 - 您可以使用 testProject.fullyParallel 或 testConfig.fullyParallel,將整個專案配置為並行執行所有檔案中的所有測試。
- 若要停用並行處理,請將 工作程序數量限制為一個。
您可以控制 並行工作程序數量,並 限制整個測試套件中的失敗次數,以提高效率。
工作程序
所有測試都在工作程序中執行。這些程序是作業系統程序,獨立執行,由測試執行器協調。所有工作程序都具有相同的環境,並且每個工作程序都會啟動自己的瀏覽器。
您無法在工作程序之間進行通訊。Playwright Test 會盡可能重複使用單一工作程序,以加快測試速度,因此通常會在單一工作程序中依序執行多個測試檔案。
工作程序總是在 測試失敗 後關閉,以確保後續測試的環境是乾淨的。
限制工作程序數量
您可以透過 命令列 或在 組態檔 中控制並行工作程序的最大數量。
從命令列
npx playwright test --workers 4
在組態檔中
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Limit the number of workers on CI, use default locally
workers: process.env.CI ? 2 : undefined,
});
停用並行處理
您可以透過在組態檔中設定 workers: 1
選項,或將 --workers=1
傳遞至命令列,來停用任何並行處理。
npx playwright test --workers=1
在單一檔案中並行測試
預設情況下,單一檔案中的測試會依序執行。如果您的單一檔案中有許多獨立的測試,您可能會想要使用 test.describe.configure() 並行執行它們。
請注意,並行測試會在獨立的工作程序中執行,並且無法共用任何狀態或全域變數。每個測試都會為自己執行所有相關的 Hook,包括 beforeAll
和 afterAll
。
import { test } from '@playwright/test';
test.describe.configure({ mode: 'parallel' });
test('runs in parallel 1', async ({ page }) => { /* ... */ });
test('runs in parallel 2', async ({ page }) => { /* ... */ });
或者,您也可以在組態檔中選擇讓所有測試都進入此完全並行模式
import { defineConfig } from '@playwright/test';
export default defineConfig({
fullyParallel: true,
});
您也可以選擇僅針對少數專案啟用完全並行模式
import { defineConfig } from '@playwright/test';
export default defineConfig({
// runs all tests in all files of a specific project in parallel
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
fullyParallel: true,
},
]
});
序列模式
您可以將相互依賴的測試註解為序列。如果其中一個序列測試失敗,則會跳過所有後續測試。群組中的所有測試都會一起重試。
不建議使用序列。通常最好讓您的測試隔離,以便它們可以獨立執行。
import { test, type Page } from '@playwright/test';
// Annotate entire file as serial.
test.describe.configure({ mode: 'serial' });
let page: Page;
test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
});
test.afterAll(async () => {
await page.close();
});
test('runs first', async () => {
await page.goto('https://playwright.dev.org.tw/');
});
test('runs second', async () => {
await page.getByText('Get Started').click();
});
在多部機器之間分片測試
Playwright Test 可以分片測試套件,以便可以在多部機器上執行。有關更多詳細資訊,請參閱 分片指南。
npx playwright test --shard=2/3
限制失敗次數並快速失敗
您可以透過設定 maxFailures
組態選項或傳遞 --max-failures
命令列旗標,來限制整個測試套件中失敗測試的數量。
當設定「最大失敗次數」執行時,Playwright Test 將在達到此失敗測試次數後停止,並跳過任何尚未執行的測試。這對於避免在損壞的測試套件上浪費資源非常有用。
傳遞命令列選項
npx playwright test --max-failures=10
在組態檔中設定
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Limit the number of failures on CI to save resources
maxFailures: process.env.CI ? 10 : undefined,
});
工作程序索引與平行索引
每個工作程序都會被分配兩個 ID:從 1 開始的唯一工作程序索引,以及介於 0
和 workers - 1
之間的平行索引。當工作程序重新啟動時(例如在失敗後),新的工作程序程序具有相同的 parallelIndex
和新的 workerIndex
。
您可以從環境變數 process.env.TEST_WORKER_INDEX
和 process.env.TEST_PARALLEL_INDEX
讀取索引,或透過 testInfo.workerIndex 和 testInfo.parallelIndex 存取它們。
在並行工作程序之間隔離測試資料
您可以利用上述的 process.env.TEST_WORKER_INDEX
或 testInfo.workerIndex,在不同工作程序上執行的測試之間隔離資料庫中的使用者資料。工作程序執行的所有測試都會重複使用同一個使用者。
建立 playwright/fixtures.ts
檔案,該檔案將 建立 dbUserName
fixture 並在測試資料庫中初始化新使用者。使用 testInfo.workerIndex 來區分不同的工作程序。
import { test as baseTest, expect } from '@playwright/test';
// Import project utils for managing users in the test database.
import { createUserInTestDatabase, deleteUserFromTestDatabase } from './my-db-utils';
export * from '@playwright/test';
export const test = baseTest.extend<{}, { dbUserName: string }>({
// Returns db user name unique for the worker.
dbUserName: [async ({ }, use) => {
// Use workerIndex as a unique identifier for each worker.
const userName = `user-${test.info().workerIndex}`;
// Initialize user in the database.
await createUserInTestDatabase(userName);
await use(userName);
// Clean up after the tests are done.
await deleteUserFromTestDatabase(userName);
}, { scope: 'worker' }],
});
現在,每個測試檔案都應該從我們的 fixtures 檔案而不是 @playwright/test
匯入 test
。
// Important: import our fixtures.
import { test, expect } from '../playwright/fixtures';
test('test', async ({ dbUserName }) => {
// Use the user name in the test.
});
控制測試順序
Playwright Test 會按照宣告順序執行單一檔案中的測試,除非您 並行執行單一檔案中的測試。
由於 Playwright Test 預設會並行執行測試檔案,因此無法保證跨檔案的測試執行順序。但是,如果您 停用並行處理,您可以透過依字母順序命名檔案或使用「測試清單」檔案來控制測試順序。
按字母順序排序測試檔案
當您停用並行測試執行時,Playwright Test 會依字母順序執行測試檔案。您可以使用一些命名慣例來控制測試順序,例如 001-user-signin-flow.spec.ts
、002-create-new-document.spec.ts
等等。
使用「測試清單」檔案
不鼓勵使用測試清單,僅作為盡力而為的支援。某些功能(例如 VS Code 擴充功能和追蹤)可能無法與測試清單正常運作。
您可以將測試放在多個檔案中的 Helper 函式中。考慮以下範例,其中測試不是直接在檔案中定義,而是在包裝函式中定義。
import { test, expect } from '@playwright/test';
export default function createTests() {
test('feature-a example test', async ({ page }) => {
// ... test goes here
});
}
import { test, expect } from '@playwright/test';
export default function createTests() {
test.use({ viewport: { width: 500, height: 500 } });
test('feature-b example test', async ({ page }) => {
// ... test goes here
});
}
您可以建立一個測試清單檔案,以控制測試順序 - 先執行 feature-b
測試,然後執行 feature-a
測試。請注意每個測試檔案如何包裝在呼叫定義測試之函式的 test.describe()
區塊中。這樣,test.use()
呼叫只會影響單一檔案中的測試。
import { test } from '@playwright/test';
import featureBTests from './feature-b.spec.ts';
import featureATests from './feature-a.spec.ts';
test.describe(featureBTests);
test.describe(featureATests);
現在,透過將工作程序設定為一個來停用並行執行,並指定您的測試清單檔案。
import { defineConfig } from '@playwright/test';
export default defineConfig({
workers: 1,
testMatch: 'test.list.ts',
});
請勿直接在 Helper 檔案中定義測試。這可能會導致意外的結果,因為您的測試現在取決於 import
/require
陳述式的順序。相反地,請將測試包裝在一個函式中,該函式將由測試清單檔案明確呼叫,如上述範例所示。