基于Selenium2和TestNG的自动化测试

非 Y 不嫁゛ 提交于 2019-12-05 20:31:35

【IT168 技术】Selenium是时下很流行的面向web的自动化测试工具,它以执行效率高,覆盖的浏览器广泛等优点得到了很多人的亲睐。TestNG是一款测试框架,它派生自JUnit和NUnit,除了继承了两者的优势之外,又额外的发展出了一些新的功能,让其更加强大和易用。文章会重点介绍Selenium2结合TestNG如何做自动化测试,另外也会介绍ReportNG,它是对TestNG report的一个扩展,它相较于TestNG自身的report而言,更加美观和易读。

  利用Selenium实现web自动化测试的优势

  相比QTP,RFT昂贵的成本,作为开源工具的Selenium WebDriver自然不用多说。而且selenium是一款基于浏览器的测试工具,因此在响应UI请求时运行速度比较可观,能很好的节省运行时间,提高执行效率。在与大多数测试平台的整合以及可扩展的脚本语言种类上(Java、dotNET、Perl、Python、Ruby、C#等)较之其他工具也有很大优势,最后,Selenium 支持多浏览器操作(IE,Firefox,Safari ),这也是其他测试工具所不具备的,当然,没有什么万能的测试工具,在全面评估被测系统和测试需求后,合适的就是最好的;而且在做自动化测试过程中,往往不能只单独使用一种自动化工具,结合不同自动化工具的优势来达到我们的目的是最佳的实践。

  Selenium的进化

  Selenium已经从之前的1.0(RC)进化到了现在的Selenium2(Selenium1+WebDriver)。

  在运行Selenium1.0程序之前,我们必须启动Selenium server端,也就是Selenium Remote control,我们简称RC,RC主要包括三个部分,launcher,http proxy,selenium core, 其中selenium core是由一堆javascript函数构成,通过调用这些函数,来实现对浏览器的各种操作。既然已经可以实现对浏览器的操作,那为什么还需要Selenium2(Selenium1+Webdriver)呢? Selenium1主要存在以下几个缺点1.没有原生的鼠标键盘事件;2.XSS/HTTP同源数据问题;3.popup dialog问题。Webdriver对不同浏览器的处理和Selenium1.0有着明显的不同,Selenium1.0不管是什么浏览器,都是由javascript来处理,而webdriver是选择浏览器最容易识别的语言来处理,比如在Firefox中javascript最容易,在IE中C++最容易识别,通过灵活选择最容易识别的语言来处理多浏览器,我们就可以很好的回避某些浏览器对javascript的安全限制,Webdriver不仅可以处理这方面的问题,而且可以调用操作系统API,尤其是当用户需要模拟鼠标键盘操作时,这项能力的作用表现的尤其明显。通过对比, 看来从Selenium1.0进化到Selenium2.0还是很有必要的。

  利用Selenium web driver实现自动化测试

  为了让整个文章更加充实,作者以一个简单的Scenario为例,来一步一步告诉读者如何利用Selenium WebDriver+TestNG+ReportNG来实现web自动化。注:该Scenario会贯穿整个文章。

  Sample Scenario:

  简要描述: 在Jazz.net上提问

  步骤:1.打开Jazz.net: https://jazz.net/

  2.点击Log in连接

  3.以某用户名登录

  4.输入密码

  5.点击Log In button

  6.验证Profile Image是否出现

  7.点击Forum连接

  8.点击Ask a question按钮

  9.在提问页面填写所有必填域,提交问题

  10. 验证问题是否提交成功

  11. Log out

  1. 为了快速产生一个自动化脚本,我们可以利用Selenium IDE来录制原始的脚本,然后根据需要把脚本Refine成为易于维护的版本(当然,如果你对Selenium的web driver的API很熟悉,并且有一个很好的测试框架可以采纳,也可以直接写脚本)。Selenium IDE是一个Firefox add-on,易于安装和使用,这里不做介绍,只附一张通过Selenium IDE录制上面的sample scenario的截图,图1:


▲图1 Selenium IDE

  录制完成之后,将其导出成Java/JUnit4/WebDriver格式(图2),并且命名为PostAQuestionInJazzDotNet。


▲图2 可以导出的Case的格式

  2. 在Eclipse IDE中建立一个Java project,建立如下的文件夹结构,图3


▲图3 初始的文件夹结构

 

  将刚导出的PostAQuestionInJazzDotNet.java放入cases文件夹,data文件夹用来存储脚本中需要用到的数据,map文件夹中用来存储脚本中用到的对象的属性信息,lib文件夹中用来放置所需要的依赖jar包。目前需要将selenium web driver相关的jar包放入到lib中,并且加入到build path中。

  打开PostAQuestionInJazzDotNet.java,修复编译错误,例如将包名修改为cases,如图4:


▲图4 通过Selenium IDE导出的JUnit格式的java脚本

  修复编译错误后的脚本应该已经可以运行,但基于以下原因,我们需要对脚本重构:

  a. 录制出来的脚本易读性一般。

  b. 数据/对象属性与测试逻辑混为一体,不便于维护。

  c. 导出的脚本是基于JUnit的,我们需要修改为TestNG的。

  3. 重构脚本

  3.1 将测试数据从测试逻辑中分离,也即参数化数据。

  我们采用csv作为存储数据的格式,如图5所示:(截图为通过Excel打开的显示的样式)


▲图5 以CSV格式来存储数据

  第一行为每个数据项指定一个逻辑的名字,以逗号分隔,从第二行起,在对应的数据列中填上脚本中要用到的数据值,支持多行数据的存储,便于以后实现数据驱动。

  创建DataHelper类,用于从数据文件中获取数据。

  其中包含的主要方法有:

  initFullAppData,用于将数据读入内存,代码片段如下:


▲图6 initFullAppData代码片段

  getAppData,用于根据数据项的逻辑的名字读取出某行的值,代码片段如下:


▲图7 getAppData代码片段

  在脚本中可以这样使用:

  在setUp方法中调用:DataHelper.initFullAppData(this, projectPath, cassName);

  然后在其他测试方式中可以直接通过DataHelper.getAppData("PostAQuestionInJazzDotNet_data:JazzURL",1);获得数据值,其中第一个参数是数据项的全名,第二个参数是该数据项的第几个值(这点是为了考虑做iteration,也即数据驱动测试所设置的)

  3.2 将web上的元素的属性值从测试逻辑中分离

  这里需要了解一下Selenium如何查找定位web元素。

  By.id

  By.cssSelector

  By.linkText

  By.name

  By.xpath

  By.partialLinkText

  通过以上的locator可以看出来Selenium支持利用多种属性定位,那我们需要将对象的属性存储在独立的文件中,便于维护和重用,因此我们以如下的xml的格式来存储元素的属性值,如下图:


▲图8 用XML格式来存储对象属性

  其中,例如 LoginLink为对象的逻辑名称,可以由测试人员自己定义;propertyName来指定用何种方式来定位元素,可选的值包括:id, name, link, dom, xpath, css, partiallink;value用来存储属性值。

  创建AutoObjectFactory类来管理对象属性文件,代码片段如下:


▲图9 AutoObjectFactory代码片段

  在脚本中可以这样使用:

  在case中定义:private AutoObjectFactory factory = AutoObjectFactory.createInstance(

  "PostAQuestionInJazzDotNet_map.xml", projectPath

  + File.separator + "map");

  然后在测试方法中通过:WebElement element = factory.getWebElement("PostAQuestionInJazzDotNet_map:userName", driver, defaultTimeOut);获得对象,然后调用相应的方法对其进行操作,例如:

  element.sendKeys(DataHelper.getAppData("PostAQuestionInJazzDotNet_data:userName",1));

  通过两步分离之后,脚本结构更加清晰,如下图所示:


▲图10 两步分离之后的脚本的代码片段

  看似测试数据与测试逻辑的分离,对象属性与测试逻辑的分离,有些额外的efforts要做,但从长远来说对于脚本的重用,维护都有很多益处,例如:对象和数据可以在多个脚本之间公用,如果对象或者数据有变化,只需要在其独立文件中修改,修改后的内容自然得以在引用它的多个脚本中生效。

 

  结合TestNG让自动化测试的流程掌控自如

  尽管目前的脚本结构已经很清晰,数据和测试逻辑也都分离开来,易于维护,但从测试调度的角度以及可重用的角度来看,还需要进一步改进。

  TestNG,即Testing Next Generation,下一代测试技术,是一套根据JUnit 和 NUnit思想而构建的利用注释来强化测试功能的一个测试框架,既可以用来做单元测试,也可以用来做集成测试。

  通常编写一个测试的过程有三个典型步骤:

  * 编写测试的业务逻辑并在代码中插入TestNG annotation

  * 将测试信息添加到testng.xml文件或者build.xml中

  * 运行TestNG

  在上述段落中我们的Sample scenario是一个相对长的测试用例,如果是将此用于手动测试,应该不失为一个好的测试用例,但是用在自动化测试中,我们期望可以尽可能模块化我们的脚本,以便于以后重用。模块化之后,我们就可以利用TestNG的Annotation指定该模块何时运行,以及运行顺序等,在多个测试用例中也可以重用。

  重新组织的Sample Scenario如下:

  1.打开Jazz.net: https://jazz.net/

  2.打开Login页面

  3.输入有效的登录数据

  4.进入提问页面

  5.填写提问内容

  6.提交提问

  7.验证提交是否成功

  8.Logout

  在重构脚本且给测试方法添加TestNG的Annotation之前,需要将Junit的Annotation去除掉,然后引入TestNG相关的Jar包:testng-6.*.jar,添加TestNG的Annotation。经过重构后,脚本片段如下:


▲图11 添加TestNG的Annotation

  利用TestNG的优势,我们可以把一些初始化/ 收尾工作的测试方法用@BeforeSuite/@AfterSuite,@BeforeGroups/@AfterGroups, @BeforeTest/@AfterTest等标记, 也可以用一些属性控制它是否不管什么情况下都执行,定义其依赖的方法等。

  例如:


▲图12 @BeforeSuite的用法

 


▲图13 @AfterSuite以及属性alwaysRun的使用

  为了定义测试的执行顺序,需要建立xml文件,定义执行顺序。具体的XML中各个节点和属性的含义请参阅TestNG官方站点。


▲图14 用于定义执行顺序的XML文件

  然后在main方法通过TestNG来读取xml文件以驱动测试的执行,代码片段如下:


▲图15 通过程序调用TestNG

  运行测试用例之后,产生的TestNG的report如下:


▲图16 TestNG自带的Report

  我们在充分了解了TestNG的各种Annotation以及如何控制其执行行为,就可以把模块化的测试方法调度的更好,也可以做到很好的重用。

 

  利用ReportNG生成美观易读的测试报告

  从上个章节中,我们可以看到TestNG有其默认的report,尽管其内容较全面,但不易阅读,因此我们想利用ReportNG来替代TestNG默认的report。

  ReportNG提供了简单的方式来查看测试结果,并能对结果进行着色,还可以通过修改模板定制化内容,修改CSS来替换默认的输出样式等。

  为了使用ReportNG,首先我们要引入reportng-1.1.4.jar和velocity-dep-1.4.jar,或者直接导入有其源代码,进行定制化。

  举例说明我们进行的一些定制化的内容:

  1. 默认的ReportNG的报告中,是以字母序对执行的方法进行排序的,这不是我们期望的,我们期望是以方法的执行先后顺序来进行排序的,故修改了TestResultComparator类,如下图:


▲图17 TestResultComparator代码片段

  2. 希望报告中显示的信息更加详细,且有截图,故定制化了模板文件/本地化文件等,如图:


▲图18 本地化Properties文件


▲图19 报告输出模板文件

  3. 在ReportNGUtils中添加截图的相关方法,如下图所示:


▲图20 截图的相关代码片段

  4. 在main方法中修改代码,使得testNG使用定制化后的report作为报告输出。


▲图21 修改Main方法

  再次运行该测试用例,得到的测试报告如下:

  Overview


▲图22 报告的总体预览

  Details


▲图23 报告的详细测试结果

  截图可以放大/全屏观看,如下图:


▲图24 报告中的截屏点击后的效果

  结束语

  一套成熟的自动化框架是需要在项目实践中持续优化的,只有不断的实践才能发现问题,解决问题,积累经验,逐步完善。希望作者提供的这一实践可以给读者一些借鉴,但这一实践还远远未达到完善的地步,我们愿意和大家一起多思考,多交流,结合自己的项目特性灵活运用,合理改进已达到能真正运用工具解放日常繁琐劳动,提高效率,保证质量的效果。

  作者简介

  皇甫鹏: IBM CDL高级软件工程师, QA lead,从事自动化测试工具的设计和开发,以及创新工具的开发等。在Developworks和其他期刊上发表过多篇文章。

  陈宇:IBM GDC 软件测试工程师,主要从事功能测试,自动化测试

  余新龙: IBM GDC高级软件测试工程师,主要从事Web自动化测试。

====================以上为博文正文=======================================

2013-09-06安全测试工程师必读:解析SQL注入攻击

 

2016年2月23日 8:20lele-16的blog [上海市网友]

写的很好,有源码吗?https://jazz.net网站慢得要命

 

2015年10月26日 23:24Mc_scofield

此文章只适合高手看看,大致思路清晰,但是作为一个新手的我还是一头雾水<br /> 
1、自定义的截图方法在哪里调用?<br /> 
2、截图方法中调用的其他方法没有贴出来<br /> 
总之,,求源码啊。。。哭死

 

2015年7月12日 19:24IT168网友

博主你好,看了您的博文很受启发。我是一个TestNG和Selenium新手,现在准备使用TestNG+Selenium对一个邮件系统做自动化功能测试,有几个问题想请教。<br /> 
<br /> 
1.邮件系统有这样几个测试用例:1).Login;2)SendMail;其中SendMail需要首先登录才能进行邮件发送。我使用@dataprovider来提供数据,并将测试数据存放在XML中。我将SendMail和Login独立写的,也就是说SendMail中不涉及Login处理。测试Login时有三组测试数据,SendMail有4组测试数据(在该测试数据中不涉及Login相关数据)。<br /> 
<br /> 
在这个场景下,我希望测试SendMail功能时,首先调用Login登录进去(此处只使用Login三组测试数据中的正常登录的那一组),然后调用SendMail测试对应的4组数据,我该如何组织测试数据和这两个测试用例。<br /> 
<br /> 
2.在测试SendMail功能时,只需要测试发送端发送成功还是需要再登录到收件人查看收件人是否正确收到所发的邮件,这样SendMail才算通过?

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!