Web功能性测试

在日常工作中,我们时常需要对网站进行功能性测试,测试网站的某些功能是否正常。简单的测试如网页是否进行了gzip压缩,网页编码是否正确,网页载入时间是否正常,网页缓存时间是否正常等。复杂一点的包括网页截图,网页在载入的时候是否弹出了alert对话框,是否有页面错位或者javascript错误,网页载入的资源是否是304或者200的响应等。更麻烦一点的是交互式的调试,调试页面上到底是哪段javascript/CSS代码导致了错误等。

简单的Web测试

对于简单的Web测试,例如只用查看HTTP响应头部与页面内容的,只需要一个爬虫抓取网页,同时对头部和内容进行分析即可。在Linux下可以使用wget和curl(它们也都有相应的Windows版本),如下:

使用wget和curl可以下载网页,查看HTTP头部信息,与awk和grep之类的工具使用,一般情况下都够了。不过如果涉及到HTML的DOM解析之类的工作,就力不从心了。在这个时候,你可以使用喜欢的语言来开发自己的小工具,例如Python。如果是这样的话,你可以先看看相关的注意事项。不过,你也可以使用现成的工具,例如httpie。这是一个用Python编写的类似curl的小软件,但是它打印出来的信息可读性更好,而且还有语法高亮。如果你喜欢用WSH + javascript来写,就需要用到XmlHttpRequest组件了,其用法和普通的ajax代码一样简单。

如果你不喜欢命令行程序,更喜欢交互式的图形界面的话,各个浏览器在工具菜单下也都有相应的开发人员调试工具。第三方的工具还包括Fiddler,IETester,Firebug,以及YSlow等。

其中Fiddler最为强大,可以通过代理的方式调试所有浏览器的HTTP行为,包括查看时间-流量图,本地修改javascript/CSS代码进行交互式调试等。而IETester可以同时测试IE5.5 ~ IE10的各个IE版本,保证网页在各版本的IE下都显示正常。Firebug是火狐浏览器的一个插件,拥有极多的调试功能,查看DOM树,查看时间-流量图,调试javascript等。YSlow是Yahoo做的一个浏览器插件,支持火狐,Chrome等浏览器,它能对你的网页进行检查,并为你的网页打分,并提出建议,以改善网页的性能,这些建议包括对网页进行gzip,将javascript放到尾部等。

PhantomJS测试

虽然一些简单的测试可以通过爬虫的方式来做,但是如果涉及到比较复杂的javascript代码和CSS渲染的话,就必须使用真正的浏览器了。毕竟自己实现DOM解析还相对容易,但是如果要做javascript虚拟机和渲染的话,工作量就太大了。

PhantomJS是一个无界面浏览器(Headless Browser),可以在后台运行,通过javascript代码控制,你可以用它来做网站测试(包括自动登录,表单提交等),页面截屏和流量监控。PhantomJS使用的是Webkit作为内核,能运行网页里的javascript代码和解析CSS/HTML以渲染页面,因此相当强大。在PhantomJS的examples目录中有很多例子可以学习,例如生成HAR流量图的netsniff.js等。下面是一个生成网站截图的例子:

顺便说一句,如果需要将查看HAR流量图自动化嵌入自己网站的,网上也有开源的程序可以使用。下面是用PhantomJS做出来的流量统计数据直接得到的HAR图。

HAR图

不过PhantomJS虽好,也有几个问题:

  • 不支持对IE浏览器特定特性的测试,毕竟PhantomJS是基于WebKit的,因此对于特定于IE的bug是无法检查出来的
  • 不支持对弹窗的检测,就是无法检测网页对window.open的调用,,也无法有效地截获新窗口的创建和弹出
  • 无法检测网页上的javascript错误

如果要解决上述问题,就需要自己做一个基于IE(Trident)的无界面浏览器了,网上可以参考的代码是CodeProject的这篇文章和SourceForge上的开源项目IECapt。

WSH javascript测试

由于我们网站90%以上的用户用的都是IE,而有一些代码也是特定于IE的,因此在测试的时候,必须要对IE进行自动化测试。

在Windows下进行自动化测试,自然要使用我最熟悉的WSH+javascript了,可以使用WScript对象和众多ActiveX组件来完成诸多功能,而且语法和普通javascript都一样,主要需要熟悉的就是各个组件的接口。

使用javascript进行IE测试的流程是:

  1. 通过WScript.createObject创建一个IE对象,并绑定它的事件回调(Event Callback/Sink)
  2. 调用IE对象的navigate2方法,打开指定的网页,并将其Visible属性设置为true
  3. 在IE对象的OnDocumentComplete事件中,检查网页是否已经完全载入(不然无法访问到document对象)
  4. 通过document对象访问各个HTML对象以及其计算出来的CSS属性,并模拟用户输入进行功能性测试
  5. 在最后调用IE对象的quit方法关闭IE,如果为了保险,可以找到所有的IE窗口,向其发送Alt+F4按键将其关闭
  6. 将得到的测试信息通过手机短信(如定制的HTTP接口)或者电子邮件(通过CDO.Message对象)发送到对应人员

上面是大致的流程,具体在开发过程中,还会遇到一些其他的问题:

  • 在javascript中如何创建与绑定事件回调
  • 如何在测试中绕过IE的阻止自动弹窗的设置,使得可以进行用户模拟点击打开新窗口的测试(不然弹窗会被阻止)

先说第一个问题。其实在创建一个ActiveX组件的时候,WScript.createObject方法第一个参数是组件名,第二个参数就是事件回调函数的前缀了。例如对于IE对象来说,它的组件名是InternetExplorer.Application,对应的事件有DocumentComplete、OnQuit等(参见DWebBrowserEvents2),假设我希望收到DocumentComplete事件通知,可以这样写代码:

在上面的代码中需要加入一个while循环,这样才能不退出程序,继而收到事件响应。

在HTML文档都已经载入完毕以后,就可以访问browser的document对象获取DOM树,进行一系列操作和测试了,例如通过document.getElementById('btnSumbit').click()模拟表单提交之类的。

另外,在IE中,如果通过代码模拟点击想产生一个新窗口,往往会被IE自动弹窗阻拦功能挡住,就是平时常见的顶部提示阻止了一个弹窗的细黄条。在测试过程中,我们往往需要模拟用户输入产生自动弹窗,这时候,需要在测试的时候去掉这个功能,然后在测试结束的时候再打开这个设置。要做到这一点,只需要修改注册表的HKEY_CURRENT_USER下的\Software\Microsoft\Internet Explorer\New Windows\Allow项,添加上对应的域名即可。在javascript里可以这样写:

另外,进行IE测试需要打开Windows桌面才行,因此它有一个比较郁闷的要求,就是不能是未登录状态。为了解决这个问题,我们开了一个Windows虚拟机,在虚拟机里面专门设置了计划任务运行这个代码。

更多WSH + javascript开发的事情,可以参见这篇文章。在这里有一个比较完整的WSH + javascript测试的例子,包括单元测试模板,测试页面链接,测试弹窗与模拟提交,测试结束后发送报警电子邮件等。

交互性调试

上面说的都是自动化测试,有的时候我们也需要进行交互式的调试,例如当页面出现了javascript或者CSS错误的时候。毕竟,每次为了调试都把代码放到vcs中,再通过cms发布出来看效果,不仅速度慢,而且也会在代码版本中带来无数的垃圾。

在上面我们已经提过,各个浏览器在工具菜单下也都有相应的开发人员调试工具,我们可以在相应的控制台下修改CSS和执行javascript代码。在javascript代码里,你可以访问和修改当前页面的所有变量和函数,例如将某个DOM元素的onclick事件修改成你希望的样子来调试,等等。如果javascript代码非常简单,也可以直接在浏览器的地址栏里输入javascript:window.alert(document.title);,以弹框显示出当前页面的标题。

不过对于iframe中需要访问top窗口的javascript代码,还有那些在页面载入和初始化时运行的代码,上面的方法就不适用了。在这个时候,我们需要使用Fiddler,让它在读取相应文件的时候就载入我们修改过的文件。Fiddler的使用方法可以参见这里,这里也有一篇类似的文章。

发表回复