Skip to main content

平行處理

簡介

Playwright Test 平行執行測試。為了達到這一點,它會執行多個同時運行的工作程序。預設情況下,測試檔案是平行執行的。單個檔案中的測試會按順序在同一個工作程序中執行。

你可以控制平行工作程序的數量和限制失敗次數以提高整個測試套件的效率。

Worker processes

所有測試在工作者程序中執行。這些程序是作業系統程序,獨立執行,由測試執行器協調。所有工作者有相同的環境,每個都啟動自己的瀏覽器。

你無法在工作者之間進行通訊。Playwright Test 會盡可能重複使用單一工作者以加快測試速度,因此多個測試檔案通常會在單一工作者中一個接一個地執行。

工作者在測試失敗後總是會關閉,以保證後續測試的乾淨環境。

限制工作者

您可以通過 command line 或在 configuration file 中控制最大平行工作程序數量。

從命令列:

npx playwright test --workers 4

在設定檔中:

playwright.config.ts
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() 平行執行它們。

請注意,平行測試在不同的工作程序中執行,不能共享任何狀態或全域變數。每個測試都只為自己執行所有相關的鉤子,包括 beforeAllafterAll

import { test } from '@playwright/test';

test.describe.configure({ mode: 'parallel' });

test('runs in parallel 1', async ({ page }) => { /* ... */ });
test('runs in parallel 2', async ({ page }) => { /* ... */ });

或者,您可以在配置文件中選擇將所有測試加入此完全平行模式:

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

export default defineConfig({
fullyParallel: true,
});

您也可以選擇為幾個專案啟用完全平行模式:

playwright.config.ts
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,
},
]
});

序列模式

你可以將相互依賴的測試標註為序列。如果其中一個序列測試失敗,所有後續測試將被跳過。一組中的所有測試將一起重試。

note

不建議使用序列。通常最好使您的測試獨立,以便它們可以獨立執行。

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/');
});

test('runs second', async () => {
await page.getByText('Get Started').click();
});

在多台機器之間分片測試

Playwright Test 可以分片測試套件,以便在多台機器上執行。詳情請參閱分片指南

npx playwright test --shard=2/3

限制失敗並快速失敗

您可以透過設定 maxFailures 配置選項或傳遞 --max-failures 命令列標誌來限制整個測試套件中的失敗測試數量。

當設定 "max failures" 時,Playwright Test 會在達到此數量的失敗測試後停止,並跳過任何尚未執行的測試。這對於避免在損壞的測試套件上浪費資源非常有用。

傳遞命令列選項:

npx playwright test --max-failures=10

設定在配置檔案中:

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

export default defineConfig({
// Limit the number of failures on CI to save resources
maxFailures: process.env.CI ? 10 : undefined,
});

Worker 索引和平行索引

每個 worker 程序被分配兩個 id: 從 1 開始的唯一 worker 索引和介於 0workers - 1 之間的平行索引。當一個 worker 重新啟動時,例如在故障後,新 worker 程序具有相同的 parallelIndex 和新的 workerIndex

你可以從環境變數 process.env.TEST_WORKER_INDEXprocess.env.TEST_PARALLEL_INDEX 讀取索引,或通過 testInfo.workerIndextestInfo.parallelIndex 訪問它們。

隔離平行工作者之間的測試資料

你可以利用 process.env.TEST_WORKER_INDEXtestInfo.workerIndex 提到的來隔離資料庫中不同工作者執行測試之間的使用者資料。所有由工作者執行的測試都會重複使用相同的使用者。

建立 playwright/fixtures.ts 文件來建立 dbUserName fixture 並在測試資料庫中初始化一個新使用者。使用 testInfo.workerIndex 來區分不同的工作者。

playwright/fixtures.ts
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 文件中匯入 test,而不是從 @playwright/test

tests/example.spec.ts
// 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.ts002-create-new-document.spec.ts 等等。

使用 "測試清單" 文件

warning

不建議使用測試清單,並且僅提供盡力而為的支持。一些功能如 VS Code 擴充套件和追蹤可能無法與測試清單正常運作。

你可以將你的測試放在多個檔案中的輔助函式中。考慮以下範例,其中測試並未直接定義在檔案中,而是在包裝函式中。

feature-a.spec.ts
import { test, expect } from '@playwright/test';

export default function createTests() {
test('feature-a example test', async ({ page }) => {
// ... test goes here
});
}

feature-b.spec.ts
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() 呼叫只會影響單個文件中的測試。

test.list.ts
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);

現在通過將 workers 設定為 1 來停用平行執行,並指定你的測試清單檔案。

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

export default defineConfig({
workers: 1,
testMatch: 'test.list.ts',
});
note

不要直接在輔助檔案中定義你的測試。這可能會導致意外結果,因為你的測試現在依賴於 import/require 語句的順序。相反,將測試包裝在一個函式中,該函式將由測試列表檔案顯式呼叫,如上面的範例所示。