手把手教你Testcomplete_深入分析TestComplete名称映射

来源:互联网 发布:网络主播黑名单第一批 编辑:程序博客网 时间:2024/04/30 21:38
 

 

摘要:通过实例和分析对TestComplete名称映射的功能步步推进层层展开,将名称映射

 

关键词:TestComplete,NameMapping,Templates,FullName

 

 

一.前言

 

TestComplete是AutomatedQA公司开发的一套支持自动测试软件的工具,近年来发展异常迅速,屡获大奖。支持VBScript、DelphiScript、JScript、C#Script等多种脚本语言,支持传统的各类桌面应用程序、WEB应用、单元测试和分布式测试等等领域,最新版本对flash的测试技术发展也非常迅猛,据说可以不用加编译参数重新编译被测程序源码。

对比同领域的其他的自动化测试工具,TestComplete的特点是简洁而强大。在TestComplete的常规应用中,对象识别能力也非常出色,本文重点分析其对象识别的原理和使用方法。

 

 

二.TestComplete名称映射分析

1. FullName和MappedName

Windows系统中应用程序、从属于应用程序的窗体、窗体中的控件都是对象,每个对象都有唯一的标识(通常是十六进制的一个值),这些共同构建出一个庞大的对象目录树,根节点就是Sys,可以想象一棵挂满了十六进制数树叶的树,每片树叶还有属性方法事件装饰它,如果录制的代码全是十六进制数做对象名称,所有人都会崩溃的,所以首先要对这些对象起个名字,最简单的法子是使用这个对象的类似caption,index和classname一类的属性来起一个名字,于是TestComplete给每个在内存中的对象起了名字,为了清晰表明各个对象的层次关系,使用了fullname来标识。Fullname看起来大概象这个样子:

Sys.Process("IEXPLORE").Page("http://xxx:nn/xxx.html").Panel("ext_comp_1017").Panel("ext_gen15").Panel("ext_gen16").Panel("ext_comp_1009").Panel("ext_gen26").Panel("ext_gen28").Panel("ext_comp_1008").Panel("ext_gen75").Panel("ext_gen76").Panel("ext_comp_1073").Panel("ext_gen161").Panel(0).Panel(0).Panel(0).Panel("ext_gen162").Panel("ext_comp_1075").Table(0).Cell(0,7).Table("ext_comp_1048").Cell(0,1).Button("ext_gen195")

 

呃…介个…是有点头晕,实在是太长了,不便于书写和阅读,是需要搞个短点的名字才行,于是TestComplete搞了个映射名称MappedName:

NameMapping.Sys.IEXPLORE.pageHttp1213289411581Citymanager.panelExtComp1017.panelExtGen15.panelExtGen16.panelExtComp1009.panelExtGen26.panelExtGen28.panelExtComp1008.panelExtGen75.panelExtGen76.panelExtComp1073.panelExtGen161.panelXPanelMl.panelXPanelMr.panelXPanelMc.panelExtGen162.panelExtComp1075.table.cellExtGen193.tableExtComp1048.cellXBtnCenter.buttonExtGen195

 

如果看起来还是有些长,可以使用对象引用的法子来截短一些:

Aliases是NameMapping.Sys

Set iexplore=Aliases.IEXPLORE

Set page=pageHttp1213289411581Citymanager

Set p1=panelExtComp1017.panelExtGen15.panelExtGen16.panelExtComp1009.panelExtGen26

Set p2=p1. panelExtGen28.panelExtComp1008.panelExtGen75.panelExtGen76

Set p3=p2.panelExtComp1073.panelExtGen161.panelXPanelMl.panelXPanelMr.panelXPanelMc

Set p4=p3.panelExtGen162.panelExtComp1075

Set p5=p4.table.cellExtGen193.tableExtComp1048.cellXBtnCenter.buttonExtGen195

Call p5.click

这下看起来好点了

 

 

2. MappedName有啥用处

 

映射名称仅仅是为了书写阅读的方便吗?当然不是!那是为了什么?

 

试想你录制了一段脚本,录制的时候对象obj,显示的内容是”aaa07201701”,回放的时候这个显示的内容发生了变化,成了”aaa07201721”,内容aaa的后面几位是时间,每次运行的时候这个时间都会相应变化,但是你希望能得到该对象的引用,加以操作,如果是使用fullname,名称可能就从obj(”aaa07201701”)变成了obj(” aaa07201721”)

问:怎么办?

答:可以使用类似正则匹配的方式来寻找对象,修改对象引用为obj(“aaa*”),这下总行了吧。

问:不见得哟,假设有很多个对象都一样的显示,obj(“aaa*”)匹配上的就会是很多个名称aaa开头的对象。

答:那就使用其他的属性来共同限定,比如这个对象类型是button,其他显示为aaa开头的对象都不是button,那就可以obj(“aaa*”,“classname=Button”),要是有多个button都是一样显示,那就加上实例索引,第几个button,例如:obj(“aaa*”,“classname=Button”,2) ,这次没问题了吧

 

是的,这样的确就已经可以了,不过这个方法有个缺点,对象的引用修改全部是在源代码中,如果代码量很大,非常容易修改错误,有什么好点的法子吗?

答:当然,可以使用NameMapping。双击开project下的NameMapping(没有?自己创建一个,或者随便录制一段脚本,结束录制后会自动保存一个的),双击目录树上你的对象obj aaa07201721进入一个编辑界面,把左面的text属性修改为aaa*,然后添加上右面的classname=Button,其实和修改fullname是一样的效果,但是这种法子有个好处,更直观,并且修改是在NameMapping中统一修改的,便于管理,不用跑源码里面去找得那么痛苦,当然现在TestComplete高版本的也不会再使用fullname来录制脚本了,都是映射名称了。

 

想起前面的那个问题,现在来回答一下,映射名称还可以使得修改属性更方便管理,就这样啦?还有没有其他的目的呢?

 

 

3. MappedName的本质

 

问:如果整个项目中这种需要修改属性的情况很多,一个个这么修改不是很崩溃?

答:不可能吧,哪有那么多意外情况

 

那就给你看个例子,这是录制的一个web应用:

录制的内容是点击添加套餐:

001.JPG

 

录制前可以看到该映射名称下没有子节点:

002.JPG

 

录制完成后:

Sub Test1

  Dim iexplore

  Set iexplore = Aliases.IEXPLORE

  Call iexplore.ToURL("http://xxx/xxx/cityMainFrame.html")

  iexplore.pageHttp1213289411581Citymanager.panelExtComp1017.panelExtGen15.panelExtGen16.panelExtComp1009.panelExtGen26.panelExtGen28.panelExtComp1008.panelExtGen75.panelExtGen76.panelExtComp1073.panelExtGen161.panelXPanelMl.panelXPanelMr.panelXPanelMc.panelExtGen162.panelExtComp1075.table.cellExtGen193.tableExtComp1048.cellXBtnCenter.buttonExtGen195.Click

End Sub

 

 

003.JPG

 

关闭IE,重新登录后,回放脚本,提示找不到对象了

 

找到之前录制脚本中的映射名称:

004.JPG

 

005.JPG

 

 

说明之前的映射名称根据预先设置的属性属性值,查找不到现在的实例了

 

让我们来猜猜TestComplete的映射名称是怎么根据自己的预设属性和属性值来找到对应的对象实例的呢,我猜大概应该是这样的。

Ø  首先是NameMapping映射上Sys

Ø  根据进程名字和实例顺序找到进程IEXPLORE

Ø  在IEXPLORE的儿子辈对象中,查找出ObjectType=Page并且URL=xxx的一个对象,这样iexplore.pageHttp1213289411581Citymanager就和Sys.Process("IEXPLORE").Page("http://xxx:nn/xxx.html")映射上了

Ø  后面同一个逻辑,匹配上一个对象实例后,根据映射名称设定的属性和属性值,在该匹配上的对象实例的儿子辈对象中查找相应对象,一直到结束

 

 

006.JPG

 

 

其实只要看看过滤的属性就知道了,当页面中的<添加套餐>出现的时候,在其已经匹配上的儿子辈对象实例中,用四个属性一个个的去比对,objecttype=button的对象,可能有好多个,再在这几个对象中继续搜索,innerText=添加套餐的,刚好就只有一个!这不就成功了,不好意思,还有两个属性呢,在找到的对象中再找找[idStr=ext-gen195]和[OjbectIdentifier=ext_gen195]的对象,这下糗了,因为这两个属性的值发生了变化,不再是ext-gen195,而是ext-genXXX了,具体是多少没有规律,每次运行都不同。

 

前文也描述过类似情况,那我们去掉那两个属性,留下可以匹配为唯一的属性不就行了,聪明!开工。

 

007.JPG

008.JPG

 

009.JPG

 

再次回放,发现还是不行,郁闷,再仔细一看,明白了

 

 

010.JPG

 

这个目录上面随便一个节点,都是idStr和ObjectIdentifier属性约束的,下次运行的时候就发生了变化。Oh,卖锅的!一个个panel改下去不得累死!这还仅仅是一个点击动作,要整个项目做下来,那比给周扒皮当长工还惨。不管怎样,有个法子总比没有法子好。痛定思痛,发现更痛。因为发现这个法子其实根本就不可行,原因如下:

 

选择className其实还是有风险的,仔细观察会发现web中的对象类名在不同的状态下有可能不同

比如:

className=x-panel-header x-unselectable x-accordion-hd,这次是unselectable,下次可能就是selectedtable

 

也就是说,除非你修改属性的同时,保证界面在相应的操作状态上才行。

 

彻底崩溃了,除非有个方法,让TestComplete在录制脚本的时候,映射panel对象就使用className,objectType,innerText三个属性,这样才能记录到运行当时的值,然后再修改innerText,去掉一些会变化的内容,替换成星号就可以了,至于怎么修改,你可以在NameMapping的目录树上修改,也可以跑到NameMapping目录下修改文件NameMapping.tcNM,不过不建议这种法子,怕改错了。现在问题的关键是怎么提前预设需要的属性和属性值。

 

经过摸索,找到了一个方法:

 

以panel为例,需要去掉[idStr和ObjectIdentifier],使用[className,objectType,innerText三个属性],在录制的时候就用这三个属性进行panel的名称映射。

 

 

l  在录制脚本之前删除掉不用的namemapping

011.JPG

 

 

l  点击[map object from screen]

 

012.JPG

 

要是怕选择的不对,可以用highlight看看有没有选对对象

013.JPG

 

这里是要映射对象了,点击Yes

如果提示你要映射的对象找不到,刷新一下ObjectBrowser就好了

 

l  去掉[idStr,ObjectIdentifier],加上[innerText,className],innerText的值变化的部分需要修改为星号

014.jpg

 

 

 

015.JPG

 

016.JPG

 

 

 

l  这里是关键了,要建立模板,当出现panel对象的时候:

只有在这种情况下,点击了templates才会出现add按钮,非常难找

017.JPG

 

018.JPG

 

 

参看帮助:Edit NameMapping Template Dialog

这里是解释active和store的:

The properties currently used to match the mapped object with the template have the Active option checked. To modify this set of properties, simply check or uncheck their Active checkbox.

 

Note: When name mapping, TestComplete automatically chooses one or several templates that match the mapped object. If that object does not contain a property specified by the template or the property’s value does not match the value defined by the template, the template is not chosen for the object.

 

The properties that are added to the list of properties used for object identification, have the Store option checked. To change this property set, check or uncheck the Store checkbox for the desired properties.

 

Note: Do not use the Name and FullName properties to identify objects. Objects mapped using these properties may be identified incorrectly.

 

简单的说,就是如果钩选了active,等你点击确定退出模板窗口,你会发现当前窗口的属性变成你的最新设定了;

只要钩选了store识别panel的时候,就会启用className=.*、innerText=.*和ObjectType=panel

 

说了一大堆,其实就这点管用

 

 

019.JPG

 

 

 

模板都建立了,大功告成了,你可以试试再录制脚本,凡是panel对象就会启动新设置的三个属性进行映射了。

 

 

做到这里,再回头看看之前的那个问题,NameMapping除了方便书写阅读,还可以使得修改属性更方便管理,其实NameMapping最重要的能力是根据设定条件进行名称的映射,对象的高效识别。

 

 

TestComplete看界面很简单,其实内在丰富呀。不单对象展现直观,更重要的是对象的识别简单实用。些许收获,不敢专享,有错漏之处,望不吝赐教。

 

 

 

原创粉丝点击