Playwright
npm install @tracera/playwright
需要 Node.js ≥ 22.19(见 自动化测试适配器)。@tracera/playwright。
在 playwright.config.ts 中:
import '@tracera/playwright/register';
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [['@tracera/playwright/reporter']],
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure', // or "on-first-retry"
},
});
import "@tracera/playwright/register" 会在每个 worker 中修补 test.step / hooks,使 tracera.comment / tracera.error 落在当前步骤。
在配置中一次性启用 screenshot / video / trace — Playwright 产物会自动转发到 Tracera 结果(结果最多 10 个附件,每个步骤最多 10 个)。启用重试时只上报最终一次尝试。若该次是重试(retry > 0),结果 Env 页会包含 PLAYWRIGHT_RETRY,即 Playwright 的 testInfo.retry(1 表示第二次运行)。
环境变量与运行模式见 自动化测试适配器。
绑定 testCaseId 与 autotestName
从 @playwright/test 导入 test / expect,从 @tracera/playwright 导入 tracera / annotations。
若未设置 autotestName,适配器使用 Playwright 测试标题。
在声明时(推荐):
import { test, expect } from '@playwright/test';
import { annotations } from '@tracera/playwright';
test('login', { annotation: annotations(42, 'e2e/login') }, async ({ page }) => {
await page.goto('/login');
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
});
在测试体内(若 annotations 已绑定用例则可省略):
import { test, expect } from '@playwright/test';
import { tracera } from '@tracera/playwright';
test('login', async ({ page }) => {
tracera.testCase(42, 'e2e/login');
await page.goto('/login');
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
});
步骤
使用 Playwright 的 test.step — 会记入 测试。若你更习惯各适配器统一的 API,也可用 tracera.step,上报方式相同。写在 test.beforeEach 里的步骤进入 准备;写在 test.afterEach 里的步骤进入 清理。
import { test } from '@playwright/test';
import { annotations } from '@tracera/playwright';
test.beforeEach(async ({ page }) => {
await test.step('open shop', async () => {
await page.goto('/shop');
});
});
test('checkout', { annotation: annotations(10, 'e2e/checkout') }, async ({ page }) => {
await test.step('add to cart', async () => {
await page.getByRole('button', { name: 'Add' }).click();
});
});
test.afterEach(async ({ page }) => {
await test.step('cleanup', async () => {
await page.goto('/cart/clear');
});
});
注释、错误与附件
在步骤内是该步骤的字段。在步骤外是结果上的字段。
import { test } from '@playwright/test';
import { tracera, annotations } from '@tracera/playwright';
test('login', { annotation: annotations(42, 'e2e/login') }, async ({ page }, testInfo) => {
tracera.comment('result-level note');
tracera.error('result-level error text');
await test.step('open login', async () => {
await page.goto('/login');
tracera.comment('landed on login');
});
await testInfo.attach('suite-log.txt', {
body: 'finished login flow',
contentType: 'text/plain',
});
});
自定义文件请使用 testInfo.attach。Playwright 会自行附上截图、浏览器录屏和 trace — 在 Tracera 中,图片在灯箱中打开,录屏可内联播放,trace 在 Trace Viewer 中打开。
参数化测试
import { test, expect } from '@playwright/test';
import { annotations } from '@tracera/playwright';
const rows = [
{ id: 42, name: 'e2e/login-ok', path: '/login' },
{ id: 43, name: 'e2e/login-sso', path: '/login/sso' },
];
for (const row of rows) {
test(row.name, { annotation: annotations(row.id, row.name) }, async ({ page }) => {
await test.step('open', async () => {
await page.goto(row.path);
});
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
});
}
也可以在体内调用 tracera.testCase(row.id, row.name),而不使用 annotations。
自定义 fixtures
像往常一样扩展 Playwright 标准 test:
import { test as base, expect } from '@playwright/test';
import { tracera } from '@tracera/playwright';
export const test = base.extend<{ asUser: void }>({
asUser: [
async ({ page }, use) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByRole('button', { name: 'Sign in' }).click();
await use();
},
{ auto: true },
],
});
test('dashboard', async ({ page }) => {
tracera.testCase(99, 'e2e/dashboard');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});