详解Puppeteer前端自动化测试实践

起因

目前我们在持续开发着一个几十个页面,十万+行代码的项目,随着产品的更迭,总会出现这样的问题。在对某些业务逻辑或者功能进行添加或者修改的时候(尤其是通用逻辑),这些通用的逻辑或者组件往往会牵扯到一些其他地方的问题。由于测试人员受限,我们很难在完成一个模块单元后,对所有功能重新测试一遍。
同时,由于环境及数据的区别,(以及在开发过程中对代码完备性的疏忽),代码会在某些特殊数据的解析和和展示上出现问题,在开发和测试中很难去发现。总的来说,我们希望有一个这样的工具,帮我们解决上述几个问题:

  1. 在进行代码和功能改动后,能够自动访问各个功能的页面,检测问题
  2. 针对大量的数据内容,进行批量访问,检测对于不同数据的展示是否存在问题
  3. 测试与代码功能尽量不耦合,避免每次上新功能都需要对测试用例进行修改,维护成本太大
  4. 定期的测试任务,及时发现数据平台针对新数据的展示完备性

其中,最重要的问题,就是将测试代码与功能解耦,避免每次迭代和修改都需要追加新的测试用例。我们如何做到这一点呢?首先我们来梳理下测试平台的功能。

功能设定

由于我们的平台主要是进行数据展示,所以我们在测试过程中,主要以日常的展示数据为重心即可,针对一些复杂的表单操作先不予处理。针对上述的几个问题,我们针对自动化测试工具的功能如下:

  1. 依次访问各个页面
  2. 访问各个页面的具体内容,如时间切换、选项卡切换、分页切换、表格展开行等等
  3. 针对数据表格中的详情链接,选择前100条进行访问,并进行下钻页的继续测试
  4. 捕获在页面中的错误请求
  5. 对错误信息进行捕获,统计和上报

根据以上的梳理,我们可以把整个应用分为几个测试单元

  • 页面单元,检测各功能页面访问的稳定性
  • 详情页单元,根据页面的数据列表,进行批量的详情页跳转,检测不同参数下详情页的稳定性
  • 功能单元,用于检测页面和详情页各种展示类型点击切换后是否产生错误

通过这样的划分,我们针对各个单元进行具体的测试逻辑书写用例,这样就可以避免再添加新功能和页面时,频繁对测试用例进行修改了。

Puppeteer

带着上面我们的需求,我们来看下Puppeteer的功能和特性,是否能够满足我们的要求。

文档地址

Puppeteer是一个Node库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。

我们可以使用Puppeteer完成以下工作:

  • 访问页面,进行截图
  • 自动进行键盘输入,提交表单
  • 模拟点击等用户操作
  • 等等等等。。

我们来通过一些小案例,来介绍他们的基本功能:

访问一个带有ba认证的网站

puppeteer可以创建page实例,并使用goto方法进行页面访问,page包含一系列方法,可以对页面进行各种操作。

(async () => {
 const browser = await puppeteer.launch();
 const page = await browser.newPage();
 // ba认证
 await page.authenticate({
  username,
  password
 });
 // 访问页面
 await page.goto('https://example.com');
 // 进行截图
 await page.screenshot({path: 'example.png'});

 await browser.close();
})();

访问登陆页面,并进行登录

首先,对于SPA(单页面应用),我们都知道,当页面进入后,客户端代码才开始进行渲染工作。我们需要等到页面内容渲染完成后,再进行对应的操作。我们有以下几种方法来使用

waitUntil

puppeteer针对页面的访问,切换等,提供了waitUntil参数,来确定满足什么条件才认为页面跳转完成。包括以下事件:

  • load - 页面的load事件触发时
  • domcontentloaded - 页面的DOMContentLoaded事件触发时
  • networkidle0 - 不再有网络连接时触发(至少500毫秒后)
  • networkidle2 - 只有2个网络连接时触发(至少500毫秒后)

通过waitUnitl,我们可以当页面请求都完成之后,确定页面已经访问完成。

waitFor

waitFor方法可以在指定动作完成后才进行resolve

// wait for selector
await page.waitFor('.foo');
// wait for 1 second
await page.waitFor(1000);
// wait for predicate
await page.waitFor(() => !!document.querySelector('.foo'));

我们可以利用waitForSelector方法,当登录框渲染成功后,才进行登录操作

// 等待密码输入框渲染
await page.waitFor('#password');
// 输入用户名
await page.type('input#username', "username");
// 输入密码
await page.type('input#password', "testpass");

// 点击登录按钮
await Promise.all([
 page.waitForNavigation(), // 等跳转完成后resolve
 page.click('button.login-button'), // 点击该链接将间接导致导航(跳转)
]);

await page.waitFor(2000)

// 获取cookies
const cookies = await page.cookies()

针对列表内容里的链接进行批量访问

主要利用到page实例的选择器功能

const table = await page.$('.table')
const links = await table.$$eval('a.link-detail', links =>
 links.map(link => link.href)
);

// 循环访问links
...

进行错误和访问监听

puppeteer可以监听在页面访问过程中的报错,请求等等,这样我们就可以捕获到页面的访问错误并进行上报啦,这也是我们进行测试需要的基本功能~

// 当发生页面js代码没有捕获的异常时触发。
page.on('pagerror', () => {})
// 当页面崩溃时触发。
page.on('error', () => {})
// 当页面发送一个请求时触发
page.on('request')
// 当页面的某个请求接收到对应的 response 时触发。
page.on('response')

通过以上的几个小案例,我们发现Puppeteer的功能非常强大,完全能够满足我们以上的对页面进行自动访问的需求。接下来,我们针对我们的测试单元进行个单元用例的书写

最终功能

通过我们上面对测试单元的规划,我们可以规划一下我们的测试路径

访问网站 -> 登陆 -> 访问页面1 -> 进行基本单元测试 -> 获取详情页跳转链接 -> 依次访问详情页 -> 进行基本单元测试

-> 访问页面2 ...

所以,我们可以拆分出几个大类,和几个测试单元,来进行各项测试

// 包含基本的测试方法,log输出等
class Base {}

// 详情页单元,进行一些基本的单元测试
class PageDetal extends Base {}

// 页面单元,进行基本的单元测试,并获取并依次访问详情页
class Page extends PageDetal {}

// 进行登录等操作,并依次访问页面单元进行测试
class Root extends Base {}

同时,我们如何在功能页面变化时,跟踪到测试的变化呢,我们可以针对我们测试的功能,为其添加自定义标签test-role,测试时,根据自定义标签进行测试逻辑的编写。

例如针对时间切换单元,我们做一下简单的介绍:

// 1. 获取测试单元的元素
const timeSwitch = await page.$('[test-role="time-switch"]');

// 若页面没有timeSwitch, 则不用进行测试
if (!timeSwitch) return

// 2. time switch的切换按钮
const buttons = timeSwitch.$$('.time-switch-button')

// 3. 对按钮进行循环点击
for (let i = 0; i < buttons.length; i++) {
 const button = buttons[i]

 // 点击按钮
 await button.click()

 // 重点! 等待对应的内容出现时,才认定页面访问成功
 try {
  await page.waitFor('[test-role="time-switch-content"]')
 } catch (error) {
  reportError (error)
 }

 // 截图
 await page.screenshot()
}

上面只是进行了一个简单的访问内容测试,我们可以根据我们的用例单元书写各自的测试逻辑,在我们日常开发时,只需要对需要测试的内容,加上对应的test-role即可。

总结

根据以上的功能划分,我们很好的将一整个应用拆分成各个测试单元进行单元测试。需要注意的是,我们目前仅仅是对页面的可访问性进行测试,仅仅验证当用户进行各种操作,访问各个页面单元时页面是否会出错。并没有对页面的具体展示效果进行测试,这样会和页面的功能内容耦合起来,就需要单独的测试用例的编写了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • puppeteer库入门初探

    puppeteer 是一个Chrome官方出品的headless Chrome node库.它提供了一系列的API, 可以在无UI的情况下调用Chrome的功能, 适用于爬虫.自动化处理等各种场景 根据官网上描述,puppeteer 具有以下作用: 生成页面截图和 PDF 自动化表单提交.UI 测试.键盘输入等 创建一个最新的自动化测试环境.使用最新的 JavaScript 和浏览器功能,可以直接在最新版本的 Chrome 中运行测试. 捕获站点的时间线跟踪,以帮助诊断性能问题. 爬取 SPA

  • Puppeteer 爬取动态生成的网页实战

    Puppeteer 相关介绍与安装不过多介绍,可通过以下链接进行学习 一.Puppeteer 开源地址 英文文档 中文社区 二.爬取动态网页 1. 需求 首先,了解下我们的需求: 爬取zoomcharts文档中 Net Chart 目录下所有访问连接对应的页面,并保存到本地 2. 研究 ZoomCharts 文档页面结构 首先,我们得研究透 ZoomCharts 页面如何加载,以及左侧导航的 DOM 树结构,才好进行下一步操作 页面首次加载 页面首次加载,左侧导航第一个目录 Introducti

  • Puppeteer环境搭建的详细步骤

    简介 Puppeteer是Google开发并开源的一款工具,可用代码驱动浏览器操作. 由于诸多优秀的特性,Puppeteer常被用在爬虫与自动化测试上.详细介绍参见官方 README. Puppeteer本身是个NodeJS的库,自动化脚本也需要使用NodeJS编写,如果对JS不了解建议先学习JavaScript基础语法,或者使用Selenium等其他工具去实现. 对于一个陌生的工具,应当先检查是否适合自己,再去尝试使用,切莫盲目从众. Puppeteer 用处 利用网页生成PDF.图片 爬取S

  • puppeteer实现html截图的示例代码

    puppeteer是谷歌官方出品的一个通过 DevTools协议控制 headless Chrome 的Node库.可以通过Puppeteer的提供的api直接控制Chrome模拟大部分用户操作来进行UI Test或者作为爬虫访问页面来收集数据. 安装 直接运行安装命令: npm install puppeteer 如果出现无法安装的问题,可以使用淘宝镜像. puppeteer实现滑动截图 在我 puppeteer 使用截全屏的过程中发现有些图片无法截取到,而实际上是因为有些图片是懒加载的,如果

  • 爬虫利器Puppeteer实战

    Puppeteer 介绍 Puppeteer 翻译是操纵木偶的人,利用这个工具,我们能做一个操纵页面的人. Puppeteer 是一个 Nodejs 的库,支持调用 Chrome的API来操纵Web ,相比较 Selenium 或是 PhantomJs ,它最大的特点就是它的操作 Dom 可以完全在内存中进行模拟既在 V8 引擎中处理而不打开浏览器,而且关键是这个是Chrome团队在维护,会拥有更好的兼容性和前景. Puppeteer 用处 利用网页生成PDF.图片 爬取SPA应用,并生成预渲染

  • 使用puppeteer破解极验的滑动验证码

    基本的流程: 1. 打开前端网,点击登录. 2. 填写账号,密码. 3. 点解验证按钮,通过滑动验证,最后成功登陆. 代码实现: github上可以checkout. 具体代码如下所示: run.js const puppeteer = require('puppeteer'); const devices = require('puppeteer/DeviceDescriptors'); const iPhone = devices['iPhone 6 Plus']; let timeout

  • Windows下Node爬虫神器Puppeteer安装记

    对于爬虫,相信大家并不陌生.当希望得到一些网站的数据并做一些有趣的事时,必不可少要爬取网页,用到爬虫.而目前网络上也有很多爬虫的教程资料,不过又尤以python语言居多.想来自己是做web的,就希望以js的方式解决问题,于是希望利用nodejs.今天介绍一款node的爬虫利器:Puppeteer. Puppeteer正如其名"木偶",它允许我们像牵线木偶一样操纵它.它是一个建立在DevTools协议上的提供控制无头Chrome或Chromium的高级接口的Node库.官网上对其应用举了

  • 使用puppeteer爬取网站并抓出404无效链接

    检查网页无效链接 前言 自动化技术可以帮助我们做自动化测试,同样也可以帮助我们完成别的事情,比如今天我们要做的检查网站404无效链接. 原理 实现这样的功能,大致分为以下步骤: 1.打开官网首页,获取页面上所有的链接. 2.添加规则对这些链接过滤,把外链去掉. 3.遍历访问这些链接,打开打开其中的每一个链接,检查是否为404,如果是距离下来. 4.重复执行1,2,3.直到把整个网站所有的链接都遍历完. 准备 CukeTest 一款可以专业的编辑自动化脚本的工具.cuketest.com/ pup

  • 详解Puppeteer 入门教程

    1.Puppeteer 简介 Puppeteer 是一个node库,他提供了一组用来操纵Chrome的API, 通俗来说就是一个 headless chrome浏览器 (当然你也可以配置成有UI的,默认是没有的).既然是浏览器,那么我们手工可以在浏览器上做的事情 Puppeteer 都能胜任, 另外,Puppeteer 翻译成中文是"木偶"意思,所以听名字就知道,操纵起来很方便,你可以很方便的操纵她去实现: 1) 生成网页截图或者 PDF 2) 高级爬虫,可以爬取大量异步渲染内容的网页

  • 详解puppeteer使用代理

    背景 在使用puppeteer进行访问页面的时候,有时候需要用到代理. 环境: centos 7 chrome 安装 puppeteer使用chrome. 参考chrome的命令行使用方式. 在官网中没看到说明,不过一般的执行文件都是支持help的. 在服务器上安装chrome : vim /etc/yum.repos.d/google-chrome.repo 添加内容 [google-chrome] name=google-chrome baseurl=http://dl.google.com

随机推荐