sunshinelius 发表于 2010-11-29 10:03:17

在AC上开发和运行QTP自动化测试脚本

本帖最后由 sunshinelius 于 2010-11-29 10:08 编辑

AC应用案例:金融系统自动化测试
对于金融业务系统来说,测试案例往往涉及到数据校验,交易确认,业务关联等等,手工测试执行起来比较复杂,更不用提自动化测试的实施了。这也是当前金融系统业界功能自动化测试程度不高的原因之一。
1 金融系统业务测试的复杂性
比如某个银行支付系统的转账案交易,手工测试大概的流程如下:1. 创建Test Account A和Account B,并在各自名下建立相应权限的转账卡2. 使用Account A登录银行转帐系统,使用名下某一张卡对Account B做转账交易,支付金额为1000元人民币.3.
查看Account A和B的余额,确认A账户减少1000元,B账户上增加1000元。
以上三个步骤从银行业务角度来看是各自独立的三个功能,但在转账场景里,又有密切的联系。步骤2依赖于步骤1的先决运行,步骤3则需要步骤2的转账数据。使用QTP等工具针对以上案例开发脚本,则会面临棘手的问题,如果把三个功能写在一个脚本里,就会大大降低每个功能脚本的复用性。若开发成三个不同的脚本,那么彼此的关系和数据交互又需要增加额外的开发成本来实现。
2使用AC的观点完成TestJob的定义
在AC的世界里,一切都得非常简单,三个功能将被定义成三个TestJob。Create_Account_Info负责创建测试账户A和B,然后将accountA,accountB作为参数输出。 在AC中做如下定义:
<QTP name="Create_Account_Info" description="以管理员身份登录后台系统创建测试账户及相关卡信息 " depends="" >
         <JobOutput name="accountA"/>
          <JobOutput name="accountB"/>
         <Lib location=”common\lib\lib_utility.vbs”/>
            <Run path="testcase\qtp\admin_createaccount"></Run></QTP>
其中admin_createaccount是录制好的qtp脚本路径, lib_utility.vbs是脚本使用到的lib文件,AC将会自动加载到QTP运行环境中。Transfer_FromAToB则会运行转账交易,将account A里的款项转给account B,并将转账数额作为参数输出。在AC中做如下定义:
<QTP name="Transfer_FromAToB" description="以账户A登录,转账给B账户"depends=""Create_Account_Info" >
         <JobInput name="accountA"/>
         <JobInput name="accountB"/>
         <JobOutput name="transfer_amount"/>
      <Lib location=”common\lib\lib_utilityvbs”/>
            <Run path="testcase\qtp\transfer_bank"></Run>
</QTP>
Verify_Account根据输入的两个account信息和转账金额,检查account的余额是否预期变化。在AC中做如下定义:
<QTP name="Verify_Account " description="检查账户A和账户B的余额是否预期变化 " depends="" Transfer_FromAToB " >
      <JobInput name="transfer_amount"/>
      <JobInput name="accountA"/>
          <JobInput name="accountB"/>
         <Lib location=”common\lib\lib_utilityvbs”/>
         <Run path="testcase\qtp\transfer_bank"></Run>
</QTP>

以上三个TestJob被AC组织起来,将会根据depends关系计算出执行路径:Create_Account_Info→Transfer_FromAToB→Verify_Account同时,AC搭建一条全局数据通道,所有TestJob的JobInput和JobOutput等数据都可在这条通道中进行交互。针对QTP脚本,AC提供了框架vbs 函数writeDataIntoACChanel(paraname,paravalue)和getDataFromChannel(paraname)实现写入和读出全局数据的功能。上面谈到的是一种理想的TestJob结构模型,在实际的业务中,还有一些比较复杂的因素。比如,Create_Account_Info创建测试账户,测试卡号等信息这些工作,更合适在产品实例安装结束之后,作为基础数据被sql脚本直接创建至Database中。这时,我们可将Create_Account_Info从QTP改由Java类型,而接口维持不变。
<Java name="Create_Account_Info" description="Java程序调用jdbc运行sql脚本,在数据库中创建基础数据" depends="" >
       <JobOutput name="accountA"/>
         <JobOutput name="accountB"/>
         <ClassPath location=”javacase\jdbc_sql.jar”/>
         <Run path="jdbc.createAccount"></Run>
</Java>
其中jdbc.createAccount是按照AC规范自开发的java程序,调用jdbc运行sql脚本。这种好处显而易见,Create_Account_Info从QTP转换成Java类型之后,只要接口维持不变(JobOutput不变),那么其它两个TestJob,Transfer_FromAToB和Verify_Account不会受到任何影响。同理,Verify_Account也可改写成Java或者selenium类型,以不同的方式进行验证。另外一种复杂的情形可能会出现在QTP层面上,如果QTP的脚本规模较大,而又在同一个产品实例的上下文中完成不同的功能。比如,登录后做查账,查账之后做理财交易等等,都是基于一个web session上完成的。针对这种情况,AC的QTP提供了一种Factory Mode(工厂模式)的开发方式,使得所有的测试案例的定义和执行可以在同一个QTP执行环境中完成,非常适合QTP大规模的脚本开发工作。
3.AC提供QTP的工厂开发模式
基于录制生成的QTP脚本,是面向功能的,而不是结构化的测试案例。这使得QTP在维护和增加测试案例时,成本十分昂贵。为此,AC引入工厂开发模式,使得QTP的开发像Junit一样清晰方便。QTP的工厂开发模式有如下规范:1.每个QTP的测试案例在表现形式上都是一个Vbscript的函数,测试案例的增加/删除通过增加/删除一个VBS的Function来达到。2.工厂模式不支持对象库模式的脚本,所有的功能都以Description编程来实现3.使用checkDependence函数来检查每个测试案例的运行结果状态4.调用writeIntoACChannel和getDataFromChannel来完成测试案例之间的数据交互。5.每个测试案例都是一个函数,一个函数是否成为一个测试案例取决于在TestJobFile.xml中的定义。
示例:QTP自带的Flight演示程序,录制生成的脚本如下模式:
‘登录客户端Dialog("Login").WinEdit("Agent Name:").Set "testing"Dialog("Login").WinEdit("Password:").Set "mercury"Dialog("Login").WinButton("OK").Click‘输入机票信息,下订单Window("Flight Reservation").ActiveX("MaskEdBox").Type "081210"Window("Flight Reservation").WinComboBox("Fly From:").Select "Frankfurt"Window("Flight Reservation").WinComboBox("Fly To:").Select "London"Window("Flight Reservation").WinButton("Insert Order").ClickWindow("Flight Reservation").Close

从QTP录制脚本转换成工厂模式脚本,步骤如下:1.创建一个testcase.vbs2.将原始脚本进行description改写,并按照工厂模式规范,写入testcase.vbs
登录测试案例
Function login
'调用框架函数ReportRunningInfo,写日志
ReportRunningInfo "start to run login test case"
……………Description创建……………………
Dialog(dlgLoginDesc).WinEdit(editUserDesc).set getDataFromACChannel("user")
Dialog(dlgLoginDesc).WinEdit(editPasswdDesc).set getDataFromACChannel("passwd")
Dialog(dlgLoginDesc).WinButton(btnOKDesc).Click
if(Window(flightWindowDesc).Exist(30)) Then
‘调用reportPass,向AC报告当前案例成功状态
reportPass "has sigin in successfully"
login = True
Else
‘调用reportFail,向AC报告当前案例失败状态
reportFail "failed to sigin in"
login = False
End If
'将用户名写入数据通道,供后续执行的测试案例使用.

username = "sheng.liu"
writeIntoACChannel "displayname",usernameEnd Function
   订机票测试案例
Function bookFlight
ReportRunningInfo "start to run book flight test case"
'检查login案例是否成功,如果失败,当前案例则返回失败.
If Not CheckDependence("login") Then
bookFlight = False
Exit Function
End If
…………..Description创建及调用……………………
'从数据通道中获得login案例写入的用户名,作为订单用户名下单.
username = getDataFromACChannel("displayname")
Window(flightWindowDesc).WinEdit(nameEditDesc).Set usernameWindow(flightWindowDesc).WinButton(insertBtnDesc).Click
……………………….End Function

3.定义TestJobFile.xml文件,指定工厂模式和测试案例。

<QTP name="QTP_DesktopClientTest_AC" description="demo" factoryMode="true" depends="Java_Init" iteration="">
      <Lib location="testscripts\DesktopClient\testcase.vbs"/>
       <Testdata type="xsl" location="data\data_global_shining.xls"/>
       <Testdata type="xsl" location="data\data_global_shining.xls"/>
         <Testdata type="iteration" location="data\testdata.xls"/>
      <Case name="test.vbs" description="demo" depends="">
         <Test name="login"description="login flight app"><Run path="login"/></TestJob><Test name="bookFlight" description="book flight"><Run path="login"/></TestJob>
</Case>
</QTP>

4.运行AC框架
AC会从指定的lib路径中获得testcase.vbs,然后以工厂模式运行login和bookflight两个测试案例。并最终形成测试报告。
从上面的示例可以看出,经过工厂模式改写后,QTP自动化测试具有以下优势1.测试案例的粗细粒度更加细微,可以有效地与手工测试案例形成一一对应的映射关系2.扩展性大大增强,增加新的功能点,只需开发新的function函数即可集成到AC中。3. 案例之间的依赖关系和数据交互更加密切。
总之,工厂模式非常实用于大规模的QTP的自动化测试脚本开发,大大减少维护成本,提升开发效率。
Automation Center免费,并逐步在www.cesoo.info发布开源,详情了解http://www.cesoo.info/bbs/

testhellen 发表于 2010-12-1 16:26:29

虽然有些新意!但是太繁琐了!如其这样,我还不如直接在QTP中去写呢!

sunshinelius 发表于 2010-12-2 22:21:18

录制回放的qtp脚本适合周期短,上手快的项目。
要是想开发稳定大规模的qtp脚本,那就必须在效率和结构中做一个平衡

testhellen 发表于 2010-12-6 15:46:57

我并不是指的是录制回放,我看了你的东西,实际你搭了一个框架,但是里面所有的实现由我们来做!但是你的框架搭建的比较繁琐,我是这样理解的!如果我们的思路和你的思路相同,那么你的框架帮我少写了很多程序!但是我们不需要你那么多的东西或者说想法不同的话,反而会增加我们的工作量!
比如说:你所指的描述性编程,我们也采取描述性编程模式来做!但是如果使用你们的模式,那么就必须要按照你的约定,先做定义这个对象约定来做,否则就不可行,
还有比如说我们有很多的数据控制,我们写了很多的数据处理方法,数据都是保存在数据库中,而且编写了很多QTP接口来调用数据,但是你们采取xls驱动也就很难满足像我们这些企业级,多类数据源的客户的。
所以我觉得你这个有很多借鉴的地方,但是我觉得你这个框架更加适用于与你思路相同或者相仿的人,或者说尚未开始自动化模式的人,如果像我们这样做过多年,然后像你们这边靠的化,反而麻烦了!
我觉得你的思想很不错!我反而建议你模块独立化,不一定采取你的这个模式来实现整体化的东西

sunshinelius 发表于 2010-12-9 21:44:35

回复 4# testhellen

呵呵,看来上面的朋友是做过多年自动化测试的朋友了。所以咱们直奔主题了来具体问题具体讨论
1. depedency(约定)是为了减少自动化测试失败可能带来的浪费时间。假设B案例依赖于A案例,A失败了,则B可不必运行。实际上,我们在设计测试案例的时候也是遵循高内聚,低耦合的设计原则,尽量使每个案例独立而单一,但实际上很难做到,所以引入dependency的概念。
2. 如果测试一个比较复杂的应用,比如web系统,各个测试案例的运行其实上是基于一个web session的。如果按照传统的qtp脚本的话,某些session初始化的操作必然会被重复调用多次,比如登录等。因为qtp一旦启动,又关闭,上下文就消失了。factory模式的一个作用就是解决这个问题,其实所有的function都是基于一个session完成的,理论上,只要安排得到,所有的测试案例脚本都可以在保证无重复性的被调用。您如果有好的想法,我愿意虚心学习
3. 至于数据驱动从db,xml还是xsl走,这是一个低层的问题,能够符合业务需求就是最好的解决方案。我的企业里,qtp的脚本行数超过10万行了,一直用xml数据源也很好。
另外,在Automation Center里,qtp只是其中一个job engine,还有selneium engine,jdbc engine,java engine。我个人建议,基础数据工作如果庞大,其创建和读取更合适独立出来,放在jdbc job里, 而qtp job和jdbc job做一个dependecy定义,数据通过框架的数据通道传递。QTP只关心业务的操作,jdbc只负责数据的处理,这样更显清晰。

希望听到您的意见!

sunshinelius 发表于 2010-12-9 21:53:50

实际上,vbscirpt由于其脚本解释执行的效率低下,脆弱的错误处理能力,大规模脚本难以调试的特点,应该对vbscript的规模加以限制。我个人看法是,凡是和qtp object model调用无关的操作,尽量使用编译语言来完成, 比如数据的读取,qtp的驱动,结果报告的生成,完全可以通过技术手段绕开vbscirpt,以获得健壮性。
Automation Center就是纯java开发。呵呵。

sunshinelius 发表于 2010-12-9 22:30:44

回复 4# testhellen
如果方便,能否说下您的产品测试有什么特点,qtp的具体解决方案是怎样的。
页: [1]
查看完整版本: 在AC上开发和运行QTP自动化测试脚本