简介:Selenium是一个没有正式指导手册的开源项目,这让测试人员的问题调查很费时间。本文为基于Selenium1.0(发布于2009年6月)的测试期间的常见问题提供最佳实践。简介Selenium是一个健壮的工具集合,跨很多平台支持针对基于web的应用程序的测试自动化的敏捷开发。它是一个开源的、轻量级的自动化工具,很容易集成到各种项目中,支持多种编程语言,比如.NET、Perl、Python、Ruby和Java?编程语言。利用Selenium测试Ajax应用程序AsynchronousJavaScriptandXML(Ajax)是一种用于创建交互式web应用程序的web开发技术。Ajax应用程序的一个特征是,不会导致一次重新加载整个页面。相反,浏览器将具有一个对服务器的异步调用以获得数据,并且只刷新当前页面的特定部分。要提高web页面的交互性、响应速度和可用性,测试Ajax应用程序的过程需要一些改变。我们首先刷新web页面,然后就是等待,直到异步调用完成。完成之后,可以继续进行验证。此时,出现适当等待时间的问题。一种选择是在测试应用程序中简单地暂停一段固定的时间,这在大多数情况下都是可行的。在有些情况下,比如说网络吞吐量很慢时,Ajax调用在暂停一段特定的时间之后没有完成,会导致测试用例失败。另一方面,如果暂停时间太长,会使得测试慢得不可接受。Selenium提供了更为高效的处理等待的方式。一种可能做法是,使用类com.thoughtworks.selenium.Wait来等待一个元素或文本在页面上出现或消失。可以在until()函数中定义等待的退出条件,或者扩展Wait类来实现等待退出。清单1是使用Wait类的样例代码。它将在条件满足时停止等待,或者在超出最大等待时间时返回一个超时异常。清单1.等待元素或文本出现Waitwait=newWait(){publicbooleanuntil(){returnselenium.isElementPresent(locator);//orselenium.isTextPresent(pattern);}};wait.wait(,timeoutInMilliseconds);另一种选择是使用Selenium中的waitForCondition函数,一个JavaScript代码片段将被作为参数传递给该函数。一旦Selenium检测到条件返回为真,它将停止等待。您可以等待一些元素或文本出现或者不出现。JavaScript可以运行在由Selenium.browser.getCurrentWindow()函数弹出的应用程序窗口中。清单2是检查窗口状态的样例代码。它只工作在Firefox中。清单2.等待窗口就绪的状态Stringscript=varmy_window=selenium.browserbot.getCurrentWindow();script+=varbool;;script+=varreadyState=(my_window.document.readyState);;script+=if(readyState=='complete'){;script+=bool='true';;script+=};script+=bool;;selenium.waitForCondition(script,timeoutInMilliseconds);如何支持dojo应用程序Dojo是一个常用的JavaScript工具包,用于构造动态web界面。使用Selenium测试Dojo应用程序时的一个关键点是认识Dojo小部件和记录它们的操作。作者定义的Dojo小部件处于抽象级别。页面运行时,会将Dojo小部件转换成基本的HTML代码。存在很多由Dojo自动生成的HTML代码,因此,Dojo小部件的认识可能与传统HTML小部件有些不同。Dojo小部件上执行的操作(包括文本字段、按钮复选框和单选按钮)可能与HTML小部件相同。但是,Dojo在组合框上提供的日期选择器和其他额外的小部件可能需要特定的处理。图1.Dojo组合框使用SeleniumIDE来记录图1中提供的组合框上选中的操作。单击向下箭头,会出现一个下拉列表。选中第三项Stack(SWG)。记录的脚本提供在图2中。图2.SeleniumIDE记录的脚本有时,只会由IDE生成第二行脚本。在这种情况下,添加单击箭头按钮的操作。对于上面的脚本,如果第一行被重新播放,那么它应该生成下拉列表。但是它不执行任何操作。对于多个Dojo小部件,单击并不真正执行单击操作。将click(locator)更改为clickAt(locator,coordString)或者MouseDown(locator)和MouseUp(locator)。对于下拉列表,等待时间应该相加。像图2中展示的脚本一样,选中项的单击操作将会刚好在单击向下箭头按钮之后执行。它可能会因为下拉列表没有出现而失败。简单地添加一个pause命令,或者使用waitFor命令等待菜单项元素出现,并继续执行下一个命令。修改后的将会自动化Dojo组合框上的选择的脚本展示在图3中。图3.修改后的在Dojo组合框中进行选择的IDE脚本RC代码展示在清单3中。清单3.自动化Dojo组合框中选择操作的RC代码selenium.clickAt(//div[@id='widget_offeringType']/div/div,””);selenium.waitForCondition(selenium.isElementPresent(\offeringType_popup2\),2000);selenium.clickAt(offeringType_popup2,””);图4.日期选择器对于图4中的日期选择器例子,执行的操作可能不会被IDE记录。编写如下面清单4所示的RC代码。清单4.自动化选择的RC代码//clickonthedatefieldbyidyoudefined;selenium.clickAt(dateBox,);//waitforthedropdowndateboxbyid;selenium.waitForCondition(selenium.isElementPresent(\widget_dateBox_dropdown\),\2000);//clickpreviousyear2008;selenium.clickAt(//span[contains(@class,'dijitCalendarPreviousYear')],);//clickonthemonthincrease;//previousmonthwouldcontains‘dijitCalendarIncrease’.selenium.clickAt(//img[contains(@class,'dijitCalendarIncrease')],);//clickonthedatesuchas28ofcurrentmonth;Ifyoudonotspecify//thetdwiththeattributeofcurrentmonthclass,itwillclick\onthe//first28ofpreviousmonth;selenium.click(//td[contains(@class,'dijitCalendarCurrentMonth')]/span[text()='28']);如本例所示,Dojo应用程序不能通过简单的IDE记录进行测试。这些脚本有可能不能通过测试。脚本中有一些丢失的操作,或者操作并不真正工作。脚本应该调整成能够在IDE和RC中顺利地执行。对于复杂的Dojo小部件,一种可能的解决方案是使用runScript(String)函数,因为Selenium对JavaScript提供很好的支持。清单5提供一个JavaScript语句来模拟组合框选择。清单5.运行JavaScript语句在组合框上进行选择selenium.runScript(dijit.byId(\offeringType\).setValue(\Stack(SWG)););如何利用Ant构建Selenium测试诸如Ant这样的集成工具可以方便地构建Selenium测试和顺畅地运行测试用例,无需单独启动Selenium服务器。如果Selenium测试由TestNG驱动,那么定义清单6所示TestNGAnt任务。清单6中假设classpath是TestNG.jar文件的文件路径。清单6.TestNGAnt任务taskdefresource=testngtasksclasspath=testng.jar/主要的目标是启动服务器、运行测试,然后停止服务器。这些任务按照bulid.xml中定义的顺序实现在清单7中。清单7.启动服务器、运行测试用例并停止服务器的Ant任务targetname=run_testdescription=start,runandstopdepends=distparallelantcalltarget=start-server/sequentialechotaskname=waitformessage=Waitforproxyserverlaunch/waitformaxwait=2maxwaitunit=minutecheckevery=100httpurl==testComplete//waitforantcalltarget=runTestNG/antcalltarget=stop-server//sequential/parallel/target代码更可取的地方是使用waitfor任务来测试Selenium服务器是否已成功启动,而不是暂停一段固定的时间。如果URL=testComplete可用,就意味着Selenium已经成功启动。在清单7中,它最多等待两分钟,并且每100毫秒在本地主机上检查一次Selenium服务器,以提供完整的URL。start-server任务的详细内容定义在清单8中。Firefoxprofile模板位置和其他参数可以指定在标记arg中。清单8.详细的启动服务器的Ant任务targetname=start-serverjavajar=lib/selenium-server.jarfork=trueargline=-firefoxProfileTemplate${selenium}/profile///java/targetrunTestNG任务的详细内容定义在清单9中。testng任务的常用属性包括outputDir和xmlfileset。属性outputDir用于设置输出报告位置。属性xmlfileset用于包含启动XML文件。更多选项请参考TestNG正式网站。清单9.运行测试用例的Ant任务targetname=runTestNGtestngoutputDir=${testng.report.dir}sourcedir=${build}classpathref=run.cphaltOnfailure=truexmlfilesetdir=${build}includes=testng.xml//testng/targetstop-server任务的详细内容定义在清单10中。清单10.停止Selenium服务器的Ant任务targetname=stop-servergettaskname=selenium-shutdownsrc==shutDownignoreerrors=true/