浏览器自动化测试初探 - 使用phantomjs与casperjs
收录待用,修改转载已取得腾讯云授权
作者:yangchunwen
首先要解释一下为什么叫浏览器自动化测试,因为本文只关注发布后页面功能的自动化测试,也就是UI层面的自动化。
浏览器测试有别于js代码的单元测试,后者一般是发布前的代码功能逻辑测试,在这方面已经有很多比较成熟的方案,如jasmine mocha Qunit...
为什么要做自动化
个人认为自动化测试的主要出发点有两点:
减少重复的工作。让机器自动帮我们完成需要的交互操作,验证我们的页面功能。
自动监控。通过自动回归我们的页面功能,可以在功能出错的时候提供报警,为我们手动排除问题提供参考。
开胃菜
说到浏览器自动化测试,不得不介绍大名鼎鼎的phantomjs及casperjs。phantomjs可以理解为一个无界面的浏览器,可以通过流水线式的代码来驱动其页面的浏览行为,而后者是前者在易用性API上的一些封装。
这里演示下使用casperjs截取百度首页
关于这两个东西的安装,有兴趣体验的建议去看官方文档,其实很简单,这里不一一赘述。
首先创建一个js文件baidu.js:
var casper = require('casper').create();
casper.start();
casper.thenOpen('http://www.baidu.com/', function () {
casper.captureSelector('baidu.png', 'html');
});
casper.run();
以上代码主要做了三件事:
创建一个casperjs实例
require('casper').create()
,可以理解为一个浏览器进程打开一个页面
casper.thenOpen(...)
;截取页面图像
casper.captureSelector
在命令行运行
casperjs baidu.js
看看此脚本生成的图片结果
等等!为什么这个图只有400X300的大小?
原因是我创建了一个浏览器进程去加载页面,但是没有指明用什么浏览器去加载。所以在创建casper实例的时候,可以指定浏览器的窗口大小,甚至我们可以通过指定userAgent的方式冒充手机端的浏览器。例如我们将其指定为iPhone5的safari,并设置窗口大小:
var casper = require('casper').create({
pageSettings: {
// 冒充浏览器
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53'
},
// 浏览器窗口大小
viewportSize: {
width: 320,
height: 568
}
});
再次运行后我们的是这样,是不是手机浏览时的样子了?
简单应用
以上的例子,可以知道了怎么使用一个无界面的浏览器去加载页面,并获得页面的界面截图。
我们可以不打开浏览器,一行命令就可以知道页面长啥样了,所以每次我们只要运行这个casperjs脚本,通过截图就能看到我们页面是不是正常的。
但是,通过肉眼去判断,肯定是有违“自动化”的初衷的,所以必须要借助工具来帮我们分析。
最简单直观的办法就是“像素对比”,也就是把两次或多次的截图,逐一对比每一像素或一定范围区域,这样就能产出图片的差别了,如下图:
实际应用中,可以指定一个图片作为基准图,每一次我们截取的页面图与之对比,如果不一样,就可以说明线上的页面出现了异常。
像素对比这样的工具已经比较成熟,这里介绍一个与前端开发非常亲近的方案:Resemble.js。
为什么说它和前端亲近,因为它使用的是canvas。我们知道,每一个图片的每一像素,都可以通过RBGA(red,blue,green,alpha)三个值来确定:
Resemble.js的主要原理就是把我们需要对比的图片绘制到canvas中,读取需要对比的像素点(或区域)的image data,从而确定图片的差异。
为了与phantomjs/casperjs更好的结合,Resemble.js作者同时做了基于Resemble.js的封装phantomcss。
phantomcss使用了简单的API来做图片对比:
phantomcss.screenshot( "#CSS .selector1", screenshotName1);
phantomcss.screenshot( "#CSS .selector2", screenshotName2);
phantomcss.compareFiles(screenshotName1, screenshotName2);
假如对比的图片有不一致的地方,会生成一张对比图,同时有差异的地方会用显眼的颜色标出,类似这样:
注意
页面截图对比出现不一致,并不能证明我们的页面就出现了异常,例如广告位等,这些变化频繁的区域,每一次对比都有可能出现差异,所以对广告位或其他经常变化的位置不宜所差异对比。
实际应用中,对整个页面进行截图对比是不推荐的,这样的方式过于简单粗暴,我们更应该对页面的各个区域进行细分对比,做细粒度的监控。
cookie
既然是浏览器测试,不能没有cookie的参与,casperjs没有对cookie的操作作封装,可以使用phantomjs直接“种”cookie:
phantom.addCookie({
name: 'cookie',
value: 'value',
domain: '.xx.com',
path: '/',
secure: false,
httponly: false,
expires: Date.now() + (1000 * 60 * 60 * 24 * 5)
});
在前面的开胃菜中,我们访问到的页面都是没有登录态的,这里通过手动植入百度帐号登录态的cookie值来实现登录访问。
在PC端chrome中打开百度首页,并用你的帐号登录,在开发者工具中复制百度帐号关键cookie BDUSS的值
并hard code到你的casperjs脚本中:
phantom.addCookie({
name: 'BDUSS',
value: '你复制的cookie值',
domain: '.baidu.com',
path: '/',
secure: false,
httponly: false,
expires: Date.now() + (1000 * 60 * 60 * 24 * 5)
});
Done!右上角已经有用户名,说明此时我们已经登录了!
交互
简单的截图+对比还远远达不到我们的测试要求,对于自动化原则来说,为我们实现自动化的页面交互才是王道,别急,这就来。
前面介绍了手动种植cookie的方式实现登录,下面看下怎么实现手机端百度的登录过程。
先预览下整个脚本login.js的代码,下面解释一下整个过程:
1. 创建实例。与开胃菜中的配置基本一致,这里为了更快,实例化的配置选择了不加载图片
loadImages: false
2. 加载页面
3. 截取无登录态的页面:
casper.captureSelector('1.png', 'html');
这一步会得到图片1.png,并且右上角是没有用户名的(未登录):
4. 读取当前的所有cookie并输出
var cookies = phantom.cookies;
for (var i = 0, len = cookies.length; i < len; i++) {
console.log(cookies[i].name + ': ' + cookies[i].value);
}
这一步输出到命令行的结果:
可以看到,当前的cookie中还没有百度账号的关键cookie BDUSS。
5. 点击登录按钮
casper.mouse.click('#login');
casperjs(phantomjs)支持了非常丰富的可以支持复杂交互的鼠标事件:
- click
- doubleclick
- rightclick
- down
- up
- move
鼠标事件支持指定操作目标的CSS3路径
6. 点击登录后,会跳转到一个填写用户名和密码的登录页,这里为了方便,强行等待3秒确保登录页加载完
casper.wait(3000);
7. 截取登录页界面
casper.captureSelector('2.png', 'html');
8. 填写表单
casper.evaluate(function () {
document.querySelector('[name=username]').value = '***';
document.querySelector('[name=password]').value = '***';
});
这里使用了一个非常有用的方法evaluate。
9. 截取填写登录表单后的样子
10. 点击登录按钮
11. 等待跳转回首页
12. 截取登录后的首页界面
13. 逐一读取cookie并显示到命令行中
最后,运行测试脚本casperjs login.js
能得到4张截图,分别记录了整个登录交互过程中关键步骤的交互效果:
对比图1和图4,区别在于图4右上角的用户名:
同时,在命令行中最后还读取到了登录后的BDUSS cookie值:
再来点猛料
- iframe里的操作
phantomjs(casperjs)不仅可以在当前页面操作,还可以把当前context切换到iframe里进行操作,这点给嵌入iframe的页面测试带来了很多方便。
- 操作区域
phantomjs(casperjs)支持使用CSS3选择器及XPath的方式对我们需要操作的目标进行操作(点击、截图等),还可以通过指定区域边界的来操作,例如可以指定x/y坐标/width/height来进行点击或截图等:
casper.capture('capture.png', {
x: 200,
y: 300,
width: 200,
height: 300
});
交互的一些局限
现实世界的web里,有些交互功能不是机械的操作,有时候出于安全或其他因素考虑,页面会做一些限制,要求我们的交互需要根据一些动态输出,这种功能是很难做到完全自动化的,例如,上面的百度登录功能,有时候会出现验证码的情况:
这时候就很难借助机器来帮我们做登录了,所以在前面我要介绍通过手动植入cookie的方式实现登录。
单元测试
通过前面的介绍,使用phantomjs(casperjs)已经能实现很多自动化的功能,在此基础上,实现单元测试就很简单了。
casperjs提供了相对比较完善的单元测试API
单元测试中,每一个testsuite都被包装在一个闭包中:
casper.test.begin('your testsuite', 0, function (test) {
// 单元测试代码
});
例如下面是一个测试百度页面title及log位置是否正确的一组测试用例:
casper.test.begin('test demo', 0, function (test) {
casper.start();
casper.thenOpen('http://www.baidu.com/', function () {
// 测试页面title是否正确
casper.test.assertTitle('百度一下', 'page title');
// 测试logo的位置信息
// 获取x/y/width/height
var layout = casper.getElementBounds('#logo');
layout = JSON.stringify(layout);
// 验证是否符合
casper.test.assertEquals(layout, '{"height":87,"left":0,"top":53,"width":320}', 'logo\'s boundary');
});
casper.run(function () {
casper.test.done();
});
});
完整代码test.js在这里
运行casperjs test test.js
可以在命令行中看到以下输出:
两个case都已pass!
与前面的截图肉眼查看的方式相比,单元测试为我们提供了更加简洁的测试结果。
另外,casperjs的test模块还可以在测试后产出XML结果,例如上面那个例子的结果如下:
<?xml version="1.0" encoding="UTF-8" ?>
<testsuites time="2.228">
<testsuite name="test demo" tests="2" failures="0" errors="0" time="2.228"
timestamp="2015-08-31T13:30:12.462Z" package="test">
<testcase name="page title" classname="test" time="2.223">
</testcase>
<testcase name="logo's boundary" classname="test" time="0.005">
</testcase>
<system-out>
</system-out>
</testsuite>
</testsuites>
利用这个XML结果,与报警等系统结合,可以实现各种强大的自动化功能。
问题
浏览器兼容。
说到底,phantomjs(casperjs)提供的还是一个无界面的webkit内核浏览器,所以无法覆盖IE浏览器。目前Gecko内核的无界面浏览器已经有解决方案SlimerJS,并且支持与phantomjs一模一样的API。设备兼容。
在各种手机等终端设备良莠不齐的情况下,服务端的无界面浏览器在这点上更难以做到模拟所有的软硬件环境。
原文链接:https://www.qcloud.com/community/article/641602001489391648
浏览器自动化测试初探 - 使用phantomjs与casperjs的更多相关文章
- [转] 浏览器自动化测试初探:使用 phantomjs 与 casperjs
[From] https://www.qcloud.com/community/article/641602001489391648 作者:yangchunwen 首先要解释一下为什么叫浏览器自动化测 ...
- PhantomJS、CasperJS安装配置图文详解
目前网站主流的加载方式: 一种是同步加载:另一种是异步加载,也即我们常说的用ajax.对于同步加载的网站,普通的爬虫程序轻松就能搞定.但是对于那种异步请求数据的网站,通常使用selenium+Phan ...
- PhantomJS与CasperJS在Windows下的安装与使用
按照网上的教程来呢,一定是不好使的,这是常理. 所以必须要告诉你怎么使用Phantomjs…… 这么用! 1.下载Phantomjs的压缩包并解压缩: 2.在bin目录(包含phantomjs.exe ...
- [Python爬虫] 在Windows下安装PhantomJS和CasperJS及入门介绍(上)
最近在使用Python爬取网页内容时,总是遇到JS临时加载.动态获取网页信息的困难.例如爬取CSDN下载资源评论.搜狐图片中的“原图”等,此时尝试学习Phantomjs和CasperJS来解决这个问题 ...
- 前端端对端测试:基于PhantomJS的CasperJS
简介 Casperjs是一个基于PhantomJS和SlimerJS的前端端对端测试框架,当然你也可以使用它完成网络爬虫功能,它的特点的通过简单的脚本模拟浏览器行为, 主要有casper.tester ...
- Selenium浏览器自动化测试工具
目录 Selenium浏览器自动化测试工具 Selenium模块在爬虫中的使用 Python简单使用Selenium Selenium的基本操作 Selenium爬取动态加载的数据 Selenium动 ...
- Python3+unitest自动化测试初探(中篇)
目录 6.生成测试报告 7.编写邮件发送工具 8.发送邮件 发布 0 86 编辑 删除 Python3+unitest自动化测试初探(中篇)(2019-04-18 01:41) 发布 3 245 编辑 ...
- Python3+unitest自动化测试初探(下篇)
目录 9.用例结果校验 10.跳过用例 11.Test Discovery 12.加载用例 unittest官方文档 本篇随笔承接: Python3+unitest自动化测试初探(中篇) Python ...
- 第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS
第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS PhantomJS虚拟浏览器 phantomjs 是一个基于js的webkit内核无头浏览器 ...
随机推荐
- 关于button标签会刷新页面的问题
当button标签在form表单里面时,这时点击button按钮会提交表单刷新页面. <form action=""> <button>点击</but ...
- 洛谷P2231 [HNOI2002]跳蚤 [数论,容斥原理]
题目传送门 跳蚤 题目描述 Z城市居住着很多只跳蚤.在Z城市周六生活频道有一个娱乐节目.一只跳蚤将被请上一个高空钢丝的正中央.钢丝很长,可以看作是无限长.节目主持人会给该跳蚤发一张卡片.卡片上写有N+ ...
- Python之路【第四篇】: 函数、递归、内置函数
一. 背景提要 现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码 while True: i ...
- Django+Nginx+uwsgi搭建自己的博客(五)
在上一篇博文中,向大家介绍了Users App和Index的前端部分的实现,以及前端与Django的通信部分.至此,我们的博客已经具备一个简单的雏形,可以将其部署在本地的服务器上了.目前较为流行的we ...
- nyoj 269 VF 动规
VF 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 Vasya is the beginning mathematician. He decided to make a ...
- []APC001
题目质量都好高啊... A:求一个是$X$的倍数但不是$Y$的倍数的数,无解输出$-1$ 无解就是$Y|X$,否则输出$X$即可 B:给定$a_{1\cdots n},b_{1\cdots n}$,求 ...
- JDK源码(1.7) -- java.util.Map<K,V>
java.util.Map<K,V> 源码分析 --------------------------------------------------------------------- ...
- 如何理解Hibernate中的HibernateSessionFactory类
package com.zz.util; import org.hibernate.HibernateException; import org.hibernate.Session; import o ...
- ExtJS表格——行号、复选框、选择模型
本篇的内容是为表格添加行号,和复选框,最后谈一下Ext的选择模型.内容比较简单,就直接上代码了.一. 设置行号 行号的设置主要问题在于删除某一行后需要重新计算行号 Ext.onReady(fun ...
- 一些WPF中的滤镜特效——Effect Library
WPF支持类似PhotoShop的滤镜功能,称之为Effect.在.Net 4.0中,WPF就废弃了对BitMapEffect的支持,转向使用支持GPU加速的Effect类,例如,我们可以使用如下代码 ...