收录待用,修改转载已取得腾讯云授权


作者:yangchunwen

首先要解释一下为什么叫浏览器自动化测试,因为本文只关注发布后页面功能的自动化测试,也就是UI层面的自动化。

浏览器测试有别于js代码的单元测试,后者一般是发布前的代码功能逻辑测试,在这方面已经有很多比较成熟的方案,如jasmine mocha Qunit...

为什么要做自动化

个人认为自动化测试的主要出发点有两点:

  • 减少重复的工作。让机器自动帮我们完成需要的交互操作,验证我们的页面功能。

  • 自动监控。通过自动回归我们的页面功能,可以在功能出错的时候提供报警,为我们手动排除问题提供参考。

开胃菜

说到浏览器自动化测试,不得不介绍大名鼎鼎的phantomjscasperjs。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();

以上代码主要做了三件事:

  1. 创建一个casperjs实例require('casper').create(),可以理解为一个浏览器进程

  2. 打开一个页面casper.thenOpen(...)

  3. 截取页面图像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结果,与报警等系统结合,可以实现各种强大的自动化功能。

问题

  1. 浏览器兼容。

    说到底,phantomjs(casperjs)提供的还是一个无界面的webkit内核浏览器,所以无法覆盖IE浏览器。目前Gecko内核的无界面浏览器已经有解决方案SlimerJS,并且支持与phantomjs一模一样的API。

  2. 设备兼容。

    在各种手机等终端设备良莠不齐的情况下,服务端的无界面浏览器在这点上更难以做到模拟所有的软硬件环境。

原文链接:http://ivweb.io/topic/55e46d8d771670e207a16bdc


原文链接:https://www.qcloud.com/community/article/641602001489391648

浏览器自动化测试初探 - 使用phantomjs与casperjs的更多相关文章

  1. [转] 浏览器自动化测试初探:使用 phantomjs 与 casperjs

    [From] https://www.qcloud.com/community/article/641602001489391648 作者:yangchunwen 首先要解释一下为什么叫浏览器自动化测 ...

  2. PhantomJS、CasperJS安装配置图文详解

    目前网站主流的加载方式: 一种是同步加载:另一种是异步加载,也即我们常说的用ajax.对于同步加载的网站,普通的爬虫程序轻松就能搞定.但是对于那种异步请求数据的网站,通常使用selenium+Phan ...

  3. PhantomJS与CasperJS在Windows下的安装与使用

    按照网上的教程来呢,一定是不好使的,这是常理. 所以必须要告诉你怎么使用Phantomjs…… 这么用! 1.下载Phantomjs的压缩包并解压缩: 2.在bin目录(包含phantomjs.exe ...

  4. [Python爬虫] 在Windows下安装PhantomJS和CasperJS及入门介绍(上)

    最近在使用Python爬取网页内容时,总是遇到JS临时加载.动态获取网页信息的困难.例如爬取CSDN下载资源评论.搜狐图片中的“原图”等,此时尝试学习Phantomjs和CasperJS来解决这个问题 ...

  5. 前端端对端测试:基于PhantomJS的CasperJS

    简介 Casperjs是一个基于PhantomJS和SlimerJS的前端端对端测试框架,当然你也可以使用它完成网络爬虫功能,它的特点的通过简单的脚本模拟浏览器行为, 主要有casper.tester ...

  6. Selenium浏览器自动化测试工具

    目录 Selenium浏览器自动化测试工具 Selenium模块在爬虫中的使用 Python简单使用Selenium Selenium的基本操作 Selenium爬取动态加载的数据 Selenium动 ...

  7. Python3+unitest自动化测试初探(中篇)

    目录 6.生成测试报告 7.编写邮件发送工具 8.发送邮件 发布 0 86 编辑 删除 Python3+unitest自动化测试初探(中篇)(2019-04-18 01:41) 发布 3 245 编辑 ...

  8. Python3+unitest自动化测试初探(下篇)

    目录 9.用例结果校验 10.跳过用例 11.Test Discovery 12.加载用例 unittest官方文档 本篇随笔承接: Python3+unitest自动化测试初探(中篇) Python ...

  9. 第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS

    第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS PhantomJS虚拟浏览器 phantomjs 是一个基于js的webkit内核无头浏览器 ...

随机推荐

  1. 关于button标签会刷新页面的问题

    当button标签在form表单里面时,这时点击button按钮会提交表单刷新页面. <form action=""> <button>点击</but ...

  2. 洛谷P2231 [HNOI2002]跳蚤 [数论,容斥原理]

    题目传送门 跳蚤 题目描述 Z城市居住着很多只跳蚤.在Z城市周六生活频道有一个娱乐节目.一只跳蚤将被请上一个高空钢丝的正中央.钢丝很长,可以看作是无限长.节目主持人会给该跳蚤发一张卡片.卡片上写有N+ ...

  3. Python之路【第四篇】: 函数、递归、内置函数

    一. 背景提要 现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码 while True: i ...

  4. Django+Nginx+uwsgi搭建自己的博客(五)

    在上一篇博文中,向大家介绍了Users App和Index的前端部分的实现,以及前端与Django的通信部分.至此,我们的博客已经具备一个简单的雏形,可以将其部署在本地的服务器上了.目前较为流行的we ...

  5. nyoj 269 VF 动规

    VF 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 Vasya is the beginning mathematician. He decided to make a ...

  6. []APC001

    题目质量都好高啊... A:求一个是$X$的倍数但不是$Y$的倍数的数,无解输出$-1$ 无解就是$Y|X$,否则输出$X$即可 B:给定$a_{1\cdots n},b_{1\cdots n}$,求 ...

  7. JDK源码(1.7) -- java.util.Map<K,V>

     java.util.Map<K,V> 源码分析 --------------------------------------------------------------------- ...

  8. 如何理解Hibernate中的HibernateSessionFactory类

    package com.zz.util; import org.hibernate.HibernateException; import org.hibernate.Session; import o ...

  9. ExtJS表格——行号、复选框、选择模型

    本篇的内容是为表格添加行号,和复选框,最后谈一下Ext的选择模型.内容比较简单,就直接上代码了.一. 设置行号   行号的设置主要问题在于删除某一行后需要重新计算行号  Ext.onReady(fun ...

  10. 一些WPF中的滤镜特效——Effect Library

    WPF支持类似PhotoShop的滤镜功能,称之为Effect.在.Net 4.0中,WPF就废弃了对BitMapEffect的支持,转向使用支持GPU加速的Effect类,例如,我们可以使用如下代码 ...