1.前端自动化测试 之 视觉测试
前端自动化测试 之 视觉测试
前端测试分类
前端测试主要分五大方向测试,而这五大方向也分很多小方向测试,首先简单的介绍每个方向的概念
界面样式测试
固定界面样式测试:主要针对文字内容不变的区域,例如页面的页头,页脚这类结构、内容不变的区域,而测试一般通过截图对比解决。
结构不变界面样式测试:主要针对结构不变的区域,例如新闻区域这类结构不变,内容变化的区域,这类测试一般通过DOM元素对比解决。
计算样式测试:主要针对计算样式不变的区域,这类测试一般通过比较计算样式解决,但是这种测试不推荐,因为测试成本比较大。
功能测试
服务器数据预期测试:主要针对用户在前端界面进行某种操作后,提交数据给后台后,测试后台能否返回预期的数据
界面功能测试:主要针对用户在前端界面进行某种交互性操作后,测试能否获取预期的功能、界面交互
多浏览器测试
- 多浏览器测试:基于界面样式测试、功能测试的基础上来进行不同浏览器的的测试,俗称兼容性测试。
性能测试
- 白屏时间:用户浏览器输入网址后至浏览器出现至少1px画面为止。
- 首屏时间:用户浏览器首屏内所有的元素呈现所花费时间。
- 页面回归时间:用户浏览器非第一次加载所有的元素呈现所花费时间。
- 用户可操作时间(dom ready) :网站某些功能可以使用的时间。
- 页面总下载时间(onload):网站中所有资源加载完成并且可用时间。
质量测试
- 雅虎网站优化规则
什么样的项目适合自动化测试呢?
如上图所示,真正工作中无法全部满足以上条件,所以需要作出权衡,一般来说,只需要满足以下几点,就可以对项目开展自动化测试:
需求稳定,不会频繁变更
自动化测试最大的挑战就是需求的变化,而自动化脚本本身就需要修改、扩展、debug,去适应新的功能,如果投入产出比太低,那么自动化测试也失去了其价值和意义;
折中的做法是选择相对稳定的模块和功能进行自动化测试,变动较大、需求变更较频繁的部分用手工测试;
多平台运行,组合遍历型、大量的重复任务
测试数据、测试用例、自动化脚本的重用性和移植性较强,降低成本,提高效率和价值;
软件维护周期长,有生命力
自动化测试的需求稳定性要求、自动化框架的设计、脚本开发与调试均需要时间,这其实也是一个软件开发过程,如果项目周期较短,没有足够的时间去支持这一过程,那自动化测试也就不需要了;
被测系统开发较为规范,可测试性强
主要出于这几点考虑:被测试系统的架构差异、测试技术和工具的适应性、测试人员的能力能否设计开发出适应差异的自动化测试框架;
什么是UI测试
对于界面布局,传统的测试都是由人工对比设计图和产品界面。当界面有修改之后,再由人通过肉眼去检查修改(包括正确的和错误的修改),这样即费时而且测试结果又不稳定,因为人工对比测试存在两个巨坑:1.效率低;2.人的不确定性。对于拥有大量复杂界面的Web应用,界面布局的测试的数量巨大,再加上这两个问题,导致这类应用的界面布局测试/回归测试时间很长,成本很高,所以很多基于Agile(敏捷开发)项目基本不可能在迭代周期内高质量的完成其视觉测试。对于每天做一次,那更是不可能完成的任务。
视觉感知测试/视觉回归测试
为了解决上面提到的各种问题,视觉感知测试孕育而生。它使用传统的对图片进行二进制比较的办法,结合敏捷迭代开发的理念,产生的一种针对界面布局的自动化测试方法。
视觉感知测试
视觉感知测试就是对第一个版本的所有界面进行第一次测试。
视觉感知测试包含以下几个主要的测试步骤:
需要注意的是!
配对URL(忽略hostname)
通过配对URL,对所有的截图按照相同的URL进行分组。当然有时候会出现新的界面,有时候老的界面会被删除。对于新的界面就需要人工进行首次验证测试 。
像素级别的图形比较
对于分组之后的截图进行像素级别的比较并生产差别图。有时候为了降噪,可以只对局部关心的组件进行比较。
人工查看所有不同
最后通过人工审查差别图报告完成测试。
视觉感知测试结果:
预期(expected) | 实际(actual) | 比较结果(diff) |
---|---|---|
![]() |
![]() |
![]() |
视觉回归测试
我们认为如果一个界面通过第一次的人工验证并发布之后,它就是一个正确的标准界面,并且是包含了人工测试价值的资产。当下一次测试的时候,这部分价值就应该被保留并重用起来,用于减少新的一次测试的时间,从而实现界面的快速回归测试。
视觉回归测试包含以下几个主要的测试步骤:
回归和感知测试流程差不多只是差异值要更小一点,并且只有效果图需要替换内容。
视觉自动测试怎么做?
要进行视觉自动测试,有三种方式。
* 第一种是截屏比对(局部、整页)。
* 第二种通过JavaScript调用window.getComputedStyle()获取计算后的样式并进行断言。
* 第三种dom结构对比加css样式对比。
这三种各有明显的优势和不足。 第二种方式强绑定了实现,从而变得可能比较脆弱。 第一种方式离设计太近了,当页面中有可变内容时就会有问题。
第三种方式,无法进行视觉感知测试结果只能进行视觉回归测试和上一版的dom继续比较差异。
我更倾向与第一种截图对比;它的测试基于用户所见而不是用户所见的抽象。当然第三种也是非常好的 page-monitor 有兴趣的朋友可以自行了解。为什么第三种那么好为什么不使用呢?因为上面这个库是基于phantomjs并且它的实现方式过于复杂不适合新手玩玩。
像素对比工具,有哪些?
名称 | 地址 |
---|---|
PhantomCSS | https://github.com/HuddleEng/PhantomCSS |
GhostStory | https://github.com/thingsinjars/Hardy |
Cactus | https://github.com/winston/cactus |
Needle | https://github.com/python-needle/needle |
CSSCritic | https://github.com/cburgmer/csscritic |
sikuli | http://www.sikuli.org/ |
Mogo | http://mogotest.com/ |
pixelmatch | https://github.com/mapbox/pixelmatch |
pixel-diff | https://github.com/koola/pixel-diff |
好了介绍了那么多,怎么选一个合适的Headless Browser呢?
Headless Browser???我是视觉测试要无头浏览器干嘛?
因为有了像素对比工具我们还需要一个浏览器进行截图和设计图进行像素比较。
比较常见出名的几个Headless Browser,有哪些?
名称 | 内核 | 地址 |
---|---|---|
Puppeteer | Webkit | https://github.com/GoogleChrome/puppeteer |
PhantomJS | Webkit | http://phantomjs.org/ |
SlimerJS | Gecko | https://github.com/laurentj/slimerjs |
TrifleJS | IE | https://github.com/sdesalas/trifleJS |
PhantomJS 基于 Webkit 内核,不支持 Flash 的播放;SlimerJS 基于火狐的 Gecko 内核,支持 Flash播放,并且执行过程会有页面展示。
我们这里呢就只讲Webkit内核的,其他的我就不讲了。
PhantomJS简介:
PhantomJS
是一个基于webkit的JavaScript API。它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JavaScript代码。任何你可以在基于webkit浏览器做的事情,它都能做到。它不仅是个隐形的浏览器,提供了诸如CSS选择器、支持Web标准、DOM操作、JSON、HTML5、Canvas、SVG等,同时也提供了处理文件I/O的操作,从而使你可以向操作系统读写文件等。PhantomJS的用处可谓非常广泛,诸如网络监测、网页截屏、无需浏览器的 Web 测试、页面访问自动化等。
但是 PhantomJS
因为毕竟不是真实的用户浏览器环境,使用起来还是有不少的诟病。之前一直在使用 PhantomJS
,功能虽然够用,不过和在真实的浏览器里面访问的界面来对比差别还是比较大的。
Puppeteer简介:
Puppeteer
是Chrome团队开发的一个Node库。它提供了一个高级API来控制无头或完整的Chrome。它通过使用Chrome无界面模式 (Headless Chrome
)和DevTools
协议的组合来实现这一点。它使用一个更上层的API来封装其功能,让用户界面测试自动化变得轻而易举。
人们基于Chrome DevTools协议开发了一系列Google Chrome工具。你在浏览器中点击更多工具 ->开发工具,打开的就是DevTools。DevTools协议是DevTools的动力基础,我们现在可以使用Chrome中的DevTools来做更多的事情。
好了简介讲完了,我们来对比一下这两个Headless Browser的区别。
截图比较
代码:
PhantomJS:
var page = require('webpage').create();page.viewportSize = { width: 400, height: 400 };
page.open("http://localhost:8899/VS", function(status) {if (status === "success") {page.render("a.jpg");} else {console.log("Page failed to load.");}phantom.exit(0);
});
Puppeteer:
const puppeteer = require('puppeteer');(async() => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('http://localhost:8899/VS');await page.setViewport({ width: 400, height: 400 })//保存图片const images = await page.screenshot({ path: 'VS.jpg', fullPage: true, omitBackground: true });//关闭浏览器await browser.close();})();
Puppeteer | PhantomJS | Chrome浏览器 |
---|---|---|
![]() |
![]() |
![]() |
浏览器效果(大图):
好了看到这里已经可以分别出来胜负了。
使用puppeteer进行视觉感知测试
我们来做一个简单的dome
我们这里拿掘金来做一个视觉感知测试的例子。
1.首先创建项目名字就叫“PerceptionTest”把。
2.安装依赖
安装Puppeteer
npm install puppeteer --save
像素对比工具我就选我最常用的blink-dif了
npm install blink-diff --save
3.依赖安完了我们来创建一个js文件“app.js”
4.加载依赖
const puppeteer = require('puppeteer'),//无头浏览器BlinkDiff = require('blink-diff'),//像素对比imgUrl = __dirname + "/blink-diff_img/";//图片目录
5.使用puppeteer进行截图
(async () => {//创建puppeteerconst browser = await puppeteer.launch({ headless: true });//new 一个新的tab页面const page = await browser.newPage();//设置浏览器的尺寸await page.setViewport({ width: 1920, height: 945 });//打开urlawait page.goto('https://juejin.im/');//保存截图await page.screenshot({ path: imgUrl + 'Screenshots.png', fullPage: true });//关闭浏览器await browser.close();
})();
6.分析页面找到要替换的内容
为什么要替换内容呢,因为我们UI测试指的是测试界面样式而不是去匹配里面的内容,如果不替换里面的内容那像素对比工具比较出来的相似度肯定很低。所以我们要替换掉内容,要让内容完整统一,我们才好更加精确的去比较差异。
好了我们来分析一下要替换的内容。
要替换的内容如下:
1. 标题
2. 标签
3. 作者
4. 发布时间
5. 阅读数
6. 列表图片
7.替换内容
puppeteer提供了非常丰富的api,其中有个api叫page.evaluate可以向页面插入一段js。
await page.evaluate(async () => {//列表var Lists = document.querySelectorAll("div.feed.welcome__feed > ul > li > div > a > div");Lists.forEach(function (element, index, array) {element.querySelector("a.title").innerHTML = "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试";//替换标签element.querySelector("ul > li.item.category > span").innerHTML = "测试";//替换作者element.querySelector("ul > li.item.username.clickable > div > a").innerHTML = "测试";//替换发布时间element.querySelector("div.info-row.meta-row > ul > li:nth-child(3)").innerHTML = "9999天前";//替换发布时间element.querySelector("div.info-row.meta-row > ul > li:nth-child(4)").innerHTML = "99999999999 次阅读";//列表图片if (element.querySelectorAll("div.lazy.thumb.thumb.loaded").length==1) {element.querySelector("div.lazy.thumb.thumb.loaded").style.background = "#fdedc9";} else {var loaded=document.createElement("div");loaded.className=" lazy thumb thumb loaded";loaded.style.background = "#fdedc9";loaded.setAttribute("data-v-b2db8566","");loaded.setAttribute("data-v-009ea7bb","");loaded.setAttribute("data-v-f2ca14b0","");element.appendChild(loaded);}});});
8.使用Blink-Diff进行像素对比较
const diff = new BlinkDiff({imageAPath: imgUrl + 'example.png', // 设计图imageBPath: imgUrl + 'Screenshots.png',//页面截图//低于其中差异的像素数/ p(默认值:500) - 百分比阈值:1 = 100%,0.2 = 20%threshold: 0.02, // 1% thresholdimageOutputPath: imgUrl + 'Diff.png'//Diff路径});diff.run(function (error, result) {if (error) {throw error;} else {console.log(diff.hasPassed(result.code) ? '通过' : '失败');console.log('总像素:' + result.dimension);console.log('发现:' + result.differences + ' 差异.');}});
完整代码:
const puppeteer = require('puppeteer'),BlinkDiff = require('blink-diff'),imgUrl = __dirname + "/blink-diff_img/";(async () => {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();await page.setViewport({ width: 1920, height: 945 });await page.goto('https://juejin.im/');await page.evaluate(async () => {//列表var Lists = document.querySelectorAll("div.feed.welcome__feed > ul > li > div > a > div");Lists.forEach(function (element, index, array) {element.querySelector("a.title").innerHTML = "测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试";//替换标签element.querySelector("ul > li.item.category > span").innerHTML = "测试";//替换作者element.querySelector("ul > li.item.username.clickable > div > a").innerHTML = "测试";//替换发布时间element.querySelector("div.info-row.meta-row > ul > li:nth-child(3)").innerHTML = "9999天前";//替换发布时间element.querySelector("div.info-row.meta-row > ul > li:nth-child(4)").innerHTML = "99999999999 次阅读";//列表图片if (element.querySelectorAll("div.lazy.thumb.thumb.loaded").length==1) {element.querySelector("div.lazy.thumb.thumb.loaded").style.background = "#fdedc9";} else {var loaded=document.createElement("div");loaded.className=" lazy thumb thumb loaded";loaded.style.background = "#fdedc9";loaded.setAttribute("data-v-b2db8566","");loaded.setAttribute("data-v-009ea7bb","");loaded.setAttribute("data-v-f2ca14b0","");element.appendChild(loaded);}});});await page.screenshot({ path: imgUrl + 'Screenshots.png', fullPage: true });const diff = new BlinkDiff({imageAPath: imgUrl + 'example.png', // 设计图imageBPath: imgUrl + 'Screenshots.png',//页面截图threshold: 0.02, // 1% thresholdimageOutputPath: imgUrl + 'Diff.png'//Diff路径});diff.run(function (error, result) {if (error) {throw error;} else {console.log(diff.hasPassed(result.code) ? '通过' : '失败');console.log('总像素:' + result.dimension);console.log('发现:' + result.differences + ' 差异.');}});//关闭puppeteerawait browser.close();
})();
差异图
有差异 | 无差异 |
---|---|
![]() |
![]() |
git完整代码
git完整代码:https://github.com/my07ke/Perception_test
好了,欲知后事如何,请听下回分解。
点击链接加入群聊【前端|WEB|CSS|Javascript|HTML】:https://jq.qq.com/?_wv=1027&k=5hGQc2J
参考:
浅谈UI自动化测试
视觉感知测试
1.前端自动化测试 之 视觉测试相关推荐
- 7种前端自动化测试框架,到底谁是No.1
7种前端自动化测试框架,到底谁是No.1 互联网时代,我们对web前端进行测试,不应该只关注其功能是否实现,还有其它更多的测试内容,如样式是否符合预期.交互是否流畅.应用是否安全等各个方面. 前端自动 ...
- 搭建自己的前端自动化测试脚手架(一)
搭建自己的前端自动化测试脚手架(一) LancerComet at 17:55, 2016.07.17. 欢迎转载,转载时还请保留作者署名. 随着前端项目规模的日益膨胀,自动化测试越来越受到广大前端与 ...
- 搭建自己的前端自动化测试脚手架(三)
上一篇:搭建自己的前端自动化测试脚手架(二) By LancerComet at 23:47, 2016.07.22. 欢迎转载,转载时还请保留作者署名. 这是最后一章了!(・∀・) 之前我们配置好了 ...
- Node + ts + puppeteer e2e前端自动化测试
前言: 此文先在其他平台发表,如有雷同,有可能那个也是我~ 先了解一下概念 自动化测试的类型及工具都有挺多:单元测试.集成测试.UI测试.e2e测试等等,相关概念网上有挺多文章介绍了,就不多聊,比如这 ...
- 前端自动化测试工具:SlimerJS、phantomJS 和 CasperJS
对于富客户端的 Web 应用页面,自动登录.页面修改.抓取页面内容.屏幕截图.页面功能测试-面对这些需求,使用后端语言需要花费不少的精力才能实现.此时 SlimerJS.phantomJS 或 Cas ...
- 前端、后端、测试,究竟应该如何抉择?
最近,有朋友留言问我,0基础的小白,想转入IT行业,前端.后端和测试,哪个更好?笔者以为,道听途说,永远不如适合自己最重要. 我是一名从业8年的前端工程师,后端也略会一二,期间也兼职过公司的测试岗位, ...
- 测试与自动化测试,记测试工具Go4Api的诞生
自动化测试 如果搜索自动化测试相关的文章,看到的集中在两类:一是宏观上的关于手工测试和自动化测试的区别.自动化测试的优缺点.测试金字塔应该的结构(比如三角.倒三角.甜筒.梯形.洋葱.地球仪模型等),等 ...
- 前端自动化测试框架 Jest 极简教程
前端自动化测试框架 Jest 极简教程 Delightful JavaScript Testing. https://jestjs.io Jest是由Facebook发布的开源的.基于Jasmine的 ...
- web前端自动化测试(基于QT4W框架)
目录 web前端自动化测试(基于QT4W框架) 一.背景 1.1前端测试种类 二.技术方案 三.核心代码 3.1控件封装 3.2操作控件方法实现 3.3测试用例case 3.4断言方法 web前端自动 ...
最新文章
- 基于颜色特征,形状特征和纹理特征的数字图像的检索(Digital Image Retrieval)MATLAB GUI实现(本科毕业设计)
- AIX的用户和组管理
- 右键 Dos在这里 删除
- php 文档在线查看器,Office Web Viewer 在线Office文档查看器API
- salesforce lightning零基础学习(一) lightning简单介绍以及org开启lightning
- Caffe实战二(手写体识别例程:CPU、GPU、cuDNN速度对比)
- 1616: 最长回文串(马拉车算法)
- 学习响应式BootStrap来写融职教育网站,Bootsrtap第十天你的收获
- 电脑技巧:键盘上的这几个键,不常用,但有必要了解一下!
- Python实现生成100个MAC地址并写入文件中,MAC地址前6位(16进制)为01-AF-3B
- 总结XMLHttpRequest对象
- 初入行的C++程序员,如何快速摆脱CRUD阶段?
- win10下使用DuetDisplay有线/无线连接,推荐通过爱思助手(非iTunes)更新驱动
- origin自定义拟合,拟合公式带有复数i怎么办?用matlab能是实现吗?怎么实现呢,可以的话额能否给个示例。
- (四)keycloak 自定义用户(SPI)开发
- 计算机为什么硬盘值钱,数据到底有多值钱?看完硬盘数据恢复价格你就知道了...
- 【windows11】win10专业版 使用“安装助手” 直接升级到win11
- qq邮箱日历同步服务器,QQ邮箱,腾讯企业邮箱,让你的日程跟着手机走
- 使用pdfcrack破解PDF密码(Linux)
- nginx+tomcat 企业级jsp项目部署