https://playwright.dev/docs/test-retries
Giới thiệu
- Test retry là cách mà test tự động chạy lại khi nó fail.
- Test retry sẽ rất hữu ích trong trường hợp bạn có một số test không ổn định (flaky).
- Test retry được cấu hình trong file config (playwright.config.ts)
Failures
-
Playwright test chạy test trên các worker process. Các process này chính là OS processes, chạy độc lập, được điều phối bởi test runner.
-
Tất cả các worker đều có môi trường độc lập và có browser riêng.
-
Cùng xét đoạn code dưới đây:
import { test } from '@playwright/test';
test.describe('suite', () => {
test.beforeAll(async () => { /* ... */ });
test('first good', async ({ page }) => { /* ... */ });
test('second flaky', async ({ page }) => { /* ... */ });
test('third good', async ({ page }) => { /* ... */ });
test.afterAll(async () => { /* ... */ });
});
- Khi tất cả cá test pass, thứ tự chạy sẽ giống nhau ở tất cả các worker:
beforeAll
hookfirst good
testsecond flaky
testthird good
testafterAll
hook
- Nếu có một test fail, quá trình này sẽ được thực hiện như sau:
- Stop worker hiện tại.
- Tạo một worker mới, tiếp tục chạy các test fail.
- Vì tạo worker mới nên các hook before, after cũng sẽ được chạy lại.
- Xét vụ dụ sau:
- Worker #1 chạy
beforeAll
hookfirst good
passsecond flaky
failafterAll
hook runs
- Worker #2 chạy
beforeAll
hookthird good
passafterAll
hook runs
- Worker #1 chạy
- Nếu bạn enable retry lên, worker số 2 sẽ chạy lại test bị fail và bắt đầu từ đây:
- Worker #1 chạy
beforeAll
hookfirst good
passsecond flaky
failafterAll
hook runs
- Worker #2 chạy
beforeAll
hooksecond flaky
passthird good
passafterAll
hook runs
- Worker #1 chạy
Retries
- Bạn có thể cấu hình số lần retry thông qua terminal:
# Give failing tests 3 retry attempts
npx playwright test --retries=3
- Hay thông qua config
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Give failing tests 3 retry attempts
retries: 3,
});
-
Playwright phân loại các test thành 3 loại:
- passed: test chạy pass
- flaky: test chạy fail lần đầu, nhưng retry lại thì pass.
- failed: test chạy fail.
-
Ví dụ
Running 3 tests using 1 worker
✓ example.spec.ts:4:2 › first passes (438ms)
x example.spec.ts:5:2 › second flaky (691ms)
✓ example.spec.ts:5:2 › second flaky (522ms)
✓ example.spec.ts:6:2 › third passes (932ms)
1 flaky
example.spec.ts:5:2 › second flaky
2 passed (4s)
- Bạn có thể xác định được retry thông qua testInfo.retry, có thể access được ở ở test, hook, hay fixture. Ví dụ:
import { test, expect } from '@playwright/test';
test('my test', async ({ page }, testInfo) => {
if (testInfo.retry)
await cleanSomeCachesOnTheServer();
// ...
});
- Bạn cũng có thể cấu hình retry cho một danh sách các test, sử dụng
test.descritbe.configure()
:
import { test, expect } from '@playwright/test';
test.describe(() => {
// All tests in this describe group will get 2 retry attempts.
test.describe.configure({ retries: 2 });
test('test 1', async ({ page }) => {
// ...
});
test('test 2', async ({ page }) => {
// ...
});
});
Serial mode
- Sử dụng
test.describe.serial()
để nhóm các test lại và đảm bảo các test sẽ luôn được chạy cùng nhau và theo thứ tự. - Nếu một test fail, tòan bộ các test còn lại sẽ bị skip.
- Thử xét ví dụ bạn có test dưới đây:
import { test } from '@playwright/test';
test.describe.configure({ mode: 'serial' });
test.beforeAll(async () => { /* ... */ });
test('first good', async ({ page }) => { /* ... */ });
test('second flaky', async ({ page }) => { /* ... */ });
test('third good', async ({ page }) => { /* ... */ });
-
Khi chạy test không có retry, nếu một test fail thì các test phía sau sẽ bị skip hết.
- Worker #1 chạy
beforeAll
hookfirst good
passsecond flaky
failthird good
sẽ bị skip
- Worker #1 chạy
-
Khi có retry, test sẽ được retry cùng nhau:
- Worker #1 chạy
beforeAll
hookfirst good
passsecond flaky
failthird good
sẽ bị skip
- Worker #2 chạy
beforeAll
hook chạy lạifirst good
passsecond flaky
passthird good
pass
- Worker #1 chạy
-
Lưu ý: bạn vẫn nên viết các test độc lập nhau thì hơn. Chạy vừa nhanh, mà lúc retry cũng độc lập nữa.
Reuse single page giữa các test
- Mặc định là playwright sẽ sử dụng các page khác nhau cho mỗi test.
- Trường hợp bạn muốn dùng lại, hãy khai báo ở bên ngoài test và dùng lại bên trong.
- Ví dụ dưới đây khai báo biến page ở trong khối describe, trong beforeAll khởi tạo cho biến page, và dùng lại ở trong các test
import { test, type Page } from '@playwright/test';
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();
});
Trả lời