利用 Selenium 自动化 web 测试
上一篇 / 下一篇 2011-11-17 22:44:23 / 个人分类:loadrunner
查看( 3976 ) /
评论( 13 )
TAG:
- jenery 发布于2011-11-29 16:40:28
-
好东西,支持一下
- msnshow 发布于2011-11-29 21:49:50
-
[p=30, 2, left]如何支持 dojo 应用程序[/p][p=30, 2, left]Dojo 是一个常用的 JavaScript 工具包,用于构造动态 web 界面。使用 Selenium 测试 Dojo 应用程序时的一个关键点是认识 Dojo 小部件和记录它们的操作。作者定义的 Dojo 小部件处于抽象级别。页面运行时,会将 Dojo 小部件转换成基本的 HTML 代码。存在很多由 Dojo 自动生成的 HTML 代码,因此,Dojo 小部件的认识可能与传统 HTML 小部件有些不同。[/p][p=30, 2, left]Dojo 小部件上执行的操作(包括文本字段、按钮复选框和单选按钮)可能与 HTML 小部件相同。但是,Dojo 在组合框上提供的日期选择器和其他额外的小部件可能需要特定的处理。[/p]
图 1. Dojo 组合框
[p=30, 2, left]使用 Selenium IDE 来记录图 1 中提供的组合框上选中的操作。单击向下箭头,会出现一个下拉列表。选中第三项 Stack(SWG)。记录的脚本提供在图 2 中。[/p]
图 2. Selenium IDE 记录的脚本
[p=30, 2, left]有时,只会由 IDE 生成第二行脚本。在这种情况下,添加单击箭头按钮的操作。对于上面的脚本,如果第一行被重新播放,那么它应该生成下拉列表。但是它不执行任何操作。对于多个 Dojo 小部件,单击并不真正执行单击操作。将 click(locator) 更改为clickAt(locator, coordString) 或者 MouseDown(locator) 和 MouseUp(locator)。[/p][p=30, 2, left]对于下拉列表,等待时间应该相加。像图 2 中展示的脚本一样,选中项的单击操作将会刚好在单击向下箭头按钮之后执行。它可能会因为下拉列表没有出现而失败。简单地添加一个 pause 命令,或者使用 waitFor 命令等待菜单项元素出现,并继续执行下一个命令。[/p][p=30, 2, left]修改后的将会自动化 Dojo 组合框上的选择的脚本展示在图 3 中。[/p]
图 3. 修改后的在 Dojo 组合框中进行选择的 IDE 脚本
[p=30, 2, left]RC 代码展示在清单 3 中。[/p]
清单 3. 自动化 Dojo 组合框中选择操作的 RC 代码
selenium.clickAt("//div[@id='widget_offeringType']/div/div",””);
图 4. 日期选择器
[p=30, 2, left]对于图 4 中的日期选择器例子,执行的操作可能不会被 IDE 记录。编写如下面清单 4 所示的 RC 代码。[/p]
清单 4. 自动化选择的 RC 代码
//click on the date field by id you defined; selenium.clickAt("dateBox",""); //wait for the drop down date box by id; selenium.waitForCondition("selenium.isElementPresent("widget_dateBox_dropdown")", \ "2000"); //click previous year 2008; selenium.clickAt("//span[contains(@class,'dijitCalendarPreviousYear')]", ""); //click on the month increase; //previous month would contains ‘dijitCalendarIncrease’. selenium.clickAt("//img[contains(@class,'dijitCalendarIncrease')]",""); //click on the date such as 28 of current month; If you do not specify //the td with the attribute of current month class, it will click \ on the //first 28 of previous month; selenium.click("//td[contains(@class,'dijitCalendarCurrentMonth')]/span[text()='28']");
[p=30, 2, left]如本例所示,Dojo 应用程序不能通过简单的 IDE 记录进行测试。这些脚本有可能不能通过测试。脚本中有一些丢失的操作,或者操作并不真正工作。脚本应该调整成能够在 IDE 和 RC 中顺利地执行。对于复杂的 Dojo 小部件,一种可能的解决方案是使用runScript(String) 函数,因为 Selenium 对 JavaScript 提供很好的支持。清单 5 提供一个 JavaScript 语句来模拟组合框选择。[/p]
清单 5. 运行 JavaScript 语句在组合框上进行选择
selenium.runScript("dijit.byId("offeringType").setValue("Stack(SWG)");");
- msnshow 发布于2011-11-29 21:50:34
-
如何利用 Ant 构建 Selenium 测试
[p=30, 2, left]诸如 Ant 这样的集成工具可以方便地构建 Selenium 测试和顺畅地运行测试用例,无需单独启动 Selenium 服务器。如果 Selenium 测试由 TestNG 驱动,那么定义清单 6 所示 TestNG Ant 任务。清单 6 中假设 classpath 是 TestNG.jar 文件的文件路径。[/p]
清单 6. TestNG Ant 任务
<taskdef resource="testngtasks" classpath="testng.jar"/>
[p=30, 2, left]主要的目标是启动服务器、运行测试,然后停止服务器。这些任务按照 bulid.xml 中定义的顺序实现在清单 7 中。[/p]
清单 7. 启动服务器、运行测试用例并停止服务器的 Ant 任务
<target name="run_test" description="start,run and stop" depends="dist"> <parallel> <antcall target="start-server" /> <sequential> <echo taskname="waitfor" message="Waitforproxy server launch" /> <waitfor maxwait="2" maxwaitunit="minute" checkevery="100"> <http url="http://localhost:4444/selenium-server/driver/?cmd=testComplete" /> </waitfor> <antcall target="runTestNG" /> <antcall target="stop-server" /> </sequential> </parallel> </target>
[p=30, 2, left]代码更可取的地方是使用 waitfor 任务来测试 Selenium 服务器是否已成功启动,而不是暂停一段固定的时间。如果 URLhttp://localhost:4444/selenium-server/driver/?cmd=testComplete 可用,就意味着 Selenium 已经成功启动。在清单 7 中,它最多等待两分钟,并且每 100 毫秒在本地主机上检查一次 Selenium 服务器,以提供完整的 URL。[/p][p=30, 2, left]start-server 任务的详细内容定义在清单 8 中。Firefox profile 模板位置和其他参数可以指定在标记 <arg> 中。[/p]
清单 8. 详细的启动服务器的 Ant 任务
<target name="start-server"> <java jar="lib/selenium-server.jar" fork="true"> <arg line="-firefoxProfileTemplate ${selenium}/profile/" /> </java> </target>
[p=30, 2, left]runTestNG 任务的详细内容定义在清单 9 中。testng 任务的常用属性包括 outputDir 和 xmlfileset。属性 outputDir 用于设置输出报告位置。属性 xmlfileset 用于包含启动 XML 文件。更多选项请参考 TestNG 正式网站。[/p]
清单 9. 运行测试用例的 Ant 任务
<target name="runTestNG"> <testng outputDir="${testng.report.dir}" sourcedir="${build}" classpathref="run.cp" haltOnfailure="true"> <xmlfileset dir="${build}" includes="testng.xml" /> </testng> </target>
[p=30, 2, left]stop-server 任务的详细内容定义在清单 10 中。[/p]
清单 10. 停止 Selenium 服务器的 Ant 任务
<target name="stop-server"> <get taskname="selenium-shutdown" src="http://localhost:4444/selenium-server/driver/?cmd=shutDown" ignoreerrors="true" /> <echo taskname="selenium-shutdown" message=" Errors during shutdown are expected" /> </target>
[p=30, 2, left]上面列出了关键任务。将它们组合到您的构建文件,以便利用 Ant 完成良好集成的测试。[/p]
- msnshow 发布于2011-11-29 21:51:18
-
[p=30, 2, left]如何支持测试 HTTPS 网站[/p][p=30, 2, left]随着互联网日益强调信息安全,越来越多的 web 应用程序在使用 SSL 身份认证。Selenium IDE 默认支持 HTTPS,但是 Selenium RC 不是这样的。Internet Explorer 和 Firefox 中的解决方案各不相同。[/p][p=30, 2, left]对于 IE,在 setup 目录下的 SSL 支持文件夹中在安装一个证书。如果使用的版本早于 Selenium-RC 1.0 beta 2,请使用 *iehta 运行模式,对于 Selenium-RC 1.0 beta 2 或更晚的版本,使用 *iexplore 运行模式。[/p][p=30, 2, left]如果测试 HTTPS 网站时出现一个如下所示的安全警告,那么单击 View Certificate 并安装 HTTPS 网站的证书。如果继续弹出警告,那么考虑在 IE 中进行配置。打开 Tool > Internet Options > Advanced,并取消选择 security 分类下的 Warn about invalid site certificates 和 Check for publisher's certificate revocation。[/p]
图 5. 测试 HTTPS 网站时的安全警告
[p=30, 2, left]创建新的 Firefox 配置文件[/p][p=30, 2, left]对于 Firefox,遵循以下步骤创建定制的配置文件,然后重启服务器:[/p]- 关闭任何正在运行的 Firefox 实例。
- 利用配置文件管理器 firefox -ProfileManager 启动 Firefox。
- 创建一个新的配置文件。出现提示时,为配置文件选择一个目录。将它放在项目文件夹里面。
- 选择配置文件并运行 Firefox。
- 利用您将用于测试的自签名证书导航到 HTTPS URL。 出现提示时接受证书。这将在配置文件中创建一个异常。
- 关闭浏览器。
- 转到 Firefox 配置文件目录。
- 删除该目录中除 cert_override.txt 和 cert8.db 文件之外的任何东西。
- msnshow 发布于2011-11-29 21:52:40
-
[i=s] 本帖最后由 msnshow 于 2011-11-29 21:55 编辑
[p=30, 2, right]如何高效地认识不带 ID 属性的 web 元素[/p][p=30, 2, left]使用一个有含义的 ID 或名称是一种高效且方便的定位元素的方式。它也可以改善测试用例的可读性。但是为了每个元素具有一个有含义的、惟一的 ID(尤其是动态元素),Selenium 提供多种策略来认识元素,比如说 Xpath、DOM 和 CSS。[/p][p=30, 2, left]下面是一个样例,使用三种策略来定位图 6 中提供的动态表格中的一个元素。HTML 代码在清单 11 中。[/p]
图 6. 动态表格样例
清单 11. 第一个表格列的 HTML 代码
<table id="test_table" border="1"> <tbody> <tr> <td align="left"> <div class="test_class">Test 1</div> </td> <td align="center" style="vertical-align: top;"> <table id="AUTOGENBOOKMARK_4"> <tbody> <tr> <td align="center" style="vertical-align: top;"> <div> <img alt="supported" src="supported.png"/> </div> </td> <td align="center" style="vertical-align: top;"> <div> <a href="test?name=test1">edit</a> </div> </td> …….
[p=30, 2, left]Xpath 是一种找到不带特定 ID 或名称的元素的简单方式。[/p]- 如果知道 ID 或名称之外的一个属性,那么直接使用 @attribute=value 定位元素。
- 如果只知道属性值的一些特定部分,那么使用 contains(attribute, value) 定位元素。
- 如果元素没有指定的属性,那么利用 Firebug 搜索最近的具有指定属性的父元素,然后使用 Xpath 从这个元素开始定位想要找到的那个元素。
表 1. 定位元素的 Xpath 表达式
定位元素 Xpath 表达式
n 行的第一列 //table[@id='test_table']//tr[n]/td
n 行的图像 //table[@id='test_table']//tr[n]//img
‘Test 1’ 的编辑链接 //a[contains(@href,test1)]
[p=30, 2, left]表 1 展示了定位元素的 Xpath 表达式。在 Firebug 的帮助下,Xpath 可以定位元素和复制的元素。在元素没有 ID 和名称时,Selenium IDE 将会采用 Xpath。尽管 Xpath 利用已经录的脚本,有助于保持一致性,但是它高度依赖于 web 页面的结构。这使得测试用例可读性差,增加了维护难度。此外,在 Internet Explorer 7 和 Internet Explorer 8 中运行具有多个复杂 Xpath 表达式的测试用例可能会太慢了。在这种情况下,将 Xpath 更换为 DOM,后者是另一种高效的定位策略。[/p][p=30, 2, left]DOM 是 Document Object Model(文档对象模型)的缩写。Selenium 允许您利用 JavaScript 遍历 HTML DOM。Java 的灵活性允许在 DOM 表达式中有多个语句,用分号隔开,以及在语句中定义函数。[/p]
表 2. 定位元素的 DOM 表达式
定位元素 DOM 表达式
n 行的第一列 dom=document.getElementByIdx_x('test_table').rows[n-1].cells[0]
n 行的图像 dom=element=document.getElementByIdx_x('test_table').rows[n-1].cells[1]; element.getElementsByTagName_r('IMG')[0]
‘Test 1’ 的编辑链接
dom=function test(){ var array=document.getElementsByTagName_r('a'); var element;for(var i=0; i<array.length; i++) {if(array.attributes.getNamedItem("href").\ value.indexOf('test2')!=-1){element=array;break;}}return element}; test()
[p=30, 2, left]表 2 展示了定位元素的 DOM 表达式。DOM 定位器在 Firefox 和 Internet Explorer 中也有很好的性能。组织 DOM 表达式需要一些 JavaScript 知识。有时,DOM 表达式对于复杂的元素来说太长了,难以看懂(参见表 2 中提到的 Test 1 的编辑链接的表达式)。[/p][p=30, 2, left]CSS 定位器用于利用 CSS 选择器选择元素。当 HTML 代码具有良好的样式时,可以高效地利用 CSS 定位器。样例表达式展示在表 3 中。[/p]
表 3. 定位元素的 CSS 表达式
定位元素 CSS 表达式
n 行的第一列 css=#test_table .test_class:nth-child(n)
n 行的图像 css=#test_table tr:nth-child(n) > td:nth-child(2) > table td:nth-child(1) > div > img
‘Test 1’ 的编辑链接 css=a[href*='test2']
[p=30, 2, left]一般来说,选用熟悉的定位器表达式,并在脚本结构中保持一致。如果有多种表达式可执行,那么使用最高效的方式在 web 页面中定位元素。[/p]
- msnshow 发布于2011-11-29 21:53:40
-
[p=30, 2, right]如何处理弹出窗口[/p][p=30, 2, right]
一般来说,操作都是在由 Selenium 启动的主窗口中执行。如果您想在一个由 window.open 函数生成的新窗口中执行操作,那么将焦点更换到新窗口。在弹出窗口中执行操作之后,焦点返回到主窗口。处理弹出窗口的过程定义在清单 12 中。
[/p]
清单 12. 处理弹出窗口的样例代码
//wait for the popup window with timeout; selenium.waitForPopUp(windowname, timeout); //select the pop up window selenium.selectWindow(popupWindowIdentifier); //perform action on popup window and close the window; .... //return to the main window use 'null' selenium.selectWindow(null);
[p=30, 2, left]windowname 是调用 window.open 函数的第二个参数。上面提到的 popupwindowIdentifier 是一个窗口标识符,可以是窗口 ID、窗口名称、title=the title of the window 或 var=javascript variable。如果弹出窗口的属性未知,但是真的定义了,那么使用getAllWindowIds()、getAllWindowNames() 或 getAttributeFromAllWindows() 函数来检索弹出窗口的属性。[/p][p=30, 2, left]在最新版的 Selenium RC 1.0.1 中,Selenium 添加了像 selectPopUp(String) 和 deselectPopUp() 这样的方法,它们的功能在以前版本中由 selectWindow(String) 提供。[/p]
清单 13. 处理弹出窗口的弹出函数
//wait for the popup window with timeout; selenium.waitForPopUp(“”, timeout); //same as selenium.selectWindow selenium.selectPopUp(“”); //perform action on popup window and close the window; .... //same as selenium.selectWindow(null); selenium.deselectPopUp();
[p=30, 2, left]清单 13 展示了处理弹出窗口最简单的方式。您可以保留 waitForPopUp 和 selectPopUp 函数中的第一个参数为空。如果同时弹出多个窗口,请指定窗口属性。[/p]
- msnshow 发布于2011-11-29 21:54:13
-
[p=30, 2, right]回页首[/p][p=30, 2, left]如何处理上载/下载文件窗口[/p][p=30, 2, left]Selenium 使用 JavaScript 来模拟操作。因此,它不支持诸如上载窗口、下载窗口或身份认证窗口之类的浏览器元素。对于非主要窗口,配置浏览器跳过弹出窗口。[/p]
图 7. 安全信息窗口
[p=30, 2, left]跳过图 7 中安全信息窗口的解决方案是打开 Tools > Internet Options > Custom Level。然后启用 Display mixed content。[/p][p=30, 2, left]配置 Internet Explorer 跳过非主要窗口会减少或消除运行测试用例时不必要的处理。但是如果配置了 Firefox,那么将它保存为新的配置文件,并利用定制的配置文件启动服务器。在关于测试 HTTPS 网站的一节中提到了这样做的原因。[/p][p=30, 2, left]对于上载/下载窗口,最好是处理而不是跳过它们。为了避免 Selenium 的局限性,一种建议是使用 Java 机器人 AutoIt 来处理文件上载和下载问题。AutoIt 被设计来自动化 Window GUI 操作。它可以认识大多数 Window GUI,提供很多 API,并且很容易转换为 .exe 文件,这样的文件可以直接运行或者在 Java 代码中调用。清单 14 演示了处理文件上载的脚本。这些脚本的步骤是:[/p]- 根据浏览器类型确定上载窗口标题。
- 激活上载窗口。
- 将文件路径放入编辑框中。
- 提交。
清单 14. 处理上载的 AutoIt 脚本
;first make sure the number of arguments passed into the scripts is more than 1 If $CmdLine[0]<2 Then Exit EndIf handleUpload($CmdLine[1],$CmdLine[2]) ;define a function to handle upload Func handleupload($browser, $uploadfile) Dim $title ;declare a variable ;specify the upload window title according to the browser If $browser="IE" Then ; stands for IE; $title="Select file" Else ; stands for Firefox $title="File upload" EndIf if WinWait($title,"",4) Then ;wait for window with title attribute for 4 seconds; WinActivate($title) ;active the window; ControlSetText($title,"","Edit1",$uploadfile) ;put the file path into the textfield ControlClick($title,"","Button2") ;click the OK or Save button Else Return False EndIf EndFunc