Playwright实战 – 从录制生成代码到有效组织测试用例

图片[1]-Playwright实战 – 从录制生成代码到有效组织测试用例-365博客

简介:Playwright的录制功能提供了快速生成代码的方式,然而在实际项目中,这些自动化测试的代码因不稳定性而难以维护。本教程旨在帮助你掌握如何通过使用Playwright的API重新组织和优化自动生成的代码,从而提高测试用例的稳定性和可维护性。

概述

Playwright 的录制功能确实为自动化测试提供了一个快速入门的途径,能够帮助我们快速生成代码,实现从 0 到 1 的自动化测试。这是它的优点——快速、低成本,特别适合初学者或者需要快速验证想法的场景。

  1. 稳定性差:这次测试能通过,下次可能就失败了,尤其是页面结构稍有变化时。
  2. 可维护性低:代码通常比较冗长,而且有很多重复的部分。比如每个测试用例都会包含登录操作,随着项目迭代,这种重复代码会越来越多。
  3. 可复用性差:录制的代码往往缺乏模块化设计,后续修改和维护的成本会越来越高。

为了解决这些问题,我们可以借助 Playwright 提供的 API 对录制的代码进行重构,重新组织和管理测试用例。这样不仅能提高代码的稳定性可维护性,还能增强代码的可复用性,让自动化测试更加高效。

这篇教程将结合 Playwright 的特性,帮助你掌握以下内容:

  • 如何从零开始编写测试用例
  • 如何组织和管理测试用例
  • 常用的 API 使用技巧
  • 元素定位策略
  • 如何编写有效的断言

第一个test case

playwright写自动化测试非常简单

只关注2件事

  1. 执行的操作
  2. 断言的内容

其他复杂细节比如等待重试,框架本身已经帮我们处理好了

例如在playwrightexample中提供的例子

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

test('has title', async ({ page }) => {
    await page
        .goto('https://playwright.dev/');

    // 标题包含Playwright
    await expect(page)
        .toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
    await page.goto('https://playwright.dev/');

    // 操作
    await page
        .getByRole('link', { name: 'Get started' })
        .click();

    // 断言
    await expect(page.getByRole('heading', { name: 'Installation' }))
        .toBeVisible();
})

解释如下:

• page.goto()操作访问指定网页

• page.getByRole().click()操作定位到的页面元素,点击

• expect().toHaveTitle()断言title内容

• expect().toBeVisible()断言文本内容可见

小结:

1,不需要手动设置等待或调用 sleep

2,只需关注操作和断言,Playwright 会自动处理复杂细节

常用的api介绍与技巧

playwright提供了比较丰富的api

结合我自己的体会,从最简单test case代码构成来看

大概划分

  • test api
    • 导航 api
    • 定位 api
    • 交互 api
    • 断言 api

就是

  1. test api 开启一个test case
  2. 导航 api 中实现访问某个URL
  3. 定位 api 中定位某个页面元素
  4. 交互 api 中实现元素操作
  5. 断言 api 中给出结果断言

test api

test.describe :描述一组用例

要组织一个测试模块,可以用describe把一组test包括进来

test.describe('two tests', () => {
  test('one', async ({ page }) => {
    // ...
  });

  test('two', async ({ page }) => {
    // ...
  });
});

解释如下

• test.describe(),定义的测试模块,包括了2个test

• test之间是互相隔离的,执行上不存在先后次序,可同时执行

• two tests作为title参数会出现在测试报告中每一个test

常见技巧,有时候,代码开发和调试过程中,如单独执行跳过执行随后调试 可考虑以下api:

test.describe.only('仅执行该组', () => {
  test('example', async ({ page }) => {
    // This test will not run
  });
});
test.describe.skip('忽略改组', () => {
  test('example', async ({ page }) => {
    // This test will not run
  });
});
test.describe.fixme('待修改组', () => {
  test('example', async ({ page }) => {
    // This test will not run
  });
});

test :描述单个用例

一个test对应一个用例,即test case

• test(title, callback)

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

test('测试用例', async ({ page }) => {
  await page.goto(..);
});

解释如下

  • test()是一个方法,接收2个参数
  • 第1个参数是字符串,测试用例
  • 第2个参数是callback函数,即async ({ page }) => {}
    • page 是一个上下文参数,后面具体说
    • async 是异步的简写,这里是个异步调用
    • await 是async await简写,等待异步方法执行完成

test也有describe相类似的方法

test.only('仅执行用例', async ({ page }) => {
    // ...
});
test.skip('跳过该用例', async ({ page }) => {
    // ...
});
test.fixme('跳过该用例', async ({ page }) => {
    // ...
});

导航 api

page.goto :导航到页面

await page.goto('https://baidu.com/');

前进后退

// 回退
await page.goBack();
// 前进
await page.goForward();

定位 api

playwright中可以说非常重要,甚至可以说,决定了自动化是否顺利实施

选用什么定位方法直接决定了定位是否成功

定位策略

结合自己使用下来体会

playwright建议的策略

 1. 优先getBy方法:比如这些

  • getByRole()
  • getByText()
  • getByPlaceholder()
  • getByAltText()
  • getByTitle()
  • getByTestId()

2. 其次locator方法

  • page.locator()

3. 多元素处理

  • locator().first()
  • locator().last()
  • locator().nth()
  • locator().all()

按钮定位

await page.getByRole('button', { name: '登录' }).click();

文本定位

await expect(page.getByText('Welcome')).toBeVisible();

小技巧

 精准匹配

await expect(
    page.getByText('导航', { exact: true }))
    .toBeVisible();

正则匹配

await expect(
    page1.getByText(/^共 \d{1,3} 条$/))
    .toBeVisible();

输入框定位

await page
    .getByPlaceholder('name@example.com')
    .fill('playwright@microsoft.com');

图片定位

await page
    .getByAltText('logo')
    .click();

css定位

await page.locator('.content);

id定位

await page.locator('#su);

交互 api

点击

await page
    .getByAltText('logo')
    .click({delay: 100});

文本输入

await page
  .getByPlaceholder('请输入')
  .fill('end2end demo');

断言 api

expect用来写断言

那断言内容呢

除通用断言外

主要是页面元素的可见性

页面断言

// 标题
await expect(page).toHaveTitle('');
// url
await expect(page).toHaveURL(/.*\/login/);
// 按钮
await expect(
  page1.getByRole('button', { name: '已申请' }))
  .toBeVisible();
// 文本
await expect(page1.getByText(/没有数据/))
  .toBeVisible();

通用断言

// 数值
expect(responseCode).toBe(200);
expect(resBody).toHaveProperty('access_token');  
// 字符串
expect(resBody).toContain('时空数据')

小结

1. 利用codege快速生成代码是个比较好的开始

2. 运用playwright提供的api接口重新组织测试用例,其中test.describe用于描述测试模块test则对应到测试用例,还可以用test.onlytest.describe.skip来调整用例执行,熟悉这些api可以迅速掌握手写代码

3. 定位策略是UI自动化的一个关键点,推荐的定位次序为:getBy方法 > locator方法,如果返回有多个元素,可以用locator().first()locator.last()locator.nth(i)locator.all()等精确定位

4. 页面交互最常见click()fill(),也可以带参数,如click({delay:100})实现延迟效果

5. 断言expect(), 比较常见的是元素可见,expect().toBeVisible()

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容