技术开发 频道

上位机软件自动化测试经验总结

【IT168 技术文章】

  一.摘要

  本文档主要描述QA在进行软件自动化测试项目中获取的经验,以及提出一些有利于下一次类似测试应该汲取的教训,以便为未来的软件自动化测试提供必要的依据。

  二.获得的经验

  1.  完整的项目回顾

  略(使用HP公司的QTP作为测试工具)

  2.  具体的开发总结

  略(公司的上位机软件,为了保密,称其为VS,软件的功能主要是物体经过某个传感器系统时,能够通过各种外设收集数据并予以判断,并且做出是否将交易记录递交数据库的决定)

  2.1 流程测试的风险

  将VS的通过传感器系统的流程纳入项目,是基于测试工具本身能使用动态链接库来扩展其自身语言(VBScript)无法完成的输入输出信号模拟功能。但这是有很大风险的,第一,数据通讯依赖串口,既要正确的通过串口发出信号,也要正确的通过串口捕获信号,但是一个串口只能被一个软件打开,使用什么技术来模拟这种输入输出信号呢?普通的商用机只有一个物理串口,如果没有很好的串口模拟技术支撑,不仅随时随地的流程自动化测试将化为泡影,测试成本也将上升。第二,我们不知道测试工具对哪些编译型语言编写的dll支持,是否支持的好,程序员能否熟练编写这种未知语言编写的dll;

  实际上,这两种风险在开发过程中我们都真实的遇到了。对于第一种风险,我们最终使用串口对接技术来解决,并且放弃了物理串口,使用虚拟串口。编写dll 时,我们一开始使用Delphi来写dll,但是测试工具无法正常调用,最后我们用C#成功的编写了测试工具可以正常调用的dll。

  2.2 自动化测试的架构

  自动化测试的架构也是我们在项目开始初经常涉及的问题。好的测试架构能够提高开发效率,保证开发质量,规避开发歧途,降低项目后期整合时的维护难度。因为项目组成员,来自各个不同的部门,对于测试自动化的理解深浅不同,使用自动化工具的水平参差不齐,团队的合作开发使得我们亟需完美的测试架构。但是,这毕竟是我们第一次做自动化测试项目,没有任何的经验积累。公司目前采用的测试管理工具是QC,那么使用QC+QTP,就是我们架构的唯一选择。QC和QTP 能够无缝结合,使用QC可以方便的生成,运行,管理自动化测试案例。除了架构带给我们开发过程中的这些便利外,我们还需要考虑测试编码过程中编码的方式,编码的效率,测试对象的管理,函数的管理,代码的配置管理。

  我们将测试对象做成一个共享对象库,每个团队成员进行某个自己负责的案例开发时,只要关联这个对象库,就能自动识别被测软件的对象。使用共享对象库,不但保证被测软件对象的唯一性,而且便于后期对象的维护。目前,在自动化测试中模拟操作的更好的代替方法是描述性编程,可以避免软件升级时对象库的维护。但是由于团队成员是初次参与这种项目,所以采用更成熟的对象库技术。

  编码方式有3种,一种是直录,一种是手工编,还有一种是混编。直录的优点是速度快而方便,缺点是它产生的新对象不会存到共享对象库,脚本相对累赘。手工编的优点是代码清晰简洁,可读性更好,缺点是相对麻烦,编码速度稍慢。混编是指主要采用手工编码方式,在人机交互复杂时用直录提高效率,完成脚本后再使用手工编码简化脚本。我们采用的就是混编方式。如果使用描述性编程,那就必须要完全使用手工编码了。

  本文为51Testing论坛会员xixihahahu原创,转载请保留作者及出处。

  在自动化测试中,函数库起到很大作用。在QC的自动化项目中,适当的编目函数库,将项目无关的函数放在公共的函数库中,将项目有关的函数放在项目根目录下。我们此次项目编写了大量的自定义函数,主要有两类:一类是起到简化主脚本代码的作用,使测试脚本看起来更加简洁,例如InitCom,FreeCom 函数等(用于进行串口的初始化);一类是起到检查点的作用,例如CheckDb,Check_Object_SelectedText函数等(检查点函数)。我们这次的自动化测试项目,很少去用工具自带的检查点。QTP本身包含一些检查点,但是有局限性,有些需要直录产生的图片的支持,有些需要对象库的支持,不利于手工编码,也很不简洁。通过直接调用检查点函数,就能很方便的检查软件功能的期望效果,不依赖对象库,也不依赖图片。

  代码的配置管理没有做,这是缺陷,直接后果是对于测试代码形成的版本历史无法追溯。这跟公司使用的CVS有关。事实上使用QC+QTP的架构后,我们的版本控制依赖QC所支持的配管工具,其中微软的VSS和开源的Subversion是比较著名的2个,但是这些都不能和CVS兼容。

  2.3 无法识别的对象

  项目中比较棘手的是遇到对象无法识别,或者识别程度不够好。对象无法识别表示计算机对该对象一无所知,也就无法正常的操作对象或者获取该对象的运行时属性,涉及到该对象的功能就无法验证它的期望值。对象无法识别有两种原因造成,一种是测试工具本身的插件就不支持识别该对象,另一种是由于将要识别的对象放在容器里边而这种容器本身不能识别。举例来说:测试工具能够识别VB中的Label控件,但是当Label控件放置在PictureBox中,就无法识别了。原因:QTP的VB插件不能识别PictureBox,因为它这个插件本身就不支持该对象;PictureBox是个容器,将Label放在其中就有了嵌套关系,工具就不能直接定位和识别到Label了。对于类似PictureBox这样的对象,一般没有办法正常的识别,所幸的是自动化测试的检查点一般不会对容器做检查;对于放置在容器中的原来可以识别的对象,可以采用遍历函数来对整个Form进行遍历,找到名称和开发名称相同的,然后再返回所需要的属性值。

  对象识别程度不够好,一般指该对象的所有属性值不能唯一定义这个对象。测试工具针对这种缺陷提供了一个解决方案,就是在对象描述中有一个描述位置的属性 Ordinal Identifiers。这个属性值确定了相似对象在窗体中出现的顺序,从而能够让测试工具唯一识别。但是当某个类似对象脱离界面时,窗体中的所有类似对象就会重新排序,用之前的对象描述识别的是一个其他的类似对象。这种缺陷导致测试运行与界面的相关性提高,但目前没有更好的解决方法。在VS系列软件中,左侧菜单栏就存在这种缺陷。

  2.4 测试复用

  自动化测试项目开发过程中,尤其要注意复用。测试复用有2种方式:第一种是通过函数复用使得测试脚本简洁,并且为将来其他上位软件的测试提供服务;第二种是测试案例的复用,包括Test的复用和Action的复用。一个Test可以包含多个Action,如果这个Test有特殊性,无法复用,就让 Action能够复用。做用每个Action的时候,要注意它的原子性。举例:在做流程测试的时候,实际上有很多的Action在不同的流程测试中都被包含,此时Action就可以被设计成可复用的。但是不能简单的将Action置成可复用就算结束,一定要注意它的原子性。流程测试中每个Action都涉及到串口,如果要让Action工作,就要在这个Action的开头初始化串口,在结尾释放串口。这样当Action被其他流程引用的时候,它才能正常的运行并且不会造成串口的冲突。

  2.5 对象的生命期

  在手工编制脚本的过程中,会遇到这样一种情况:在脚本开头定义了所有在脚本中要使用的对象变量,使用这些变量操作对象。但是在测试运行时,测试工具突然提示找不到这个对象,测试被中止,而软件窗体还在那开着,对象并没有被遮挡和消失。为什么会出现这种怪异的现象呢?原来在测试运行过程中,包含对象的窗体被关闭过一次而被重新打开,变量指向的原有对象消失了,新窗体的对象虽然属性和原来一模一样,但是变量所代表的对象却并不是当前窗体的对象。在这种情况下,只有重新定义对象变量,才能够操作当前窗体对象。我们可以说,对象的生命期在对象被关闭后结束。

  2.6 插件的选择

  测试插件一般根据被测软件所使用的编程语言选定。如VS系列软件使用的主编程语言是VB,那么就要选定VB作为插件。这次测试项目我们将ActiveX也作为测试插件,主要是因为VS系列软件有些用户自定义控件。选择ActiveX会将用户自定义控件识别为ActiveX类,而只选择VB会将用户自定义控件识别为WinObject类,就是被识别为一个标准的Windows对象。这可能是项目的一个失误,因为这些自定义控件确实不是ActiveX控件,有些只是测试工具不支持的标准VB控件,但选择了ActiveX,QTP就会将其识别为ActiveX控件。QTP识别对象的原理可能是非此即彼,如果非 VB标准控件,它就看做是ActiveX控件,如果连ActiveX控件的一点特征都没有,它就识别为WinObject。实际上在项目结束以后,我们发现只选择VB插件,添加的对象可能更科学些。因为它无论如何都会是WinObject,但未必就是ActiveX类。而识别为ActiveX的可读性能更好些,层次结构会更简单些。但是我们已经使用两种插件做了大量的案例,而案例是靠对象库支撑的。插件变了,对象库就失效了,脚本也就失效了,所以选定插件后就不能随意更改。插件的选择在编写脚本之前一定要考虑清楚。

  2.7 等待时间

  在我们开发的测试脚本中,使用了大量的Wait函数。Wait函数能够让测试工具在设定的时间内停止运行。为什么要使用Wait函数呢?这是因为计算机执行的速度太快了。在执行上一条指令后,下一条指令立刻开始执行。这就有一个问题,上一条指令触发的事件虽然产生了,但是这个事件要通过桌面程序反馈出来。举例:第一条指令点击按钮,打开一个窗口;第二条指令检查这个窗口是否存在。窗口打开的事件已经被触发,但是窗口被打开并呈现在桌面上有一个短暂的时间差,如果直接执行检查函数就会导致测试失败。所以要用Wait函数去人为的弥补这个时间差。通过Wait函数,找不到对象的错误提示就不会再出现了。

  2.8 重复运行

  重复运行是指单个测试案例能够任意执行多次而不必对被测软件进行任何修改。这里的被测软件修改包括软件设置的修改和软件数据库的修改。为了避免被测软件修改,达到重复运行,测试脚本需要遵循两点:第一,脚本从哪个界面开始,就到哪个界面结束;第二,Action之前之后都要清数据。

  三.项目经验简述

  1.   详细的项目计划,确定功能点和相关的负责人,确定工作进度。经常监督计划的执行。

  2.   经常性的讨论,使用每个人的智慧,并且尝试每一种方案。

  3.   建立一个好的测试框架并且保证大家都在这个框架下工作,不仅事半功倍而且能确保文档的一致性。

  4.   正式编码前多做一些实验,真正做过几个案例后才能归纳出适合的方式。

  5.   使用共享对象库,并且保证其他人也使用共享对象库,避免使用本地对象库。

  6.   界面对象在一个测试案例中会移动位置时就使用描述性编程。

  7.   描述性编程和共享对象库可以结合使用,无法描述的对象就暂时用对象库。

  8.   设计复用函数时一定要注意软件无关性,做到在今后其他软件的测试中不改动。

  9.   避免开发一段时间后轻易改动函数。

  10.  尽量使用自定义的检查点函数。

  11.  测试复用的Action要注意原子性。

  12.  找不到对象时,按如下顺序排查:登陆测试工具的插件是否支持,测试对象有没有被遮挡,是否没有设置等待时间,使用了指向对象的变量有没有关闭窗口。

  13.  如果不确认被测软件还使用了哪些技术,尽量只使用被测软件的主语言插件
 

 

0
相关文章