Sahi 是 Tyto Software 旗下的一个基于业务的开源 Web 应用自动化测试工具。Sahi 运行为一个代理服务器,并通过注入 JavaScript 来访问 Web 页面中的元素。Sahi 支持 HTTPS 并且独立于 Web 站点,简单小巧却功能强大。它相对于 Selenium 等自动化测试工具,在动态 ID 元素查找和隐式页面等待处理等方面具有一定的优势。选择 Sahi 工具来实现具体 Web 项目的自动化测试是一个很不错的选择。
Web 测试背景
随着 Web 技术和互联网的发展,Web 应用产品越来越丰富,基于 Web 页面测试的需求与日俱增。在当前全球软件都在追求高效、敏捷的开发模式的大背景下,Web 自动化测试成为了新一波技术探讨和研究的热潮。因为传统的手工测试不仅效率低,并且测试质量受限于测试人员的一些情绪和心情。若当一个测试人员带着烦躁情绪来测这些繁杂的大量重复性工作,测试的质量令人担忧。更何况,当这项测试工作涉及到全球化方面的测试时,多语言版本的测试工作导致该测试工作量的成倍增加,这无疑是一项巨大的考验!
Sahi 的特性和优势:
当提及面向 Web 的自动化测试,相信许多读者会想到或者说使用过 Selenium、Watir 等工具,而对于 Sahi 就可能比较陌生。首先,让我们先来了解下 Sahi 工具。它是一款印度公司 Tyto Software 开发的成熟的开源 Web 自动化测试工具。Sahi 简单易用,能良好支持 Ajax 和 Web2.0 技术,同时适用于敏捷和传统的不同测试模式。那么,它与其他非常流行的 Web 自动化测试工具有哪些不同和优势呢?让我们将其与主流自动化测试工具 Selenium 和 Watir 来进行一番对比,请参考图 1:
图 1. Sahi 与其他工具的对比
从上图的对比可以看出,Selenium 支持的脚本语言比较丰富,且自带 Selenium IDE 自动录制工具,Watir 执行的速度相对其他较快。而 Sahi 同样具备了自带的录制器,且支持几乎所有浏览器,且对 JS 支持较好,拥有页面等待判断机制,内置 Java 异常报告,支持 Ajax 等优势。
下面,本文将详细介绍一下 Sahi 的几大优势。
基于上下文的页面识别机制:
大多数如 Selenium 等 Web 自动化测试工具或是自动化框架,都采用类似基于 DOM 的定位策略、Xpath 定位策略和 id、name、identifier 等页面元素定位策略。
Identifier 定位是最普遍的一种定位方式,当不能识别为其它定位方式后,默认为 identifier 定位。在这种策略下,第一个使用 id 的页面元素将被识别出来,如果没有使用指定 id 的元素,那么将识别第一个名字与指定条件相符的元素。
例如,identifier 识别 username 元素的定位策略:identifier=username
Id 定位是在知道元素具体 id 特征的情况下的一种更精确定位。例如,定位页面元素 loginFrom:id=loginFrom
name 定位方式是去识别第一个匹配名称属性的 UI 元素。如果多个元素拥有相同的名称属性,可以使用 value 过滤器来进一步优化您的定位策略。例如,定位页面元素为 username:
name=username
Xpath 定位是在 XML 中定位元素的方法,而 HTML 可以被看作是 XML 的一种实现。XPath 扩展了上面 id 和 name 定位方式,提供了绝对路径和相当路径两种查找方式。
绝对路径:html/body/div[1]/div[1]/div[3]/div[1]/form/span/input[1]
相对路径查找://div[@id='fm']/form/span/input
然而,在实际的情况下,页面元素并非如预期般明确。一些动态页面的 DOM 树常常随着 Web 产品的更新而频繁改变。许多的元素值如 ID、Name 等在代码中并不是必须的,常常会缺省。并且,属性值往往不是唯一对应的,页面中有时会存在相同属性的元素。当缺省 id 值或是 Xpath 定位失效时,上述这几种查找定位方式往往显得无助和脆弱。
Sahi 采用了一种主动查找的机制,它不受限于特定的元素属性。在没有 ID、Name 值的情况下,它可以使用一些如“title,value”等属性,这些都是页面可见的属性,所见即所得。同时,Sahi 会通过传入这些可见可识别的属性值,来按照 Sahi 预设的机制进行查找识别。Sahi 允许开发者对每一种元素设置不同属性和特定的查找顺序,包括那些自定义的属性名。所以 Sahi 相对于其他的 Web 自动化测试工具更灵活更开放。
比如,_link(“valueName”)用来定位一个定义为“valueName”的 link,这里的 valueName 并不一定是 value 的属性值,也可以是它的 id、title 等。
前面提到了 Sahi 主动查找的机制,那么它是如何去查找 DOM 节点下的特定元素的呢?Sahi 主要提供了三种基于上下文的元素 API:_in,_near 和_under。
从字面意思上,我们不难理解,_in 是指在某个 DOM 节点下查找某个元素,这比 Xpath 的不管是绝对路径或是相对路径查找都来的灵活,不会因为 DOM 树内部结构发生变化而导致路径失效找不到元素的问题。
_near 是指在某个元素附近查找相应设定规则条件的最近一个元素,这对于一个页面中有多个相同属性值的情况提供了一个很好的解决方式,使查找的范围更精确。
_under 是指在某个元素下方开始查找,找到符合条件的最近一个元素,一般_under 都适用在具有相同偏移量的同一列中。下面,我们来看一个例子,加深对 Sahi 这种基于上下文识别查找机制的理解:
图 2. 案例网页
假设,在图 2 显示的 Web 页面的所有 text box 的 name=”q”,那么,Sahi 的侦探器通过一些标识来鉴别它们,如(_textbox("q"), _textbox("q[1]")和_textbox("q[2]"))。
如果,我们要定位“Ruby for Rails”那一行的 text box,即_textbox("q[1]")。传统的元素识别会遇到多个相同属性元素的问题,即使是 Xpath 的定位方式也会因为在它前面加了一行新的数据而导致 Xpath 定位失败的情况。
这时 Sahi 可以通过_near 这种方式来定位:
_textbox("q",_near(_cell("Ruby for Rails")))
当要定位 check box 时,我们又会发现,“Ruby for Rails”这一行有“Recommend”和“Already own”两个 check box,为了更准确地定位,我们可以结合_under,例如:_checkbox(0,_near(_cell("Ruby for Rails")),_under(_cell("Recommend")))。
如果在整个页面中存在多个这样的表格,我们还可以用_in 来进一步缩小范围,如:_checkbox(0,_near(_cell("Ruby for Rails")),_under(_cell("Recommend")),
_in(_cell("Cost))).
同时值得一提的是,Sahi API 中的 identifier 参数都支持正则表达式,例如,_div(/name.*/) 用来识别所有以某种预属性值是 name 开头的 div。
隐式页面加载响应等待机制:
现在越来越多的 Web 应用采用 Ajax 的应用技术,来支持网页数据的异步请求响应。当前一般的 Web 自动化测试工具没有一个智能的处理机制,来判断何时可以继续下一个操作。像 Selenium 等自动化测试工具通常会在脚本中人为来设定一个固定的等待时间。但这往往被证实不一定是准确的。实际测试中,人是很难准确判断每一个操作请求需要的合理时间数值。因为,等待时间设置过短,下一步操作在被测应用请求还未返回就执行了,或是由于网络因素使正常的响应时间变长,都可能导致测试过程找不到相应的页面元素,从而导致整个测试用例失败的情况。而如果把时间设置过长,又会造成在一些正常响应过程中的不必要等待的时间浪费,降低了测试效率。
当然,一些测试人员会在自动化测试脚本中加入一些自定义的代码。通过轮询界面上某个指定元素,来判断请求响应是否返回,进而决定继续下一步操作或者是超时。但是,这样的查找过程会导致整个脚本代码变得非常臃肿,加大了开发的成本。更何况,在一个动态的页面找到指定的元素本身就不是一件容易的事。
Sahi 内置了智能的页面等待机制,能够自动判断 Ajax 请求是否已经处理完毕,然后继续下一步操作。并且,这一点对于用户是“隐式”的,不需要增加额外的代码。
Sahi 的工作原理:
简单地说,用 Sahi 实现自动化测试有三步,录制,精炼脚本和回放,如下图:
图 3. Sahi 工作的三个主要过程
如上图 Sahi 就是先用其自带的录制工具,把大致的操作过程录制下来,并用 Sahi 代码记录下整个操作过程。随后,将自动生成的代码进一步的精炼和开发,调用一些外部 API 或编写特定代码来实现特定的操作。最后,用 Sahi 来回放保存好的最终脚本,Sahi 就将自动对 Web 应用进行定义好的测试操作。
下面,本文将对这三个过程进行详细说明。
第一步:录制
图 4. Recording 过程的工作原理
Sahi 是通过运行为一个代理服务器,并通过设置浏览器代理为 Sahi 服务器。这样 Sahi 的脚本就能够通过 request 请求来注入到 JavaScript 里以访问 Web 页面中的元素。如图,可以很清晰的看到,Sahi 就是 Web 浏览器和 Web 服务器之间的一个中间代理。
第二步:精炼脚本
图 5. Refine Script 过程的工作原理
录制的脚本都是指定元素并唯一操作的,这时就需要对代码进行重构,抽取出核心的功能块,对其中的元素进行参数化处理,以实现重用。这样的数据可以从外部的 DB 或文件中读取而来。与此同时,也可调用 Sahi API 或外部 Java 等 API 实现特定的一些功能。
第三步:回放
图 6. Play back 过程的工作原理
Sahi 运行提炼好的脚本来自动化测试操作,并生成测试报告。
Sahi 的安装部署与配置
Sahi 虽然是 Tyto 公司的产品,但它的下载放在世界上最大的开源软件开发网站 SourceForge 上,可以通过点击这里下载。
图 7. Sahi 下载
默认推荐是下载 install_sahi_xxx.jar,这是一个可执行文件,包含了 Sahi 的安装器和 Sahi 工具及其源代码。当然您也可以点击上图红框处“Browse All Files”来选择历史版本和一些免安装压缩文件。比如,选择只包含 Sahi 工具的 sahi_xxx.zip 文件,或者包含了 Sahi 和源代码的免安装压缩包文 件sahi-src_xxx.zip。
一般建议选择推荐的 Sahi 安装包文件即可,这样可以免去一些设置操作,并可以选择是否安装源代码。双击 jar 文件进行安装,如图:
图 8. Sahi 安装
安装过程非常简单,待安装完成后双击桌面图标打开 Sahi 程序。打开程序先会出现一个 Sahi Dashboard,它能自动开启 Sahi 代理服务来启动浏览器,而不需要繁琐的代理服务器设置操作。当然如有需要,您也可以手动修改这些代理设置。
图 9. Sahi Dashboard 界面
Sahi 会自动去侦探您系统里安装的一些浏览器,并在 Sahi Dashboard 上显示出来,如果发现有一些其他的浏览器未被准确侦探出来,您也可以点击下面的“Configure”来进行配置添加进来。
接下来,通过点击 Sahi Dashboard 上的浏览器图标按钮来启动相应浏览器。
图 10. Sahi 启动 firefox 浏览器
您可以输入起始测试的网页 URL 开始您的测试。如果测试的目标 URL 是 HTTPS 协议的,也可以点击“SSL Manager”来查看和管理 SSL 证书。
图 11. Sahi SSL 管理界面
按住 Alt 键并双击页面,将弹出 Sahi 控制窗口,如图 12:
这个窗口相当于 Sahi 的主控台,在这里我们可以来录制和回放 Sahi 脚本,并编辑和管理脚本信息。
图 12. Sahi Controller 录制
在 Record 视图界面,输入一个脚本名称,点击“Record”,这时 Sahi 录制器便开始工作了。把鼠标移到浏览器上的目标网页上,您的所有操作过程都将被记录下来。您也可以自定义增加一个 Assertion。按住 Ctrl 键,把鼠标移动到目标网页的任意一个 HTML 元素,那么这个 Accessor 会自动出现在 Sahi 控制器中。这时,便可以自定制对该元素的操作。常用的操作有“点击”,“高亮”,“赋值等。同时,您可以通过“Append to Script”按钮来加到脚本代码中。录制完成后按“Stop”来结束整个过程。
图 13. Sahi 自动生成脚本精炼
图 13 是一个简单的 Sahi 自动录制过程得到的 Sahi 脚本代码。其大致过程为:通过百度搜索“sahi”关键字,校验 Sahi 官网的 assert 是否存在,点击进入 Sahi 官网后继续校验 assert“Community Forums”,点击进入。通过前一节“Sahi Controller 录制”来完成这个操作过程,那么,您可以在默认目录“C:\Users\IBM_ADMIN\sahi\userdata\scripts”中找到先前命名为“Test_sahi”的脚本文件,我们可以将这段代码进行一个精炼和丰富的过程,比如在点击“Community Forums”链接前将它进行高亮操作:
_popup("Sahi Web Test Automation Tool")_highlight(_link("Community Forums"));
或者您想在 Sahi 脚本代码中调用内置的 Java 类,例如:
functionprintThroughJava(s){ java.lang.System.out.println("Through Java: "+s);} printThroughJava("Hi there");
“Through Java: Hi there”将在 sahi 的命令行中输出。
图 14. Sahi Controller 回放
回放的时候,只需要在 Sahi 控制台上切换到“Playback”tab 页面,找到脚本存放的路径,下面就有开始、暂停和结束等按钮来进行操作。需要注意的是,开始以前必须给它设置一个“Stat URL”否则无法回放脚本。脚本回放的时候,在“Statements”里可以看到脚本运行的日志,比如操作步骤和一些错误信息等。
通过点击右下角的“View Logs”可以查看详细的 Sahi 运行日志报告:
图 15. Sahi 日志报告
由图可见,这样自动录制生成的脚本代码都是 Sahi 代码,我们可以在实际的 Java 项目中调用这些 Sahi 代码,以实现重用。其实,我们可以通过打开 sahi/config/sahi.properties 文件将其中属性设置为 controller.mode=java 来实现自动录制脚本的语言为 Java。值得注意的是,改为 Java 语言录制后的 Sahi 控制器和原来有所不同,它的界面更简洁,功能也更简单一些,没有了自动回放功能。因为,这更多是为了自动生成一些简单的脚本,来提高开发人员的开发效率。
Sahi 的语法与示例应用
Sahi 脚本是基于 JavaScript 的,而 Sahi 脚本是通过代理解析的,并能够在 rhino JavaScript 引擎中有效执行的。除了变量前的强制符$,它和 JavaScript 基本很像。
Sahi 操作的代码声明是一句以分号结尾的普通代码行,如:
_click(_link("Login"));
变量声明:
var$variableName =value;
或者先声明再赋值:
var$variableName;// declaration $variableName =value;// assignment
所有的变量都是以$符号开头的,关键字 var 用于局部变量,如:
var$username ="SahiTestUser"; var$password;// declaration; $password =$username +"_password";// "SahiTestUser_password"
函数声明:
// function declarationfunctionlogin($usr,$pwd){ _click(_link("Login")); _setValue(_textbox("username"),$usr); _setValue(_password("password"),$pwd); _click(_submit("Login")); } // function call login("sahi_user","secret");
在一个 Sahi 代码文件中可以通过_include来包含调用其他 Sahi 文件,如:
_include("includes/common_functions.sah");
由上面的语法可知,Sahi 是由下划线开头,带上操作或 HTML 元素,非常简单,清晰易懂,这些 API 基本都是能够看字面就能理解它的功能。
Sahi 的 API 主要可以分为 3 类:浏览器访问 API、浏览器操作 API和混合 API。
浏览器访问 API:用于访问浏览器上的元素,并通过代理来注入这些 API 到浏览器中去。
浏览器操作 API:主要来执行一些如点击、输入数据等操作,并在浏览器上声明这些元素的。
混合 API:是既能在浏览器又能在代理上用于处理异常和操作文件和数据库的。
由于 Sahi 对网页的访问方法的 API 很多,大家可以参考官方 API 文档进行学习。
由上可知,Sahi 脚本都是很直接的声明和操作过程,在一个运行的代理上,由 Sahi Dashboard 来管理执行。如果我们希望能够将我们的 Sahi 自动执行的过程与我们其他的项目功能模块进行集成,那么把这些脚本转换成 Java 代码,又能用独立运行,是一件两全其美的事。
接下来,本文将介绍一个用 Sahi Java Driver 来编写 Sahi 自动化脚本实现 Web 自动化测试的简单案例。
首先,将 Sahi 的开发库包文件 sahi.jar 加入到 Java 项目中,该文件位于 Sahi 安装路径下..\sahi\lib\下,接下来就可以参考 Sahi 的 Java API 来开发自动化测试脚本。下面是一个简单的案例脚本:
清单 1. 导入 Sahi 类包
import net.sf.sahi.client.Browser; import net.sf.sahi.config.Configuration;
设置 sahi 安装路径和 userdata 路径
清单 2. 配置 Sahi 代理
String sahiBase = "C:/Users/ADMIN/sahi/"; String userDataDirectory = "C:/Users/ADMIN/sahi/userdata"; Configuration.initJava(sahiBase, userDataDirectory);
您可以设置任意一种浏览器类型,也可以在 sahi/userdata/config/browser_types.xml 文件中自己创建定义
清单 3. 配置浏览器并启动
String browserType = "firefox"; Browser browser = new Browser(browserType); browser.open();
清单 4. 操作代码示例
browser.navigateTo("http://sahi.co.in/demo/training/"); browser.textbox("user").setValue("test"); browser.password("password").setValue("secret"); browser.submit("Login").click(); browser.textbox("q").setValue("2"); browser.textbox("q[1]").setValue("9"); browser.textbox("q[2]").setValue("4"); browser.button("Add").click(); System.out.println(":: browser.textbox(\"total\").value()=" + browser. textbox("total").value()); browser.close();// close the browser
需要注意一点,除了 Firefox 浏览器,其他的浏览器都必须进行服务器代理配置,并在运行脚本前打开 Sahi 代理服务。
实际测试结果表明,Sahi 代码简介,运行轻巧快速,而且它还能与外置的一些模块集成完成发送邮件,读取 PDF 文件等操作,功能非常完善。
结束语
综上所述,本文从当前 Web 自动化测试的困境出发,通过与其他开源 Web 自动化测试进行对比,介绍了 Sahi 的特性和优势。主要从基于上下文页面识别机制和智能页面加载响应等待机制两方面进行阐述。同时,详细介绍了 Sahi 的工作原理以及如何安装部署进行自动化测试开发的过程。总之,Sahi 提供了一套在多浏览器和多编程语言的开源自动化测试方案,解决了当前一些页面元素难找,页面响应不同步而导致测试失败的问题。Sahi 是一个能够快速部署,易于开发并且功能强大的开源 Web 自动化测试工具。由于篇幅所限,本文不能对 Sahi 所有的功能进行一一阐述,希望有兴趣的朋友一起研究探讨。