51Testing软件测试论坛

标题: 做了一段时间QTP, 发现趋向于"尽可能少用对象库", 不知道大家以为然否 [打印本页]

作者: lifr    时间: 2012-1-17 21:26
标题: 做了一段时间QTP, 发现趋向于"尽可能少用对象库", 不知道大家以为然否
做了QTP快两年了, 主要做了两套基于QTP测试框架, 分别是Web和Eclipse平台的应用.  不知不觉的, 发现自己在朝"尽可能少用对象库"这样的一个方向前进.

因为自己以前的自动化测试项目都是比较"低级"的, 没有基于商业的测试工具, 而是用Java, Ruby, Shell, 等等这样语言构建起来的. 所以骨子里有"自己控制一切"的倾向. 对于QTP本身, 我还只是半瓶子水, 所以我不敢确定这是否是一条正确的道路? 不知道各位资深的QTP测试开发人员是否同意我的观点?

突然有这样一个反思, 是因为前几天, 我在试图实现这样这样的一些函数: 通过函数调用(不用访问对象库), 就能在当前window把一些GUI元素找出来, 比如Button, Edit, Table, List, 等等.

  1. Function FindButton(strText)
  2.          '找出当前的window, 逻辑大概是这样
  3.          Set cw = Nothing
  4.          if 有popup window Then
  5.                set cw = popupWindow
  6.           else
  7.                Set cw = mainWindow
  8.          End If
  9.          
  10.          '用 DP找出此button
  11.          set desc = Description.create
  12.          desc("to_class").value = "Button"
  13.          desc("index").value = 0
  14.          desc("attached text").value = strText
  15.          Set ele = cw.Button(desc)
  16.         
  17.         ' 如果不能找到, 那么引用对象库
  18.          if Not ele.Exist(0) Then
  19.                Set ele = win.Button(strText)
  20.          End if
  21.         
  22.           Set FindButton = ele
  23. End Function
复制代码
为什么要实现这样一套函数库是因为 在写 testcase script的时候, 常常不得不中断下来, 把对象加入对象库. 而这样的"中断" 让我很恼火, 因为它破坏了写代码的流畅性.

如果有比较完善的这样的"找出对象"的函数库, 那么在写testcase script的时候, 几乎不会为录制"对象"而中断, 这样就更像我用Java, Ruby, Shell等语言开发的状态.

这种方法的缺点也很明显. 因为QTP对象库提供了一层中间层, 所以GUI元素发生了改变, 比如改名, 那么仅仅需要修改对象库里对象的定义, 而不需要修改任何引用它的code.

想听听大家的意见.
作者: 木卫十二    时间: 2012-1-18 14:24
为何不直接用描述性编程?

以前喜欢用对象库,后来也淡化了,改成描述性为主,对象库为辅。

赞成 <"自己控制一切"的倾向>,所以会尽量用代码,而不用QTP自带的检查点之类。
作者: lifr    时间: 2012-1-18 14:53
回复 2# 木卫十二



"不直接用DP?" 你是指直接用 win.Button("attached text:="&xxx, ...)这样的形式吗?
主要有下面三点考虑
1) FindButton函数把 查找当前window的逻辑包含进去了
这样调用FindButton函数的时候不用考虑是在main window还是popup window

2)FindButton(text)里的产生text可以有更丰富的含义
在测试web的框架里, 有一套 灵活且强大 的机制来通过各种途径查找对象, 以先后为序
     1. label名字(找到label, 然后通过label的for属性找到对应控件的id)
     2. button控件的id
     3. button控件name
     4. 对象库里对象的名字 (实在没有办法的情况下, 找对象库里的对象)
如果直接用DP是不能达到这样效果的

3) 更简洁的代码
对比

  1. FButton(xxx)
  2. win.Button("attached text:="&xxx, ...)
复制代码
我现在也描述性为主, 对象库为辅的方式来访问对象. 对象库主要存放顶级的window和比较特殊, 通过已有机制不能够找出的 GUI元素.

说到检查点, 我实现了完整的一套AssertXXX函数(参照Junit), QTP提供的Checkpoint很少用.
作者: lixudong3032    时间: 2012-1-18 16:45
对象库是QTP的一个很精髓的东西,这个建议用
作者: yyc2164708    时间: 2012-1-18 17:12
哎呀!无论描述性编程还是对象库只是个描述方式而已。
得看具体情况采用哪种方式!
作者: 黑羽祭    时间: 2012-1-18 17:39
我有时候写着写着也会慢慢的向脱离对象库走,也是觉得添加对象比较麻烦。尤其有时候给客户的是特别定制的版本的时候,有些名词改了几个字,但脚本就回放不了了,还得去对象库找到底哪个对象改变了。可能是不太知道如何更好地管理对象库吧。
继续观望,看看有什么高手有自己的管理方式或解决方法
作者: lifr    时间: 2012-1-18 19:57
回复 4# lixudong3032

对象库提供了一层对GUI元素的封装, 理论上可以做到 GUI元素变化, code不用修改的效果。

比如在一个html page中, 有一个edit input, 其name属性的值为“type”, 在对象库里通过”name=type“来识别. 在新版本中, 其name值发生了变化, 比如改变为“name=category”.  这时通过修改其在对象库里的定义就可以了, code不用做任何修改。

我推测这就是对象库最核心的价值。 ”通过对象库来隔离GUI元素的变化“。 对于比较依赖于record的开发模式, 这种方法是比较有效的。 因为对"对象的引用”在很多地方都会出现, 通过“对象库”这样一个中间层, 即使GUI元素的改变, 引用对象的代码却不用改变, 显然可以降低测试套件维护的成本。

如果换一种思路, ”通过函数来隔离GUI元素的变化“。 通过大量的细粒度的函数来对 产品的 功能逻辑或者页面逻辑 进行封装。 这样就可能出现, 在极端的情况, 所有对GUI元素的访问都是通过一个函数或者有限的几个函数调用进行的。 这样即使GUI元素出现了变化, 也只需要修改几个函数就可以了。 调用此函数的任何testcase script不用修改。在这种开发方法下, 同样达到了 “隔离对象改变”, 却不依赖于对象库。

我个人的经验, 对于通常的中型和大型的QTP项目, 基于record的开发模式不太合适。我倾向于开发大量的函数来封装 业务操作逻辑或者页面操作逻辑。 所以不知不觉的就越来越远离对象库。
作者: 云层    时间: 2012-1-19 09:26
无论是不是需要用对象库,其实这只是一个思想进步的过程

开始依赖OP,好简单啊,啥都可以自动搞定,动动鼠标就行了
然后开始依赖DP,完全看自己,清清楚楚,了然于胸
最后还是走回OP,既然最终还是要自己去简化DP,还不如用QTP自带的OP,都帮你该考虑的考虑到了,何必自己给自己找麻烦呢?
作者: davy_chen    时间: 2012-1-19 09:28
让QTP做它擅长的工作,不用对象库的QTP,好像是让研究生卖猪肉,虽然效果未必差,但是不是主流。
作者: yujie6832    时间: 2012-1-19 09:29
云层兄的想法跟我一致,OP也可以玩得很简单,自动化关键在于多用脑子去思考,用活了,你就会发现OP简单的多,这个是QTP的精华中的精华,我的理念是OP为主,DP为辅
作者: hsjzfling    时间: 2012-1-19 12:07
这需要个过程的,一般都是OR->DP->? 只有对OR DP都有足够的认识的基础上才能够根据实际情况作出最合适的选择,本人也是自4年前开始就一直坚定拥护OR为主的
作者: lifr    时间: 2012-1-19 14:05
本帖最后由 lifr 于 2012-1-19 14:08 编辑

回复 8# 云层

你指的麻烦是 "写复杂的description来定位对象"? 我想你误解了我的意思, 这应该是因为我之前的表达并不精确, 我再重新明确一下.

我赞同你的观点. 对于需要比较复杂的条件才能定位的GUI元素, 用对象库更有效率.   所以, 在 FindButton函数逻辑里, 在用DP查找失败的情况下, 还会通过对象库来查找.

通过DP就能找到的GUI元素, 恰恰不是这种"需要复杂条件才能"的元素, 反而是有规律的, 简单的方式就可以定位的元素. 这样的所谓的简单的GUI元素, 我个人经验是占总量的80%以上.

所以, 重新回到以前的问题, 对于这一些"简单的GUI元素", 是通过对象库来引用有效率, 还是写一些像FindButton这样的函数来引用比较有效率? 这里的效率既包括开发效率, 也包括后期维护的效率.
作者: lifr    时间: 2012-1-19 14:11
回复 10# yujie6832

能否详细阐述"OP简单的多", 或者举例一二.
作者: lifr    时间: 2012-1-19 14:25
本帖最后由 lifr 于 2012-1-19 14:27 编辑

回复 9# davy_chen

我想是否我真的很"非主流"的使用QTP, 下面是我做QTP项目的特点.

1) 重度的 函数 使用者.
关于函数库的设计, 我也许会另开一贴讨论. 我的项目中确实使用了大量的函数.
2) 绝不使用ReusableAction
3) 从不使用Keywork View
3) 尽可能少用Checkpoint, 而使用AssertXXX函数
4) 尽可能少用对象库, 而使用建立在DP之上的对象识别机制
5) 没有(机会)使用QC, 使用自己的Batchrun脚本和report生成工具(都是用VBS开发)
作者: 木卫十二    时间: 2012-1-19 16:12
描述性编程,封装得好,跟用对象库效果一样的。
封装的原则:页面上一个元素的改动,脚本也应该只改动一个地方。

我不仅使用函数,还使用Class,总之,一个项目全是脚本+数据,编写用例的时候甚至不需要打开QTP。
使用PsPad管理项目脚本。
作者: lifr    时间: 2012-1-19 17:10
回复 15# 木卫十二

看来你更"严重". . 我在QTP的IDE里面写testcase script. 用vim写外部函数.

有个问题? vbs支持class吗?
作者: archonwang    时间: 2012-1-19 17:18
高手云集。激活一下。
作者: 木卫十二    时间: 2012-1-19 17:50
回复 16# lifr
支持,但功能不强。参考:
http://www.51testing.com/index.p ... wspace-itemid-64875
作者: 云层    时间: 2012-1-19 20:19
回复 12# lifr


    我的意思是简单的东西用OP,略微复杂的可以用DP来辅助,因为总是调整OP来配合某些对象很麻烦,特别麻烦的成套对象还是用OP好
作者: lifr    时间: 2012-1-20 08:53
回复 18# 木卫十二


恩,  知道了.  多谢.
作者: lifr    时间: 2012-1-20 09:31
回复 19# 云层

你这里列举了多种类型的GUI元素和你采用的识别方法.  我顺便也全面总结一下, 对于QTP里使用到的GUI元素, 我采用的相应的识别方法,

1. 简单的对象
这种对象是指, 通过一个id或者name或者label或者attached text, 等等, 就可以识别出来. 这种对象包括menu, button, edit, list, radiobutton, checkbox, 等等.

通常来说, 对于一个软件产品的节目, 这种类型对象是占大多数的, 我个人经验是80%左右.

这种对象无论 是录制通过QTP自动添加到对象库, 或者通过DP来查找都很简单. 鉴于其有很强的规律性, 我倾向于用DP来做, 就像我前面所描述的FindButton这样的函数, 原因是减少了对象库操作这个步骤, 开发的时候感觉更流畅.

2. 需要通过更多 属性 来识别的对象
举个例子, 页面有一个Table, 没有id. 缺省情况下, 如果把这个table加入对象库, QTP会通过index来识别. 但是index并不是可靠的方式. 这个时候需要把识别方式改成"column names".

这种对象 通过DP反而更麻烦, 不如对象库操作直观, 方便. 所以, 我是把这种对象放入对象库.

3. 另外有些对象只能通过DP来查找, 或者用DP查找更好.
因为TO封装的属性是有限的, 所以如果一个对象只能通过native对象的属性才能识别, 那么只能有DP了.

比如一个用SWT(eclipse)开发的界面, 有一个editbox, 其"attached text"是空值, 但可以通过 native object的message属性来识别.

又比如, 我现在的一个web项目, 所有form里面的input都有对应的label(如果没有可以报bug ), 所以所有的input都可以通过
    a. 根据inner text找到label
    b. 根据label的for属性找到input的id
    c. 根据input的id找到input
相对于input的id这种识别方式, 我认为通过label更直观, 代码的可读性更好. 所以我用了DP通过label查找对象. 如果你问我 "label和id, 谁更容易变化"? 我真不知道, 只能通过时间来检验, 不过有一点我能确定, 无论是id或者label, 新版本更替时变化的比例都会是很小的.
作者: heqingbluesky    时间: 2012-1-25 14:08
这个问题很早就被讨论过了。。。。。。

如果没有OR的存在的必要,QTP就早放弃了。
作者: hsjzfling    时间: 2012-1-28 12:48
回复 21# lifr

如果DP和OR处理起来都很方便,那何不使用已经很好封装后更清晰明了的OR呢?
1 就无须讨论了
2 使用OR必须要懂得Object Identification这个配置中心
3 QTP提供了自定义对象接口,有编程能力完全可以通过该接口来自己封装对象,同类型对象定义一次即可
作者: hyholine    时间: 2012-1-30 11:14
回复 21# lifr


    受教了,个人目前的脚本开发模式,和lifr很相似,基本上也是OP和DP混着用,对于同一个web页面下一些存在共性的对象封装成一个函数供调用。对于个别较复杂的则采用QTP的对象库识别。
    这两种模式各有利弊,灵活使用方能效率最大化。对于vbs的class使用,个人不推荐,毕竟脚本不需要太复杂的封装,简单的函数调用就足够了。当然,如果项目庞大,开发外部功能拟用class来管理脚本也不失是个好办法。
作者: liujintao00    时间: 2012-1-31 11:25
本帖最后由 liujintao00 于 2012-1-31 15:01 编辑


作者: lifr    时间: 2012-2-9 09:57
回复 24# hyholine

关于class的意见所言极是. 我现在的library大约总共有7k行代码(包括注释). 对于这样规模的代码, 通过命名约束等措施, 不用class也能处理得比较好.

引入class还得考虑整个team的技术基础. 所以我也是持谨慎态度.
作者: heqingbluesky    时间: 2012-2-14 08:24
回复  hyholine

关于class的意见所言极是. 我现在的library大约总共有7k行代码(包括注释). 对于这样规模 ...
lifr 发表于 2012-2-9 09:57



    VBS本身对于Class的支持就比较弱,如果大家拼命的想往OO靠拢,那就是自己给自己找麻烦。
    我们公司的第一版VBS代码,就用Class。在第二版的时候,就放弃了。




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2