【转】建立测试自动化框架

上一篇 / 下一篇  2013-01-28 11:53:49 / 个人分类:自动化

  测试自动化框架的建立并不意味着测试后期可以不再进行修改和维护,我们只是在力求将变化的风险降到最低点,而且一个好的框架的建立,不仅仅是由技术来决定的,必须由有效的管理以及一定的资金来支撑。

  软件测试作为保证软件质量和可靠性的关键技术,正日益受到广泛的重视。但随着软件工程的规模越来越大,客户对软件的质量要求越来越高,测试的工作量也越来越大,如何提高测试的质量和可靠性,就成为众多测试同行所考虑的问题,自动化测试也 随之进入大家视野。大家都期望自动化测试能够在测试效率、测试时间测试和人力资源成本上有一个质的提高,但是现在大多数项目中却难以实施测试自动化。当然 成功实施测试自动化涵盖很多方面,比如:公司的管理、制度、领导支持力度、资金的投入等等方面,但这不是本文所谈的重点,本文着重从技术的角度探讨测试自 动化。

  测试自动化失败的几个因素

  谈这个话题前我们先看一个自动化测试脚本(基于ruby语言写的一个watir框架应用测试脚本):

require 'watir'
ie = Watir::IE.new
ie.goto (http://www.google.com)
ie.text_field(:name, "q").set("pickaxe")
ie.button(:name, "btnG").click
ifie.contains_text("Programming Ruby")
 puts "TestPassed. Found the test string: 'Programming Ruby'. Actual Results match Expected Results."
Else
 puts "Test Failed! Could not find: 'Programming Ruby'"
end

   这是一个按照“pickaxe”关键字在google中搜索网页并进行结果校验的一段测试脚本。首先确认这是一个自动化测试脚本,但是也是一个维护性非 常差的测试脚本,如果在一个大规模的测试项目中大量存在这种测试脚本,无疑将导致测试自动化的失败。在此,笔者结合上面的案例探讨一下失败的几个因素:

  1、不适合实施自动化测试的项目

  在文章的开始,笔者已经表述了在项目中实施自动化测试主要为了三个方面:提高测试效率、缩短测试时间以及降低测试人员投入。所以必须在这三个方面进行衡量后才能决定是否采用测试自动化技术。根据笔者的经验,建议在如下几种类型的项目中不实施自动化测试:

  ● 周期很短的项目。在周期非常短的项目中,往往只需要1个初级测试人员花2周进行测试,在实施测试自动化时却需要1个高级测试人员花3周进行脚本开发,而且还不涵盖测试脚本后期的维护。

  ● 定制性项目。在此类测试项目中,业界往往在测试自动化方面积累很少。

  ● 易用性测试项目。往往此类测试与人类感观有关,比如界面的美观、声音的体验等等。

  ● 业务非常复杂的测试项目。此种类型的测试自动化几乎就等于测试人员同时开发了一套同样的程序去和开发的程序进行测试对比,此时测试时间投入远远大于手工测试时间。

  ● 涉及到物理交涉的项目。比如说银行的刷卡测试等等。

  任何一个技术都有它的局限性,就像我们不能拿着剪刀去劈柴,拿着斧头去裁减布料一样,测试自动化适合于周期长、需要经常地回归测试,有一定资金投入和测试人员投入的项目,比如:产品的研发测试等等。

  2、测试脚本通用性差

  在软件行业中流行这样的一句话“惟一保持不变的就是变化”,软件开发过 程的不断地变化导致了项目中需要不断地进行回归测试,此时正是体现自动化测试的优势所在,如果测试脚本不能做到一定的通用性这将很难适应软件的变化,比如 说上面的脚本,已经固化的测试执行流程,固化了所有的测试数据,如果哪天google查询时改用不是点击按钮进行查询了,那这个脚本就得重新修改。此时一 旦软件出现任何变更将导致测试脚本的修改或者重写,这将直接导致测试时间、测试人力资源的成倍的投入,从而很大幅度地降低了测试效率。

  3、测试脚本维护性差

   测试维护性往往包含两个方面:测试数据的维护以及测试流程的维护。在后面我们将探讨这两个方面,在测试后期测试自动化方面往往大量时间都放在测试维护 上,如果在测试脚本中没有很好涵盖这方面的类型也将同时导致测试的失效。比如说,测试数据框架设计上如果存在过多的固化成分,将导致脚本无法正确执行。


  4、脚本扩展性差

  测试人员在书写测试脚本时,往往只着眼于本身的测试项目以及已经规划好的测试案例进行定制,所以往往对测试脚本的可扩展性考虑的极少或者不考 虑,这个可能是测试人员非常容易犯的错误,因为脚本只是着眼于现有的案例,虽然脚本做了一定的通用性和维护性,但是因为固化的测试案例通常会固化测试人员 设计的思路,比如说:一个案例中3个输入条件通过测试行为得出一个测试结果,如果输入条件在程序中无法向后扩展的话,一旦测试案例的变更将导致测试脚本的 失效。

  测试变更的分析

  在上面花了大量的篇幅说明可能导致测试脚本失效的种种因素:维护性差、通用性差、扩展性差等等,实际归根结底是因为软件开发所产生的变更所导致 的。我们要完善好自身的测试自动化脚本,首先要分析我们需要考虑到那些变更,我们该如何来控制软件的变更,从而来实现软件测试的自动化。我们先来看一个测 试案例:

  1、打开google页面(www.google.com)

  2、在搜索框内输入“pickaxe”关键字

  3、点击“搜索”按钮

  4、等待下个页面的出现

  5、校验结果页面是否包含“Program-ming Ruby”这个关键字,“是”代表成功。“否”代表失败。

  首先我们分析一下这个测试案例,在以后的维护中可能产生的变更包括:

  1、测试数据导致的变更

  案例中pickexe,以及Programming Ruby输入和输出的测试数据都会变化。

  2、测试行为的变更

  打开测试页面(www.google.com),点击“搜索”按钮。

  3、测试步骤地变更

  本案例中共有5个测试步骤,在现实过程中有可能出现步骤地变化,步骤3先于步骤2。

  4、测试案例的组合变更

  在现实过程中不会只有一个测试案例,一套测试程序往往可能由成千上万个案例去执行,往往案例存在着相互依赖的关系,比如说:B案例的执行要依赖 于A案例执行的结果,而C案例又得依赖于B案例,而D案例却要依赖于B与C案例的执行结果。随着案例的量的增多,各种组合关系也越来越复杂,而且在维护期 经常出现组合关系的变化。

  所以本文将可能引起的测试变更分为四类:测试数据、测试行为、测试步骤、测试案例的组合。那么我们怎样有效地控制测试变更,如何在测试自动化脚本中有效地去解决这些问题?这就涉及到本文重点要提出的测试自动化框架。

  测试自动化框架

  本文之所以题为“测试自动化框架”而不是测试自动化,是因为测试自动化着眼于被测应用,而框架是在被测应用的基础上去实现一套方法去控制或管理 者测试自动化过程的变化,从而达到最大程度的不同条件下的测试自动化。在谈这个方面之前,本文首先提一下两种现在非常流行的测试自动化方法:数据驱动测 试、关键字驱动测试

  ● 数据驱动测试:从数据文件(数据池、ODBC源、cvs文件、Excel文件、DAO对象等)中读取输入和输出数值并载入到捕获的或手工编码的脚本变量中 的一种框架。在这种框架里,输入数值和输出验证数值都使用变量。在测试脚本中编写贯穿程序的导航、数据文件的读取、记录测试状态和信息的日志代码。

  ● 关键字驱动测试:要求开发与用来运行的自动化工具、驱动测试下应用程序和数据的测试脚本代码相独立的数据表和关键字。关键字驱动测试看上去非常象手工测试。在关键字测试里,应用程序的功能特性被写在表格和每个测试的详细指引里了。

  现在大多的测试自动化框架中都采用了这两种技术,但这两种思想主要论点就是围绕如何使测试数据与应用分离。实际在本文开始的测试脚本中就运用了 关键字驱动的测试技术。我们之前表述了测试变化的原因以及测试失效的根源,那么我们怎样搭建一个有效的测试自动化框架呢?本人认为框架应该具备如下一些特 点:测试数据驱动、测试流程总体控制;测试框架独立性;测试模块的原子性;测试模块的可扩展性。

  1、测试数据驱动、测试流程的总体控制

  在测试变化分析中,涉及测试数据和测试行为的变化,在使用测试驱动和关键字驱动的模式下,我们可以把测试行为作为测试数据的另外一种演变,如果在测试自动化中有效控制了测试数据和测试流程的问题,将完成了60%的测试脚本的自动化工程,首先看一下案例:

  < input type=image name=login value=Login src="/images/btn_signin.gif"

  这个案例是登陆时一个image的按钮,在案例中我们将点击按钮去进行下一步操作。如果采用关键字驱动模式,那么image是我们的一个行为数 据。而src、value、name等是image的内涵属性。 如果测试行为作为测试数据的话,因为测试数据在框架内很容易实现参数化控制,这样,我们就可以将测试行为作为驱动案例来执行,从而实现测试行为以及测试数 据的变更控制。这是一个测试点上的变更控制,但是一个系统由多个测试点组成,为了处理测试点复杂的依赖关系,我们采用流程总控方法。如何进行流程总控,同 样采用了数据驱动流程,通过有效的控制文件的定义,来驱动这个流程的运转。请参看图1、2所示的两个数据流程控制图。

  在第一个流程中,我们可以首先通过控制文件进行案例执行顺序的定义,然后由一套测试控制程序来总控流程的运转,然后通过程序的不断循环,进行整套脚本的自动化执行。

  在第二个流程中,同样会采用文件的方法去控制测试数据的变更,但这里我们将测试数据也进行分层控制。测试数据驱动最关键的技术,就是如何进行测 试数据框架的设计。在笔者的实践中,我们将测试数据同样分为三层:高级数据层(测试行为层)、中级数据层(数据操作层)、低级数据层(数据定义层)。数据 分层处理将有效降低数据的变化对测试脚本的影响。例如,一个登录案例:用户打开一个网页,在Userbox和passowrdBox中输入用户名 (1234)和密码(1234)后按登录按钮,我们尝试将行为数据和测试数据进行分类控制,来确保测试数据变化引起的变更最低。

  从数据定义框架来看,软件中出现任何变更,只要修改相应部分数据的定义,而不会影响测试脚本的变化。比如:测试操作中需要增加一个校验码时,我 们只需要在数据操作层增加一个校验码的行为,并补充上对应的测试数据定义层,程序仍然能够完成对应的测试操作,不涉及到程序的返工和重写等。而且程序的分 层定义,带来另外一个好处,就是测试框架具有可读性以及方便维护性。

  2、测试框架的独立性

  在测试数据独立性以及流程总控中,主要是控制由应用本身所引起的变化,在对于自动化框架来说,框架本身应提供足够的灵活性来支撑应用的变化,所 以自动化框架后三点:独立性、原子性、可扩展性,主要是围绕着框架本身来定义的。所谓的框架,它所适应的不能是某一个应用,而是同一类型的许多测试应用。 所以测试框架的搭建,最先要避开应用的框架,而去寻求这一类型的框架公共组件,使得测试框架具有更好的复用性,而且每个组件之间也应具有相对的独立性,这 样才能确保将影响降到最低。一个应用往往在测试行为上表现为需要点击什么按钮、选择什么菜单、下拉列表框,从不同类型文件中读取或者书写测试数据等等,不 同的应用,它所涉及到行为具有很多的通用性,只是数据选择的不同,所以测试框架搭建时,要提取这些通用性组件,然后进行封装,提供简易的接口交付上层的应 用框架调用。这样的独立性保证了框架的变更同样不会影响脚本的执行。例如:watir框架中提供的为tesxtfield填写数据函数:

  Object.text_field(:***, 'value').set(string)

  这个函数的发布,只要涉及到向textfield中填写数据的脚本,都可以调用,而不涉及到框架的修改,即使特殊的需求需要修改框架,只要框架的接口不发生变化也同样不会影响到上层的应用程序。

  3、测试框架的原子性

  测试框架的原子性在测试同行中也有人说是测试模块化。大家都知道如果把测试行为合在一起,虽然可能前期的开发会减轻,但往往后来的维护性非常 差。如果模块细化至最低层,那就将测试变化的力度控制在最小范围内,例如上面的登录案例,按钮点击可以说是最基础的一个操作,也是测试中控制的最小单位, 我们将这个行为作为一个原子封装起来,这样即使以后按钮的测试行为出现任何变化,我们的修改范围也仅缩小到button这一个函数内。如果独立性完成的非 常好,可能仅仅涉及应用的某一个点或者框架的某一个点上,而不至于修改整套脚本。所以测试框架第三个原则,在对框架分析过程中,尽量使得测试框架原子化。

  4、测试框架的可扩展性

  可扩展性往往是很多人忽视的方面,比如说:现在很多自动化测试框架在写button这个函数时,会提供按照名字或者值进行判断然后进行点击操 作,但是如果一个页面出现两个同名同值的button,而应用可以根据另外一个关键字来判断,但脚本中的其他页面都不存在这种问题,这时如果框架不提供足 够的可扩展性将会导致整个框架的失效,当然可以再次修改框架,但是时间的消耗远远大于扩展性的脚本开发。所以在测试组件设计时应考虑到维护时的可扩展的行 为。


TAG:

 

评分:0

我来说两句

Open Toolbar