现在位置: 首页 > Playwright 教程 > 正文

Playwright 断言(Assertions)

本章全面介绍 Playwright 的断言体系,包括自动重试断言、通用断言以及软断言的用法。


什么是断言

断言(Assertion)用来验证测试的预期结果是否与实际结果一致。

Playwright 提供了两套断言:通用断言(来自 Jest)和自动重试断言(Playwright 独有)。


自动重试断言 vs 通用断言

自动重试断言(Async Matchers)

Playwright 的 Web 特定断言会自动重试,直到条件满足或超时,必须使用 await

实例

// 自动重试断言 —— 会等待条件满足
await expect(page.getByText('RUNOOB')).toBeVisible();

通用断言

用于非 Web 特定的值比较,不自动重试。

实例

// 通用断言 —— 立即执行,不等待
expect(1 + 1).toBe(2);
expect('hello').toContain('ell');
expect(true).toBeTruthy();
类型是否自动重试是否需要 await适用场景
自动重试断言必须 await页面元素、URL、标题等 Web 特定内容
通用断言不需要普通变量、数组、对象等 JavaScript 值

页面级断言

实例

// 页面标题断言
await expect(page).toHaveTitle('RUNOOB - 学的不仅是技术,更是梦想!');
await expect(page).toHaveTitle(/RUNOOB/);

// 页面 URL 断言
await expect(page).toHaveURL('https://www.runoob.com/');
await expect(page).toHaveURL(/runoob\.com/);

可见性断言

实例

const btn = page.getByRole('button', { name: '提交' });

// 元素可见
await expect(btn).toBeVisible();

// 元素不可见
await expect(btn).toBeHidden();

// 元素在 DOM 中存在(但不一定可见)
await expect(btn).toBeAttached();

// 元素在视口内可见
await expect(btn).toBeInViewport();

文本与值断言

实例

const heading = page.getByRole('heading', { name: 'RUNOOB' });

// 元素的文本内容精确匹配
await expect(heading).toHaveText('学的不仅是技术,更是梦想!');

// 元素的文本内容包含子串
await expect(heading).toContainText('技术');

// input 的当前值
await expect(page.getByLabel('用户名')).toHaveValue('runoob_user');

// 元素内容为空
await expect(page.getByTestId('error-msg')).toBeEmpty();

状态断言

实例

const checkbox = page.getByLabel('同意协议');
const input = page.getByLabel('邮箱');

// 元素已启用
await expect(input).toBeEnabled();

// 元素已禁用
await expect(input).toBeDisabled();

// 元素可编辑
await expect(input).toBeEditable();

// 复选框已勾选
await expect(checkbox).toBeChecked();

// 元素已获得焦点
await expect(input).toBeFocused();

属性断言

实例

const element = page.locator('.runoob-logo');

// DOM 属性断言
await expect(element).toHaveAttribute('src', '/static/images/logo.png');

// 只检查属性存在
await expect(element).toHaveAttribute('alt');

// CSS 类名断言
await expect(element).toHaveClass('logo-primary');

// CSS 属性值断言
await expect(element).toHaveCSS('display', 'block');

// 元素 ID 断言
await expect(element).toHaveId('main-logo');

// 无障碍名称(可访问名称)
await expect(page.getByRole('button')).toHaveAccessibleName('提交');

数量断言

实例

// 匹配元素数量
const items = page.getByRole('listitem');
await expect(items).toHaveCount(5);

// 配合 filter 使用
const activeItems = page.getByRole('listitem').filter({ hasText: '已激活' });
await expect(activeItems).toHaveCount(3);

通用断言速查

方法说明示例
toBe(value)严格相等(===)expect(x).toBe(42)
toEqual(value)深度相等expect(obj).toEqual({ a: 1 })
toContain(item)数组/字符串包含expect(arr).toContain('a')
toBeTruthy()值是真值expect(x).toBeTruthy()
toBeFalsy()值是假值expect(x).toBeFalsy()
toBeNull()值为 nullexpect(x).toBeNull()
toBeGreaterThan(n)大于 nexpect(x).toBeGreaterThan(10)
toBeLessThan(n)小于 nexpect(x).toBeLessThan(100)
toHaveLength(n)数组长度expect(arr).toHaveLength(3)

expect.soft() 软断言

普通断言失败后会立即终止测试。

软断言失败后不会终止,会继续执行后续代码,在测试结束时统一报告所有失败。

实例

test('表单验证多项检查', async ({ page }) => {
  await page.goto('https://example.com/form');

  // 软断言 —— 失败不会停止测试
  await expect.soft(page.getByLabel('用户名')).toBeVisible();
  await expect.soft(page.getByLabel('密码')).toBeVisible();
  await expect.soft(page.getByLabel('邮箱')).toBeVisible();
  await expect.soft(page.getByRole('button', { name: '注册' })).toBeEnabled();

  // 如果以上任一断言失败,会继续检查,最后统一报告
});

在测试表单页面时使用 expect.soft() 可以一次性发现所有缺失的字段,而不需要逐个修复后才看到下一个问题。这能大幅提高调试效率。


断言超时

自动重试断言默认超时 5 秒,可在配置文件或单次断言中自定义:

实例

// 单个断言设置超时(毫秒)
await expect(page.getByText('加载中...')).toBeHidden({ timeout: 10000 });

// 在配置文件中全局设置
// playwright.config.ts:
// export default defineConfig({
//   expect: { timeout: 10000 },
// });