基于TestNG 与Selenium 的自动化测试设计与实施
1、引言
软件测试是关系到软件开发和维护成本的重要环节。任何软件产品在正式发布之前都必须经过严格的测试。随着计算机技术的迅速发展,软件的结构越来越复杂,同业竞争越来越激烈。为了保证软件产品的高度可靠性和竞争力,很多软件开发机构都将其主要的研制力量投入到软件测试之中。
回归测试是软件测试中的重要组成部分,占有很大的比重。每次例行包发布前都需要对软件现有功能进行回归验证,确保无误以后才能发给各地现场,大家都知道电信业是个发展较快的行业,需求变更快、迭代周期短,从而导致回归测试十分频繁,这个时候如果单靠手工进行测试,会消耗大量的时间和精力,测试人员也随着耐心的减退而力不从心。为了避免这种情况,对于原有功能的自动化测试显得尤为重要。
2、工具介绍
说到开源自动化测试工具,网上众说风云,但别人说好的东西不一定适合你,我们在组合自动化测试工具时,根据自己的实际情况选择了 Selenium + TestNG + DBUnit组合,我先介绍一下这几种工具。
Selenium,它所采用的原理是通过录制应用程序产生的线性脚本进行回放从而达到自动化测试的目的。其优点是简单,通过录制就可以得到所需脚本。类似于录制/回放测试工具有很多,我之所以选择它的原因是它是开源的,而且它测试直接在浏览器中运行,就像真实用户所做的一样。Selenium测试可以在 Windows、Linux上的 Internet Explorer、Mozilla和 Firefox 中运行。其他测试工具都不能覆盖如此多的平台,更重要的是Selenium支持多种语言、JAVA、Ruby、Python等(如图1)
图1
支持这么多语言说明我们通过Selenium开发的测试脚本可以任意移植到多个平台,可以继承Selenium API来扩展一些我们自己的测试类,甚至可以在此基础上开发出一套属于我们自己的自动化测试平台,而其它工具,包括大名鼎鼎的QTP,SilkTest是有所不及的,虽然这些收费的软件后面有强大的技术支持,学习文档和参考资料也相当丰富,但这些工具的局限性太大,一旦使用这些工具,你就会越来越依赖人家的东西,从而无法沉淀出自己的技术,这是我选择Selenium的根本原因。
Selenium 系列一共有4款工具
Selenium Core:支持DHTML的测试案例(效果类似数据驱动测试),它是Selenium IDE和Selenium RC的引擎。
Selenium IDE:FireFox的一个插件,支持脚本录制。
Selenium RC:Selenium Remote Control。
Selenium Grid:允许同时并行地、在不同的环境上运行多个测试任务,极大地加快Web应用的功能测试。
通过selenium编写测试case的理想化是先通过Selenium IDE录制脚本,通过Firebug辅助定位页面元素,然后通过Selenium RC来完善测试脚本。Selenium IDE是Firefox的一个插件,是可以进行脚本录制以及案例转换,所以Selenium IDE+Firebug会成为你日后写测试案例的两大助手,但遗憾的是上述两个工具都依赖Firefox浏览器,如果你的程序不支持Firefox浏览器,就只能通过手工编码来完成自动化测试脚本,对于初学者来讲,如果没有这两个工具的辅助,在编写测试脚本时还是比较困难的,但熟悉了Selenium API和掌握了页面元素查找的方法以后,这两个工具就显得没那么重要了。
TestNG,单元测试工具典型代表,可能大部分开发人员只对JUnit比较熟悉,JUnit是 Java 语言单元测试当前的一站式解决方案。这个框架值得称赞,因为它把测试驱动的开发思想介绍给 Java开发人员并教给他们如何有效地编写单元测试。但是,在过去的几年中,JUnit的改进不大;所以,为当今复杂的环境编写测试已经变成一个越来越困难的任务,即 JUnit必须与其他一些补充性测试框架集成起来。而 TestNG是一个测试 Java应用程序的新框架。我选择TestNG是因为它是一种基于注释的测试框架,通过添加诸如灵活的装置、测试分类、参数测试和依赖方法等特性来克服JUnit的一些不足之处。此外,TestNG运行于Java 5.0(通过注释)和Java 1.4(通过JavaDoc样式的注释)之上。我来列举一下NG的优势:
关键字:参数化。TestNG将数据驱动的自动化测试的概念诠释的淋漓尽致,我举个例子,一个被测试方法根据不同的入参组合出20个CASE,根据数据驱动测试的思想,我们只需要写一个测试方法,然后准备20种参数组合的数据。如果使用JUnit你可能需要写20个测试方法,而TestNG通过注释就可以实现参数化。将20种不同的入参组合整理到一个Excel文件中管理,文件里可以增加用例描述甚至测试方案等相关信息,如果增加新CASE,只需要增加一行测试数据即可,如图:
测试方法只需要写一个,如图所示:
关键字:失败和重运行,在大型测试套件中,这种重新运行失败测试的能力显得尤为方便。这是 TestNG独有的一个特性。在 JUnit 4中,如果测试套件包括 1000项测试,其中 3项失败,很可能就会迫使您重新运行整个测试套件(修改错误以后)。不用说,这样的工作可能会耗费几个小时。一旦 TestNG中出现失败,它就会创建一个 XML配置文件(如图4),对失败的测试加以说明。如果利用这个文件执行 TestNG运行程序,TestNG就只运行失败的测试。所以,1000项测试有3项 Failed,这种场景你只需重新运行三个失败的测试脚本,而不是整个测试套件。
这里只列举了TestNG比较明显的优势,除了上述优势以外还有很多,这里就不详细阐述。
图4
DBUnit,它通过有效地管理测试场景中的数据简化了使用数据库的工作。其设计理念就是在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据,最后,在测试完毕后,读入备份数据库,回溯到测试前的状态,通过DBUnit还可以辅助数据持久层的测试工作,如验证一个实体通过被测试程序(DAO)进行持久化的操作是否正确,验证数据实体是否按照预期写入数据库,并且提供了将数据从数据库与XML文件存储中互相转换的功能。
上图是从客户表中导出的一条数据,如果测试过程中需要这条数据,那可以通过DBUnit将此条数据初始化到数据库中。
还有一种情况,如果是新增一个客户,那这个文件里的数据可以用来做断言预期的依据,DBUnit可以将xml转换为DataSet甚至 JavaBean,你可以直接通过数据集进行比较而不是每个字段都要比较一次。
不过DBUnit也有自己的缺陷,如上图所示,当通过DBUnit与数据库交互时需要检查表的主键,如果某张表没有设置主键就没有办法使用DBUnit的API,只能通过其它方式实现。
Fitnesse,业务驱动测试的工具代表,FIT是一种通用的开放框架,将测试人员编写的测试方法转换成表格的形式展现给客户,常用于自动化验收测试,在页面上以表格形式记录测试用例输入、预期输出内容,自动运行并显示测试执行结果。但是增加了开发人员一些工作量,要想让fit与你的软件通信,需要自己编写Fit fixture来实现业务与程序逻辑的转换。
3、自动化测试实施过程
通过上面几种工具的组合,灵活使用,就可以搭建出一套适合自己的自动化测试平台。
下面我来介绍一下,这些工具在不同测试场景下的使用情况:
1)接口测试
(TestNG+DBUnit)接口自动化测试可以通过单元测试来完成,利用TestNG对每一个接口编写单元测试代码,通过DBUnit初始化数据库,将一个或多个测试并被定义为<suite>标签,批量执行测试代码并生成测试报告。
2)Webservice接口自动化测试
目前大多数互联网公司都采用SOA架构,因此对于webservice接口类型的测试显得更加重要。通常测试工程师可能会借助SoapUI等工具进行web service的测试,不可否认SoapUI在进行单一webservice接口测试中具有非常好的效果,但是在接口组合测试,以及在测试结果需要进行数据库校验的情况下就显得不是那么的自动化,总是需要人工干预,这在一定程度上导致测试效率偏低,因此我们在这里介绍如何使用Fitnesse这块开源产品实现接口测试自动化(未完待有时间补充)
3)WEB应用系统的自动化(Selenium + TestNG + DBUnit)
TestNG 尤其适合与Selenium结合使用,可以实现其他测试框架无法实现的测试,例如使用依赖项进行测试,重新运行失败了的测试,以及使用单独文件中定义的参数进行参数化测试。所有这些特性结合在一起,使它在众多 Web应用程序测试框架中脱颖而出。
在测试自动化中,测试代码不仅仅包含测试逻辑,还包含许多其他的代码,比如URL拼接、Html/xml解析、访问UI控件,等等。若把测试逻辑与这些无关的代码混在一起,测试逻辑将很难理解,也不容易维护。而采用分层结构可以解决这一问题。在分层的测试框架中,其三层结构为:
(1)数据层,包含UI数据和测试数据;UI数据是指在页面中需要输入的数据,如,普通客户新装,你需要在页面里输入三户信息,包括订购的产品及资源数据。这些通过页面注入的数据我们统称为UI数据,需要在执行测试前提前整理到Excel中,如图所示:
实现起来比较容易,使用TestNG注释功能,就可以将这些数据作为页面的输入。而测试数据是指数据库中基础数据,这些数据是用来支撑整个系统运作的,比如操作员及组织权限,新装订购的套餐,套餐与产品的关系数据等等,没有这些数据,系统就没有办法正常运行,所以执行测试脚本之前要对这些基础数据进行初始化;还有一种情况当执行完一次测试脚本时产生的新数据会影响测试脚本的二次运行,这意味着运行任何测试之前,都希望数据库具有一组干净的数据,使用 DBUnit 的 CLEAN_INSERT 命令确保在先前运行的测试中创建的行被删除掉,因此我可以重新运行测试,该测试可以不断创建数据并且不用考虑数据库约束。将测试数据提前整理到xml文件,也可以从数据库直接导出到xml文件里,如图所示:
在执行测试脚本前,通过DBUnit将这些文件里的数据提前初始到数据库里,这样一来数据库就是程序所期望的样子。
(2)测试用例层,包含业务逻辑和控制逻辑。驱动程序WebDriver(Selenium2.0)负责UI数据的载入,在页面回放时将UI数据输入到页面中。前台页面回放完成后,数据进入持久阶段,这时需要比对后台业务处理逻辑,比如客户数据是否正确写入数据库,产品订购是否正确。由于输入的不同,场景的不同,业务逻辑比对也会不同,所以这块脚本的编写是整个环节中比较重要的部分。为了能够区分这些分支,需要将整个新装流程拆分多个模块进行管理,使用TestNG将测试用例分组,形成多个Test Suite进行控制。
(3)待测系统层,与测试端完全分离,被测系统只需要提供URL通过HTTP协议就可以被测试脚本调用执行。
4、自动化测试的持续集成
持续集成是一种软件开发实践,对于提高软件开发效率并保障软件开发质量提供了理论基础,持续集成保障了每个时间点上团队成员提交的代码是能成功集成的。换言之,任何时间点都能第一时间发现软件的集成问题,也能尽快将测试脚本投入生产使用。
通过SVN统一代码管理,在Ant或Maven脚本增加测试组件配置,当例行编译结束后即可以使用Hudson定时启动测试脚本的运行工作。运行结束后返回测试报告给测试人员。整个迭代周期如下图所示:
5、结语
软件自动化测试弥补了手工测试时重复劳动的缺陷,而且能在软件开发过程中尽早发现缺陷,因此实施自动化测试是非常有必要的。本文中介绍了几种自动化测试工具,通过不同的工具组合成适用自己的自动化测试框架,不仅使自动化测试在产品测试中发挥其独特的作用,而且还节约了资源成本,包括测试工具购买的成本以及人力资源成本等。