在多个培训中,我都会与学员探讨测试的七项基本原则,发现自己所举出的例子都是反面的,思考一下这个问题,为何我们在一些基本原则上仍然Hold不住?是不是有些“潜规则”在作祟?因而,发起这个话题,讨论测试的“潜规则”。
先看看ISTQB的“测试七项基本原则”:
原则1:测试指出缺陷的存在——测试没有发现缺陷并不意味着不存在缺陷
原则2:穷尽测试是不可能的
原则3:测试要尽早介入
原则4:缺陷集群性——大多数缺陷总是发生在少量模块/特性上
原则5:杀虫剂悖论
原则6:测试活动依赖于测试Context
原则7:“Absence-of-errors ”(无错就是好)谬误
总结一下偏离这些基本原则的潜规则,如下:
潜规则1:可以规划软件中缺陷的数量
- 使用千行代码缺陷密度做为过点要求
- 缺陷密度降低被认为是质量改善
潜规则2:测试周期总是可以压缩的
- 计划是倒排的,但开发周期延长,测试还是要保证按时完成
- 实在无法压缩的话,通过外包一批完全不懂测试的人也可以搞定
潜规则3:测试在前期的工作只能是学习
- 测试只需要在后端介入,前端投入是浪费人力
- 系统设计与测试无关,不能测的话自己想办法
潜规则4:缺陷都应该用“三板斧”来发现
- 对每个特性,构造满配置、满容量、频繁倒换,Bug马上出现
- 基本功能的覆盖没有意义,发现不了问题
潜规则5:姜是老的辣,用例是陈的香
- 规格变了,用例不需要更新;架构变了,用例不需要更新;需求变了,用例也不需要更新
- 用了10年没变化的用例被视为“金科玉律”,绝对不能变更
潜规则6:任何一个测试项目都是可以复制的
- 做测试策略,先把上个版本的Copy过来,再修改版本号,基本搞定!
潜规则7:超出设计规格的缺陷都不是缺陷
- 设计本来就是这样的,这样测就不对
- 如果有问题是需求的问题,不是缺陷
那么,做测试的你,被“潜”了吗?
LOFTER现在提供iOS、AOS等多个平台的移动客户端服务,这两个端也已经相继开发了几个版本,最近开发的2.0版本即将上线,测试了这么久也该总结一下了。
现在我们测试时,开发会先在本地机上打好包,然后我们在开发提供的网址上下载这个包就可以了,这样在真机上直接测试可以更直观的发现bug。以下是功能测试时需要注意的点:
1、登录
● 登录用户名和密码错误时,界面有提示信息
● 用户主动退出登录后,下次启动APP时,应该进入登录界面
● 对于支持自动登录的APP,数据交换时 ,是否能自动登录成功且数据库操作无误
● 密码更改后,登录时是否做到了有效数据的校验
● 对于未登录时一些页面的操作,是否做了控制
● 切换账号登录,检验登录的信息是否做到及时更新
● 对于多个端都进行操作时,确保数据库操作无误,且每个端可以及时看到数据的更新
● 对于一些软件,支持一个账号只允许登录一台机器,这时,需要检查账号登录多个手机时,是否将原用户剔除,且能够给出提示信息
● APP切换到后台时,再次切换到前台的测试,如登录时,有电话打进来
2、离线
离线是应用程序在本地的客户端会缓存一部分数据以功程序下次调用
● 对于一些程序,需要在登录进来后,这时没有网络的情况下可以浏览本地数据
● 对于无网络时,刷新获取新数据时,不能获取数据且能给出友好提示
● 切换到后台,再次切换到前台时,可以正常查看
● 离线后又连上网,这时对数据有更新时,需要从服务器端获取新数据来更新客户端数据,且要更新本地缓存信息
● 对于一些界面的数据不提供离线查看,需要给出相应提示且界面更新后无任何数据
3、Sqlite数据库
AOS和IOS客户端都采用了sqlite数据库,当APP需要在客户端保存数据时,它们会创建相应的数据库表,最常见的就是对账号的保存,这时的测试点主要有:
● 跟一般数据库一样,需要见擦数据的增,删,改,查
● 客户端即用即建,当表不存在时,是否会自动创建
● 数据表被删除后,新建的表中的数据能否自动从服务器端中获取回来兵保存
● 当对数据进行了修改,删除,客户端和服务器端能否有相应的更新
● 获取数据,客户端是从直接从客户端获取还是和服务器端的数据进行比较
● 对于客户端从服务器端更新的数据,客户端是否有保存于本地
4、刷新
主要是针对数据的更新操作
● 删除数据后,刷新界面观察数据是否被真正刷新,小心前端做的一些陷阱用来迷惑用户
● 添加数据后,多次刷新,确保数据真正更新
● 对于一些自动刷新的界面,进入界面是否有数据的更新
● 数据的一些处理逻辑的检查
● 确保每次刷新时从服务器端获取的新数据而非本地缓存数据
● 前后台切换时是否有数据的更新
5、APP中含有音乐 视频文件
● 播放,暂停,停止三个状态之间的转换测试
● 播放模式的检测,音乐文件一般为单曲播放
● 几首歌之间的切换,是否播放正常
● 状态栏的信息是否显示正确,音乐视频是否支持状态栏关闭的功能
● APP切换到后台,音乐 视频是否还在播放,且功能状态是否正确
● 锁屏时,这些文件是否还在播放
● 对于页面交换时,是否影响这些文件的播放
6、相机服务
● 应用相机时,再返回到APP,APP是否会崩溃
● 应用相机时,对于IOS AOS版本都做一些检查
● 前后台切换测试
● 相机拍摄的照片返回APP时,图片不能被拉伸
7、消息推送
● 如果用户设置了不接受推送消息,检查用户不会再接收到推送消息
● 检查推送消息是否按照指定的规则进行推送
● 如果推送消息只是针对登录用户,需要检查收到的消息手否与用户身份相符合,一般情况下,只对手机上的最后一个登录用户进行推送
8、UI检查
● 像素的检查
● 边框外是否含有阴影
● 边框外是圆角还是直角
● 不能出现一些显示紧凑过密的文字
● 提示文字的友好性
● 拒绝大片的空白区域
● hover与不hover时的区别
9、版本更新
● 客户端有新版本时,有更新提示
● 当客户端有新版本时,本地不删除客户端,直接更新检查是否更新成功
● 接上面,检查更新的客户端是否为新版本
● 强制更新时,可以选择取消更新
● 有更新版本时,保证老版本能继续使用,且做到兼容
● 当强制升级时,取消更新,下次进来依然提醒用户更新
10、网络
● 无网络时,执行的操作,给出友好提示
● 内网测试时,要注意外网操作时的异常情况
● 网络信号不好时,检查数据是否会一直处于提交的状态
● 在网络信号不好时,执行操作,在回调没有完成时,退出页面,有无异常情况
11、其他
● 各个端系统版本兼容测试,ios4.3 ios5.0 ios6.0 aos2.0 aos4.0等
● APP应用键盘的收起展开正确
● 快速操作不能引起程序崩溃
● 按钮不能点击时,是否显示灰白
● 屏幕旋转是否影响界面布局
● 手机端和pc端操作,每个端应该有容错处理
在上一讲“SilkTest入门 快打系列1- 录制回放”中,我们介绍了如何建立一个简单的SilkTest 测试项目 ,用它来测试WindowsXP 自带计算器的加法功能。在上一讲中,我们使用SilkTest 的录制回放功能来产生测试用例的脚本,虽然它可以工作地很好,但是采用录制回放的方法,会有一些局限。首先,由于录制回放总是操作原生对象,没有隐藏对象的细节,从而导致每行脚本都很长,不易阅读。其次,如果待测AUT 的GUI 发生了变化,那么很可能,你需要重新录制脚本,不利于已有代码的维护。所以这一讲中,我将介绍如何直接编写SilkTest 脚本 进行测试。
我们仍然测试计算器的加法功能,首先像上一节一样捕捉计算器GUI 的定义,并在其基础上对其进行一定的修改。也就是将/,*,-,+,= 等按钮的定义名改成容易识别的名称:
将
[+] PushButton N52 [+] multitag “?[5]” [ ] “$90″ [+] PushButton N92 [+] multitag “?[9]” [ ] “$91″ [+] PushButton PushButton20 [+] multitag “-” [ ] “$93″ [+] PushButton PushButton26 [+] multitag “+” [ ] “$92″ [+] PushButton PushButton27 [+] multitag “=” [ ] “$112″ |
改成:
[+] PushButton Div [+] multitag “?[5]” [ ] “$90″ [+] PushButton Mul [+] multitag “?[9]” [ ] “$91″ [+] PushButton Dec [+] multitag “-” [ ] “$93″ [+] PushButton Plus [+] multitag “+” [ ] “$92″ [+] PushButton Equal [+] multitag “=” [ ] “$112″ |
这样,我们在脚本里面就可以用“计算器.Plus ”来表示加号按钮,而不是晦涩的“计算器.PushButton26” 了。
除此以外,我们还需要将
[+] TextField TextField1 [ ] tag “$403″ |
改成
[+] TextField CalResult [ ] tag “$403″ |
然后,我们新建一个WriteScript.t,里面写如下的代码:
[-] testcase Cal123Plus() //1 [ ] 计算器.SetActive () //2 [ ] 计算器.C.Click () //3 [ ] 计算器.N1.Click () //4 [ ] 计算器.N2.Click () //5 [ ] 计算器.N3.Click () //6 [ ] 计算器.Plus.Click () //7 [ ] 计算器.N1.Click () //8 [ ] 计算器.N2.Click () //9 [ ] 计算器.N3.Click () //10 [ ] 计算器.Equal.Click () //11 [ ] String sResultValue = 计算器.CalResult.GetText() //12 [-] if(val(sResultValue) == 246) //13 [ ] Print(“Passed: Expect 123+123=246, actually it is {sResultValue}”) //14 [-] else //15 [ ] raise 1, “Failed: Expect 123+123=246, actually it is {sResultValue}” //16 |
我来解释一下这16 行代码的意思,其实他们做的事情,和上一讲的测试用例是一样的,就是验证123+123 的值等于246.
行1 :定义一个名为Cal123Plus 的测试用例
行2 :将当前激活的应用设为计算器,如果计算器这个程序没有运行,那么就先启动它,然后将其设为得到焦点的应用。
行3 :先点击一下C 这个按钮,也就是清除上次计算的结果
行4- 行11 :分别点击计算器上的123+123= 这八个按钮
行12 :定一个字符串变量sResultValue ,把CalResult 控件中的文本值赋给它
行13- 行16 :如果sResultValue 得数字值等于246 ,就打印测试成功,否则抛出一个异常,表明测试失败。没有异常处理程序紧接raise之后的话,默认情况下,SilkTest 将终止执行。
好了,现在按F9 运行一下你新编写的WriteScript.t ,看看是不是通过了。
然后,再将WriteScript.t 里面的246 改成247 ,然后运行,这时测试用例应该抛出一个异常,你的脚本执行结果是不是这样呢?
相关链接:
SilkTest入门快打1-录制回放
一、软件测试的目的
软件开发过程中软件测试具有非常重要的作用。软件测试的目的在于按照规定的步骤,采用正确的方法,对开发设计阶段提供的软件工件进行严格的检测,发现和改正软件错误,使软件质量在测试过程中不断提高,逐渐达到规定要求,能够交付用户使用。如果测试中察觉软件设计质量太差,暴露出的各种问题,不是依靠测试能够完全解决,项目主管可以中断测试,责成设计组加以改进。当问题十分严重,已经无法满足用户既定的需求时,项目甚至可能被迫取消。
软件测试过程中,项目主管和质量保证部门可以采集到各种软件质量原始信息,其中最重要的是软件错误数据,包括软件错误的类型、错误的数量、错误产生的阶段、错误存在的部位。有了这些数据,就近期而言,可以对软件已经达到的质量水平做出定量评估、可以对软件可靠性增长过程及软件开发中的资源消耗做出预测。长期而言,从各个时期各种软件项目积累的质量数据,能够准确反映开发单位具有的开发和质量保证能力,能够反映开发单位能力提高过程。在重视质量相关的数据采集和拥有的历史数据方面,我国的软件开发单位和发达国家相比,存在明显的差距。
国内外软件开发经验表明,软件测试需要消耗大量资源,软件测试所需的工时通常占据其总开发工时的40%到50% ,所以高质量履行和完成软件测试阶段的各种任务,十分重要。其中包括制定正确的测试策略,采用科学的测试方法和测试技术等,制订正确的测试策略自然应该成为关注的首选。
二、渐进测试策略
渐进测试策略是指将软件的测试进程,进一步细分为相互联系而又各不相同的子阶段,对交付测试的原始软件产品,从简单到复杂,从单元到系统逐步进行测试的、完整的测试体系框架。整个测试过程通常包括单元测试、综合测试、系统测试、认证和交收测试几个阶段。
采用渐进式测试策略,能够有效地降低错误定位的难度,有利于发现和改正错误。渐进测试必须从单元测试开始,单元测试的主要目的是检查和改正单元内部的错误,只有在单元测试完成之后才能进入与其他单元结合的综合测试。综合测试主要目的是检查单元之间的接口,以及检查程序的总体结构。系统测试的主要目的是检测软件是否满足需求说明的要求,这个阶段发现的错误往往属于高层错误,例如由于对用户要求的误解和用户要求的不一致造成的错误。改正这种类型的错误,需要付出昂贵的代价,是最不希望出现的事件。可见测试固然对保证软件质量十分重要,但是毕竟属于事后把关性质,预防为主仍然是最佳的选择。应该更加关注软件设计,特别是需求分析工作的质量。
根据软件的不同性质和某些软件的特殊要求,在上述4个阶段之外,还需要增加一些其他的测试阶段。表1是一个典型的办公自动化软件测试过程,它包括了单元测试、综合测试、软件系统测试、强度测试、认证和交收测试5个阶段。表2是一个典型的嵌入式系统的软件测试过程,它包括了软件单元测试、软件综合测试、软件系统测试、硬件和软件系统综合测试、认证和交收测试5个阶段。
如果换一个角度来观察渐进测试策略,可以认为渐进测试策略是针对软件设计过程所作的由下而上的逆向验证,从而使渐进测试的内在合理性得到进一步展示。图1显示了嵌入式软件测试过程和前期各个设计阶段的对应关系。
本人使用SilkTest进行自动化测试已有一段时间,有一些经验想和初学者们分享,所以就尝试编写这个SilkTest入门快打系列教程。编写该教程有两个目的,首先,希望能够告诉初学者如何快速的上手SilkTest而不必关心很多SilkTest的细节。实际上,SilkTest是一个强大的软件测试工具,应用面很广,使用它的人很少能够面面俱到把所有SilkTest提供的功能都用到,根据28原理,绝大多数人只用到了其中20%的功能,所以我希望这个教程能够覆盖SilkTest最常被用到的那部分功能,让初学者能够尽快将SilkTest使用起来。其次,我工作中主要是用SilkTest对C/S结构的软件进行测试,一直没有机会用SilkTest来测试B/S的应用,所以希望能藉此机会,在编写该系列教程的时候同时更多地学习如何使用SilkTest。
“天下功夫,唯快不破”,让我们赶紧开始SilkTest的快打旅程吧!
开始之前,请确定你的机器上安装了SilkTest软件,我装的是2006试用版,如果你的版本和我的不同,那也没什么关系,因为不同版本SilkTest的脚本语法基本上没有变化。
今天这一节,主要教你如何开始一个简单的测试。我们将要做的是测试WindowsXP自带的计算器,需要做的首先是新建一个测试项目,然后录制
一段测试脚本并指定测试点,最后运行该测试观察测试结果。
1、新建测试项目
首先打开你的SilkTest软件,然后从菜单里选择“File->New Project”,这时会弹出一个“New Project”的对话框,里面有两项“Create Project”和”Auto Generate Project”,我们选择“Create Project”然后点击”OK”按钮。这时又出现了一个对话框,要求你输入Project的名字,请在”Project Name”里面输入Calculator,然后选择你要保存Project的路径,例如:“D:/Program Files/Borland/SilkTest/Projects/Calculator”,点击确定。这个时候你的新项目Calculator就建好了。
2、录制测试脚本
在录制脚本之前,为了让SilkTest认识我们的待测软件,也就是常说的AUT(application under testing),我们必须捕捉和建立AUT的GUI定义,这几乎是所有GUI测试的第一步。为了捕捉GUI的定义,我们首先需要建立一个Test Frame,你可以简单的理解Test Frame里面定义了将要测试的GUI上各个对象。
由于我们要测试的是WindowsXP自带的计算器,所以请先打开该程序,你可以从”开始->程序->附件”里面找到它。打开后,你可以选择菜单”File->New”,这样你就能弹出的对话框中选择”Test Frame”文件类型了,然后在”new test frame”对话框中选择”application”为计算器,其他的默认好了,点击OK按钮,SilkTest就帮你自动在Include/Frame目录下生成了frame.inc文件,这里面就是计算器GUI的定义,它的代码看起来像如下这样:
[ ] const wMainWindow = 计算器 [ ] [+] window MainWin 计算器 [+] multitag “计算器” [ ] “$C:/WINDOWS/system32/calc.exe” [ ] [ ] // The working directory of the application when it is invoked [ ] const sDir = “C:/WINDOWS/system32″ [ ] [ ] // The command line used to invoke the application [ ] const sCmdLine = “C:/WINDOWS/system32/calc.exe ” [ ] [ ] // The first window to appear when the application is invoked [ ] // const wStartup = ? [ ] [ ] // The list of windows the recovery system is to leave open [ ] // const lwLeaveOpen = {?} [ ] [+] Menu 编辑E [ ] tag “编辑(E)” [+] MenuItem 复制C [+] multitag “复制(C)” [ ] “$300″ [+] MenuItem 粘贴P [+] multitag “粘贴(P)” [ ] “$301″ [+] Menu 查看V [ ] tag “查看(V)” [+] MenuItem 标准型T [+] multitag “标准型(T)” [ ] “$305″ [+] MenuItem 科学型S [+] multitag “科学型(S)” [ ] “$304″ [+] MenuItem 数字分组I [+] multitag “数字分组(I)” [ ] “$303″ [+] Menu 帮助H [ ] tag “帮助(H)” [+] MenuItem 帮助主题H [+] multitag “帮助主题(H)” [ ] “$317″ [+] MenuItem 关于计算器A [+] multitag “关于计算器(A)” [ ] “$302″ [+] TextField TextField1 [ ] tag “$403″ [+] PushButton MC [+] multitag “MC” [ ] “$113″ [+] PushButton MR [+] multitag “MR” [ ] “$114″ [+] PushButton MS [+] multitag “MS” [ ] “$115″ [+] PushButton M [+] multitag “M+” [ ] “$116″ [+] PushButton N7 [+] multitag “7″ [ ] “$131″ [+] PushButton N4 [+] multitag “4″ [ ] “$128″ [+] PushButton N1 [+] multitag “1″ [ ] “$125″ [+] PushButton N0 [+] multitag “0″ [ ] “$124″ [+] PushButton N8 [+] multitag “8″ [ ] “$132″ [+] PushButton N51 [+] multitag “5″ [ ] “$129″ [+] PushButton N2 [+] multitag “2″ [ ] “$126″ [+] PushButton PushButton24 [+] multitag “+?-” [ ] “$80″ [+] PushButton N91 [+] multitag “9″ [ ] “$133″ [+] PushButton N6 [+] multitag “6″ [ ] “$130″ [+] PushButton N3 [+] multitag “3″ [ ] “$127″ [+] PushButton N16 [+] multitag “?[16]” [ ] “$85″ [+] PushButton N52 [+] multitag “?[5]” [ ] “$90″ [+] PushButton N92 [+] multitag “?[9]” [ ] “$91″ [+] PushButton PushButton20 [+] multitag “-” [ ] “$93″ [+] PushButton PushButton26 [+] multitag “+” [ ] “$92″ [+] PushButton PushButton27 [+] multitag “=” [ ] “$112″ [+] PushButton Backspace [+] multitag “Backspace” [ ] “$83″ [+] PushButton CE [+] multitag “CE” [ ] “$82″ [+] PushButton C [+] multitag “C” [ ] “$81″ [+] StaticText StaticText1 [ ] tag “$401″ [+] PushButton N1X [+] multitag “1?x” [ ] “$107″ [+] PushButton Sqt [+] multitag “sqt” [ ] “$103″ [+] PushButton PushButton15 [+] multitag “%” [ ] “$109″ [+] StaticText StaticText2 [ ] tag “$1000″ [+] window MessageBoxClass MessageBox [ ] tag “~ActiveApp/[DialogBox]$MessageBox” [+] PushButton OK [ ] tag “OK” [+] PushButton Cancel [ ] tag “Cancel” [+] PushButton Yes [ ] tag “Yes” [+] PushButton No [ ] tag “No” [+] StaticText Message [ ] motif tag “#2″ [ ] tag “#1″ |
现在,你可以新建一个testcase了,选择菜单的”Record -> Testcase…”,在弹出的”Record Testcase”对话框中,你可以看到默认的testcase name是Test1,初始状态是DefaultBaseState,然后你点击StartRecording按钮就可以开始录制测试用例了。当你按下该按钮时,一般右下角屏幕会出现一个Record Status的对话框,然后你在屏幕上做的任何操作都可以被记录下来。在本例中,请点击计算器的清零按”C”,然后按顺序按”1″,”2″,”3″,”+”,”1″,”2″,”3″,”=”等按钮,你就完成了123+123操作,然后将鼠标悬停在计算器的结果框上,按组合键来停止记录,这时候会弹出一个新的窗口”Verify window”让你选择要verify的内容,也就是测试点。因为你最后是悬停在计算器的结果框上,SilkTest以为你会想要verify该控件的属性,它会让你选择该控件的属性,你只需要选择Text,也就是该次计算的结果,然后点击OK,再点击record Status对话框的Done。接着出现的Record Testcase对话框中点击Paste to Editor就把这次记录的脚本粘贴到一个新的脚本文件中了,保存它为Record.t。如果你得到了如下的代码,恭喜你录制已经完成。
[-] testcase Test1 () [-] recording [ ] 计算器.SetActive () [ ] 计算器.C.Click () [ ] 计算器.N1.Click () [ ] 计算器.N2.Click () [ ] 计算器.N3.Click () [ ] 计算器.PushButton26.Click () [ ] 计算器.N1.Click () [ ] 计算器.N2.Click () [ ] 计算器.N3.Click () [ ] 计算器.PushButton27.Click () [-] 计算器.TextField1.VerifyProperties ({…}) [ ] “” [-] {…} [ ] {“Text”, ”246. “} |
3、执行录制的测试脚本
脚本录制好了,从项目里面选择上你记录的Record.t文件,按F9就可以直接运行了。这个时候,SilkTest会激活计算器这个应用,然后以飞快的速度重复我们刚才做的操作,然后退出显示result文件,它的内容如下:
[ ] Script record.t – Passed [ ] Machine: (local) [ ] Started: 04:20:45PM on 31-May-2009 [ ] Elapsed: 0:00:02 [ ] Passed: 1 test (100%) [ ] Failed: 0 tests (0%) [ ] Totals: 1 test, 0 errors, 0 warnings [ ] [-] Testcase Test1 – Passed [ ] *** DefaultBaseState is setting 计算器 active, MainWin(“SilkTest入门快打.txt – 记事本|$C:/WINDOWS/notepad.exe”) was active |
该result文件表示我们的测试时Passed,见第一行。然后会记录测试开始的时间和耗费的时间。如果测试中有warning或者Error,result文件的结果会用紫色或红色的文字显示,没有任何问题的话,测试结果应该是黑色文字显示。
怎么样,使用silktest不是那么困难吧?你已经会测试简单的程序啦!
自动化测试设计简介
我们在本章提供的信息,对自动化测试领域的新人和经验丰富的老手都是有用的。本篇中描述最常见的自动化测试类型, 还描述了可以增强您的自动化测试套件可维护性和扩展性的“设计模式”。还没有使用这些技术的、有经验的自动化测试工程师会对这些技术更加感兴趣。
测试类型
您应该测试应用程序中的哪些部分?这取决于您的项目的各种影响因素:用户的期望,时间期限,项目经理设置的优先事项等等。但是,一旦项目边界定义完成,作为测试工程师,你必须做出要测试什么的决定。
为了对Web应用的测试类型进行分类,我们在这里创建了一些术语。这些术语并不意味着标准,但是这些概念对web应用测试来说非常典型。
● 测试静态内容
静态内容测试是最简单的测试,用于验证静态的、不变化的UI元素的存在性。例如:
→ 每个页面都有其预期的页面标题?这可以用来验证链接指向一个预期的页面。
→ 应用程序的主页包含一个应该在页面顶部的图片吗?
→ 网站的每一个页面是否都包含一个页脚区域来显示公司的联系方式,隐私政策,以及商标信息?
→ 每一页的标题文本都使用的<h1>标签吗?每个页面有正确的头部文本内吗?
您可能需要或也可能不需要对页面内容进行自动化测试。如果您的网页内容是不易受到影响手工对内容进行测试就足够了。如果,例如您的应用文件的位置被移动,内容测试就非常有价值。
● 测试链接
Web站点的一个常见错误为的失效的链接或链接指向无效页。链接测试涉及点各个链接和验证预期的页面是否存在。如果静态链接不经常更改,手动测试就足够。但是,如果你的网页设计师经常改变链接,或者文件不时被重定向,链接测试应该实现自动化。
● 功能测试
在您的应用程序中,需要测试应用的特定功能,需要一些类型的用户输入,并返回某种类型的结果。通常一个功能测试将涉及多个页面,一个基于表单的输入页面,其中包含若干输入字段、提交“和”取消“操作,以及一个或多个响应页面。用户输入可以通过文本输入域,复选框,下拉列表,或任何其他的浏览器所支持的输入。
功能测试通常是需要自动化测试的最复杂的测试类型,但也通常是最重要的。典型的测试是登录,注册网站账户,用户帐户操作,帐户设置变化,复杂的数据检索操作等等。功能测试通常对应着您的应用程序的描述应用特性或设计的使用场景。
● 测试动态元素
通常一个网页元素都有一个唯一的标识符,用于唯一地定位该网页中的元素。通常情况下,唯一标识符用HTML标记的’id’属性或’name’属性来实现。这些标识符可以是一个静态的,即不变的、字符串常量。它们也可以是动态生产值,在每个页面实例上都是变化的。例如,有些Web服务器可能在一个页面实例上命名所显示的文件为doc3861,并在其他页面实力上显示为doc6148,这取决于用户在检索的‘文档’。验证文件是否存在的测试脚本,可能无法找到不变的识别码来定位该文件。通常情况下,具有变化的标识符的动态元素存在于基于用户操作的结果页面上,然而,显然这取决于Web应用程序。
下面是一个例子。
<input id="addForm:_ID74:_ID75:0:_ID79:0: checkBox" type="checkbox" value="true" /> |
这是一个HTML标记的复选框,
其ID (addForm:_ID74:_ID75:0:_ID79:0:checkBox) 是一个动态生成的值。这个页面下次被打开时,复选框的ID将可能是一个不同的值。
● Ajax的测试
Ajax是一种支持动态改变用户界面元素的技术。页面元素可以动态更改,但不需要浏览器重新载入页面,如动画,RSS源,其他实时数据更新等等。Ajax有不计其数的更新网页上的元素的方法。但是了解AJAX的最简单的方式,可以这样想,在Ajax驱动的应用程序中,数据可以从应用服务器检索,然后显示在页面上,而不需重新加载整个页面。只有一小部分的页面,或者只有元素本身被重新加载。
验证结果
● 断言assert与验证verify
什么时候使用断言命令,什么时候使用验证命令?这取决于你。差别在于在检查失败时,你想让测试程序做什么。你想让测试终止,还是想继续而只简单地记录检查失败?
这需要权衡。如果您使用的断言,测试将在检查失败时停止,并不运行任何后续的检查。有时候,也许是经常的,这是你想要的。如果测试失败,你会立刻知道测试没有通过。TestNG和JUnit等测试引擎提供在开发测试脚本时常用的插件,可以方便地标记那些测试为失败的测试。优点:你可以直截了当地看到检查是否通过。缺点:当检查失败,后续的检查不会被执行,无法收集那些检查的结果状态。
相比之下,验证命令将不会终止测试。如果您的测试只使用验证,可以得到保证是—假设没有意外的异常—测试会被执行完毕,而不管是否发现缺陷。缺点:你必须做更多的工作,以检查您的测试结果。也就是说,你不会从TestNG和JUnit得到反馈。您将需要在打印输出控制台或日志文件中查看结果。每次运行测试,你都需要花时间去查看结果输出。如果您运行的是数以百计的测试,每个都有它自己的日志,这将耗费时间。及时得到反馈会更合适,因此断言通常比验证更常使用。
● 权衡:assertTextPresent,assertElementPresent和assertText
您现在应该熟悉这些命令及使用它们的机制。如果没有,请参阅相关章节。在构建你的测试时,你需要决定
→ 只检查在页面上的文本吗?(verify/ assertTextPresent)
→ 只检查是否在页面上存在HTML元素吗?即文本,图像,或其他没被检查的内容,只要和HTML标记相关。(verify/ assertElementPresent)
→ 需要同时检查元素和它的文本内容?(verify/ assertText)
没有正确的答案。这取决于您的测试要求。如有疑问,请使用assertText,因为这是最严格的类型检查点。您可以随后更改它,但至少你不会遗漏任何潜在的故障。
Verify/ assertText是最特殊的测试类型。HTML元素(标签)或文本的不符合都会导致测试失败。也许你的网页设计师经常改变页面面,而你不希望在他们改变页面时,你的测试失败,因为这是期望中的周期性变更。但是,假如你仍然需要检查的页面上的东西,如段落、标题文本或图像。在这种情况下,您可以使用verify/ assertElementPresent。这将确保一个特定类型的元素存在(如果使用XPath,可以确保它相对页面内其他对象的存在)。但你不关心的内容是什么,你只关心某个特定的元素,比方说,一个图片在一个特定的位置。
随着时间的推移和经验的积累,如何决定使用还是非常简单的。
定位元素的策略
● 选择一个定位策略
有多种方式选择页面上的对象。但面对这些定位类型,如何权衡呢?回想一下,我们定位一个对象的方式:
→ 元素的ID
→ 元素的name属性
→ XPath语句
→ 通过一个链接的文本
→ 文档对象模型(DOM)
使用元素的ID或name定位符,在测试执行方面来说,是最有效的方式。也让你的测试代码更具可读性,如果在页面源代码中的ID或name属性被友好命名的话。XPath语句需要更长的时间来处理,因为浏览器必须运行它的XPath处理器。在Internet Explorer 7,XPath出了名的慢。
使用链接的文本进行定位是很方便的,并运行起来也不错。这种技术只适用于链接。另外,如果链接文本很可能会经常改变,使用<a>标签定位元素将是更好的选择。
不过,有时你必须使用XPath定位。如果一个页面元素没有一个ID或者name属性,除了XPath定位没得选择。(DOM定位器不再普遍使用,因为,XPath可以做得更好。DOM定位器只简单地为遗留测试而存在)。
相对使用ID或name属性定位,使用XPath进行定位有一个独特的优势。使用XPath(DOM)中,你可以找到页面上相对于其他对象的一个对象。例如,如果有一个链接必须存在<div>标签里的第二个段落内,您可以使用XPath进行定位。使用ID和name属性定位,你只能得出它们存在指定的页面,而不知具体的页面位置。如果你必须测试显示公司标志的图像出现在页面顶部的头部分,XPath定位可能是更好的选择。
● 定位动态元素
正如前面测试类型部分所述,动态元素的页面标识在不同的页面实例上市不同的。例如,
<a class="button" id="adminHomeForm" onclick="return oamSubmitForm('adminHomeForm', 'adminHomeForm:_ID38');" href="#">View Archived Allocation Events</a> |
这个HTML锚标记定义了一个ID属性为“adminHomeForm”按钮。和大部分HTML标签相比,这是一个相当复杂的锚标记,但它仍然是一个静态标签。每次页面被浏览器加载时,HTML将保持不变。它的ID在所有的页面实例里保持不变,也就是说,页面被展示时,这个UI元素总是有同样的标识符。所以,点击此按钮的测试脚本(Selenium Server)如下所示:
selenium.click("adminHomeForm"); |
然而,你的应用程序,可能生成动态的HTML标识符。在不同的网页实例中,标识符发生改变。例如,一个动态的页面的HTML元素可能会是这个样子:
<input id="addForm:_ID74:_ID75:0:_ID79:0:checkBox" type="checkbox" name="addForm:_ID74:_ID75:0:_ID79:0:checkBox" value="true" /> |
这是一个复选框,id和name属性都是addForm:_ID74:_ID75:0:_ID79:0:checkBox。在这种情况下,使用标准的定位,测试脚本应该是这样子的:
selenium.click("addForm:_ID74:_ID75:0:_ID79:0:checkBox"); |
对于动态生成的标识符,这种做法行不通。下一次页面加载时,标识符将是一个不同的值,执行上述脚本会遇到“element not found”错误。
要更正该问题,一个简单的解决办法是使用XPath定位替代ID定位器。因此,对于该复选框,可以简单地使用
selenium.click("//input"); |
或者,如果它不是在页面上的第一个文本输入域,尝试一个更详细的XPath语句。
selenium.click("//input[3]"); |
或
selenium.click("//div/p[2]/input[3]"); |
但是,如果你确实需要使用ID来定位元素,可以换一种不同的解决方案。您可以先捕捉到网站的这个ID,然后再使用它,例如:
String[] checkboxids = selenium.getAllFields(); // Collect all input IDs on page. for(String checkboxid:checkboxids) { if(checkboxid.contains("addForm")) { selenium.click(expectedText); } } |
如果页面上只有一个复选框的ID文本为“expectedText”时,这种方法工作。
● 定位Ajax元素
定位、验证AJAX元素的最好的方式是使用Selenium 2.0 webdriver的API,它专门解决Selenium 1.0测试AJAX元素的一些限制。
在Selenim 2.0中,可以使用waitfor()方法来等待一个页面元素变得可用。该参数是一个WebDriver用来实现定位的By对象。这是WebDriver的章节中详细解释。
在Selenium 1.0(Selenium-RC的)中,要做到这一点需要编写更多的编码,但它并不难。首先检查元素,如果它存在,等待预定义的时间段,然后再重新检查。这在循环内执行,如果超过一个预定的超时,元素不存在则终止循环。
让我们考虑页面上实现AJAX效果的一个链接(链接= ajaxLink),可以使用循环处理:
// Loop initialization. for (int second = 0;; second++) { // If loop is reached 60 seconds then break the loop. if (second >= 60) break; // Search for element "link=ajaxLink" and if available then break loop. try { if (selenium.isElementPresent("link=ajaxLink")) break; } catch (Exception e) {} // Pause for 1 second. Thread.sleep(1000); } |
这当然不是唯一的解决办法。Ajax是一个共同的话题,在用户论坛上,查找一下之前的讨论,看看别人是如何做的。
封装Selenium调用
与任何编程一样,你需要使用工具函数来处理在测试代码中重复的函数。避免重复的方法之一是封装常用的Selenium方法的调用。例如,测试时经常点击页面上的元素,等待页面加载。
selenium.click(elementLocator); selenium.waitForPageToLoad(waitPeriod); |
为了不重复上述代码,你可以写一个包装方法实现这两个功能。
/** * Clicks and Waits for page to load. * * param elementLocator * param waitPeriod */ public void clickAndWait(String elementLocator, String waitPeriod) { selenium.click(elementLocator); selenium.waitForPageToLoad(waitPeriod); } |
● 判断元素存在的“安全操作”
另一种常见的封装Selenium的方法,在执行进一步操作前检查页面上的元素存在性。这有时被称为“安全操作”。例如,下面的方法可用于实现一个依赖期望的元素存在的安全操作。
/** * Selenum-RC -- Clicks on element only if it is available on page. * * param elementLocator */ public void safeClick(String elementLocator) { if(selenium.isElementPresent(elementLocator)) { selenium.click(elementLocator); } else { // Using the TestNG API for logging Reporter.log("Element: " +elementLocator+ ", is not available on page - " +selenium.getLocation()); } } |
上述例子使用的是Selenium 1.0 API,Selenium 2.0同样支持安全操作。
/** * Selenium-WebDriver -- Clicks on element only if it is available on page. * * param elementLocator */ public void safeClick(String elementLocator) { WebElement webElement = getDriver().findElement(By.XXXX(elementLocator)); if(webElement != null) { selenium.click(elementLocator); } else { // Using the TestNG API for logging Reporter.log("Element: " +elementLocator+ ", is not available on page - " + getDriver().getUrl()); } } |
在第二个例子中,’XXXX’方法是一个占位符,可以用元素定位方法进行替换。
使用安全方法取决于测试开发人员的决定。因此,如果测试需要继续执行,即使知道页面上一些元素没有发现,这时可以使用安全方法,并发送一条缺少元素的消息到日志文件。这基本上等于实现了带报告机制的验证,而不是一个失败就终止执行的断言。但是,如果元素必须在页面上出现,以便能够执行进一步的操作(如一个门户网站主页上的登录按钮),这时安全方法技术不应该被使用。
本文转载自:http://www.loggingselenium.com/
上一篇:Selenium自动化测试用例设计注意事项(一)
UI映射
一个UI映射是一种机制,它存储所有的定位器的测试套件在一个地方,方便修改UI元素的路径标识符或改变在AUT。测试脚本,然后使用UI地图定位以被测试的元件。基本上,UI地图是一个存储库的测试脚本对象,对应于被测试的应用程序的UI元素。
是什么让一个UI地图有帮助吗?其主要目的是测试脚本的管理更加容易。当定位需要编辑,有一个中央位置轻松地找到对象,而不是通过搜索测试脚本代码。此外,它允许改变的标识符在一个地方,而不是在多个地方,以使更改在测试脚本,或为此事,在多个测试脚本。
总之,一个UI地图有两个显着的优点。
● UI对象使用一个集中的位置,而不是让他们分散在整个脚本。这使得脚本维护更高效。
● 神秘的HTML标识符和名称可以被赋予了更多的人类可读的名字,提高测试脚本的可读性。
考虑下面很难理解的测试代码(Java语言)。
public void testNew() throws Exception { selenium.open(http://www.test.com); selenium.type("loginForm:tbUsername", "xxxxxxxx"); selenium.click("loginForm:btnLogin"); selenium.click("adminHomeForm:_activitynew"); selenium.waitForPageToLoad("30000"); selenium.click("addEditEventForm:_IDcancel"); selenium.waitForPageToLoad("30000"); selenium.click("adminHomeForm:_activityold"); selenium.waitForPageToLoad("30000"); } |
该代码很难被那些不熟悉待测应用(AUT)页面源代码的人理解。即使是待测应用的固定用户可能也很难理解这段脚本代码的作用。一个更好的脚本可能是:
public void testNew() throws Exception { selenium.open(http://www.test.com); selenium.type(admin.username, "xxxxxxxx"); selenium.click(admin.loginbutton); selenium.click(admin.events.createnewevent); selenium.waitForPageToLoad("30000"); selenium.click(admin.events.cancel); selenium.waitForPageToLoad("30000"); selenium.click(admin.events.viewoldevents); selenium.waitForPageToLoad("30000"); } |
使用备注和空格换行、再加上UI映射标识,下面的代码更加易读:
public void testNew() throws Exception { // Open app url. selenium.open(http://www.test.com); // Provide admin username. selenium.type(admin.username, "xxxxxxxx"); // Click on Login button. selenium.click(admin.loginbutton); // Click on Create New Event button. selenium.click(admin.events.createnewevent); selenium.waitForPageToLoad("30000"); // Click on Cancel button. selenium.click(admin.events.cancel); selenium.waitForPageToLoad("30000"); // Click on View Old Events button. selenium.click(admin.events.viewoldevents); selenium.waitForPageToLoad("30000"); } |
有多种方法可以实现UI映射。可以创建一个类或结构体来存储字符串变量,每个变量存储一个定位信息。或者,使用一个文本文件来存储键值对。在Java中,一个包含键值对的属性property文件可能是最好的方法。
考虑如下属性文件prop.properties,为上述代码例子中的UI元素指定了 “别名”:
admin.username = loginForm:tbUsername admin.loginbutton = loginForm:btnLogin admin.events.createnewevent = adminHomeForm:_activitynew admin.events.cancel = addEditEventForm:_IDcancel admin.events.viewoldevents = adminHomeForm:_activityold |
其中定位信息还是指向页面的HTML对象,但我们在测试脚本和UI元素之间引入一层抽象层。测试类从属性文件中读取定位信息,从而实现UI映射。
页面对象设计模式
页面对象设计模式,可以提高自动化测试脚本的维护性、减少代码重复,越发流行。页面对象是一个面向对象的类,作为待测应用对外提供的接口。测试代码在需要和UI页面交互时,使用此页面对象类的方法。这样做的好处是,如果UI页面发生变化,测试代码本身并不需要改变,只需要改变相应的页面对象的代码。为适应新UI页面的所有更改,都位于一个地方。
页面对象设计模式具有以下优点:
1、测试代码和页面相关的代码,比如页面元素定位信息(若使用UI映射,也包括定位信息的应用),页面布局等,完全分离;
2、可以维护单一的储存库来存储页面提供的服务或操作,而不是把他们分散在测试代码中。
在这两种情况下,这使得任何由于UI界面变化导致的修改,都可以在一个地方进行修改。关于该技术的更多有用信息,可以在众多的博客上找到。我们也鼓励读者去阅读更多。 许多人写这样的设计模式和超出本用户指南的范围,可以提供有用的提示。不过,为了让你开始,我们将举例说明页面对象的一个简单的例子。
首先,考虑一个例子,典型的自动化测试,不使用页面对象。
/*** * Tests login feature */ public class Login { public void testLogin() { selenium.type("inputBox", "testUser"); selenium.type("password", "my supersecret password"); selenium.click("sign-in"); selenium.waitForPageToLoad("PageWaitPeriod"); Assert.assertTrue(selenium.isElementPresent("compose button"), "Login was unsuccessful"); } } |
这种方法有两个问题。
1、没有分离测试代码和待测应用的定位器(在这个例子中是ID);两者都交织在一个单一方法中。如果待测应用UI改变了它的标识,布局,或登录输入和处理的方式变化,测试代码本身必须改变。
2、ID定位信息分散在多个测试代码中,所有的测试不得不使用此登录页面。
使用页面对象技术,上述测试代码可以按如下方式重写,为登录页面的页面对象例子:
/** * Page Object encapsulates the Sign-in page. */ public class SignInPage { private Selenium selenium; public SignInPage(Selenium selenium) { this.selenium = selenium; if(!selenium.getTitle().equals("Sign in page")) { throw new IllegalStateException("This is not sign in page, current page is: " +selenium.getLocation()); } } /** * Login as valid user * * @param userName * @param password * @return HomePage object */ public HomePage loginValidUser(String userName, String password) { selenium.type("usernamefield", userName); selenium.type("passwordfield", password); selenium.click("sign-in"); selenium.waitForPageToLoad("waitPeriod"); return new HomePage(selenium); } } |
主页的页面对象可能会是这个样子:
/** * Page Object encapsulates the Home Page */ public class HomePage { private Selenium selenium; public HomePage(Selenium selenium) { if (!selenium.getTitle().equals("Home Page of logged in user")) { throw new IllegalStateException("This is not Home Page of logged in user, current page" + "is: " +selenium.getLocation()); } } public HomePage manageProfile() { // Page encapsulation to manage profile functionality return new HomePage(selenium); } /*More methods offering the services represented by Home Page of Logged User. These methods in turn might return more Page Objects for example click on Compose mail button could return ComposeMail class object*/ } |
现在,使用上述两个页面对象的登录测试代码,如下所示。
/*** * Tests login feature */ public class TestLogin { public void testLogin() { SignInPage signInPage = new SignInPage(selenium); HomePage homePage = signInPage.loginValidUser("userName", "password"); Assert.assertTrue(selenium.isElementPresent("compose button"), "Login was unsuccessful"); } } |
怎么样使用页面对象进行设计有很大的灵活性,但也有一些基本的规则以保证得到测试代码具有所需的可维护性。页面对象本身不应该被验证或断言。这应该是测试的一部分,并应始终在测试代码中去验证或断言,而不要放在页面对象内。页面对象将包含页面展现,方法的形式表示页面提供的服务,但不需要包含应该在测试代码中维护的代码。
唯一的应该存在页面对象中的验证方法是,验证页面、页面上的重要元素,被正确的加载。这这个验证应该在页面初始化时进行。在上面的例子中,SignInPage 和 HomePage 的构造函数检查了期望的页面是否可用,是否准备好接受测试代码的请求。
页面对象并不一定要代表整个页面。页面对象设计模式可用于表示页面上组件。在待测应用上的一个页面若有多个组件,每个组件对应一个页面对象可以提高可维护性。
在测试时,还会遇到其他的测试设计模式。有些人用一个页面工厂模式来实例化页面对象。讨论所有的这些测试模式,超出了本文档的的范围。在这里,我们只为大家介绍概念,使读者知道这些东西可以些什么。正如前面提到的,很多人都在博客上讨论这个话题,我们鼓励读者搜索这些话题。
数据驱动测试
数据驱动测试是指相同的测试(或测试集)可以使用不同的数据多次执行。这些数据集往往来自外部文件,如csv文件,文本文件,或者是从数据库加载。数据驱动测试是一种常用的自动化测试技术,使用不同的输入对应用程序进行多次验证。当测试被针对不同的数据进行设计时,所输入的数据就可以扩展,基本上不需要修改测试代码就可以进行更多的测试。
# Collection of String values source = open("input_file.txt", "r") values = source.readlines() source.close() # Execute For loop for each String in the values array for search in values: sel.open("/") sel.type("q", search) sel.click("btnG") sel.waitForPageToLoad("30000") self.failUnless(sel.is_text_present("Results * for " + search)) |
上面的Python代码打开一个文本文件,这个文件每行包含不同的搜索字符串。然后代码保存字符串到一个字符串数组,对数值进行遍历,使用搜索字符串进行查询,并进行断言。
这是一个非常简单的例子,但其中的思路表明,可以很简单的使用编程、脚本语言进行数据驱动的测试。有关更多示例,请参阅 Selenium RC wiki 来了解如何从电子表格读取数据或使用TestNG的提供数据。此外,这是一个在自动化测试的专业人士圈内众所周知的话题之一,包括那些不使用Selenium的自动化圈子,因此搜索互联网上的“数据驱动测试”,会得到许多关于这一主题的博客。
数据库验证
另一种常见的测试类型是,比较用户界面上的数据和存储在后台数据库中的数据。因为你也可以使用一种编程语言进行数据库查询,假设你有数据库相关的函数,你可以用它们来检索数据,然后使用这些数据来验证页面上所显示的数据是正确的。
考虑如下例子,从数据库中进行检索注册电子邮件地址,然后再和界面上的数据进行比较。代码如下,先建立一个数据库连接,并从数据库中检索数据,使用的是Java语言:
// Load Microsoft SQL Server JDBC driver. Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); // Prepare connection url. String url = "jdbc:sqlserver://192.168.1.180:1433;DatabaseName=TEST_DB"; // Get connection to DB. public static Connection con = DriverManager.getConnection(url, "username", "password"); // Create statement object which would be used in writing DDL and DML // SQL statement. public static Statement stmt = con.createStatement(); // Send SQL SELECT statements to the database via the Statement.executeQuery // method which returns the requested information as rows of data in a // ResultSet object. ResultSet result = stmt.executeQuery ("select top 1 email_address from user_register_table"); // Fetch value of "email_address" from "result" object. String emailaddress = result.getString("email_address"); // Use the emailAddress value to login to application. selenium.type("userID", emailaddress); selenium.type("password", secretPassword); selenium.click("loginButton"); selenium.waitForPageToLoad(timeOut); Assert.assertTrue(selenium.isTextPresent("Welcome back" +emailaddress), "Unable to log in for user" +emailaddress) |
这是一个简单的Java例子从数据库中检索数据。
本文转载自:http://www.loggingselenium.com/
相关链接:
风险管理
项目的未来充满风险。风险是一种不确定的事件或条件,一旦发生,会对至少一个项目目标造成影响,如范围、进度、成本和质量。风险可能有一种或多种起因,一旦发生可能有一项或多项影响。风险的起因包括可能引起消极或积极结果的需求、假设条件、制约因素或某种状况。
项目风险管理包括风险管理规划、风险识别、风险分析、风险应对规划和风险监控等各个过程。项目风险管理的目标在于提高项目积极事件的概率和影响,降低项目消极事件的概率和影响。对于已识别出的风险,需要分析其发生概率和影响程度,并进行优先级排序,优先处理高概率和高影响风险。
风险识别
风险识别是系统化地识别已知的和可预测的风险,才能提前采取措施,尽可能避免这些风险的发生,最重要的是量化不确定性的程度和每个风险可能造成损失的程度。
问题1:风险可分为哪些类型?
建议:
1、需求风险,如需求变更频繁、缺少有效的需求变更管理。
2、计划风险,如实际规模比估算规模大很多、项目交付时间提前但没有调整项目计划。
3、人员风险,如项目新员工较多、骨干员工不稳定。
4、环境风险,如设备未及时到位、新开发工具学习时间较长、环境未及时到位。
5、产品风险,如新产品、新技术、基础版本质量不高。
6、客户风险,如客户问题确认时间过长、客户不能保证投入需求评审。
7、组织和管理风险,如低效的项目团队结构降低生产率、缺乏必要的规范,导致工作失误与重复工作。
8、过程风险,如前期质量保证活动执行不到位,导致后期的返工工作量过大、需求方案确认时间过长。
问题2:风险识别有哪些方法?
建议:
1、头脑风暴:组织测试组成员识别可能出现的风险;
2、访谈:找内部或外部资深专家访谈;
3、风险检查列表:对照表的每一项进行判断,逐个检查风险。
风险评估
风险评估是对已识别风险的影响和可能性大小的分析过程。从经验来看,许多最终导致项目失败、延期、客户投诉的风险,都是从不起眼的小风险开始,由于这些小风险长时间得不到重视和解决,最终严重的影响到项目交付。
怎样搭建与培养自动化测试团队
引:毫无疑问,从企业的立场来看,它期望自动化测试能为企业带来生产效率的提升和测试成本的缩减,说通俗点,就是能用尽可能少的人干尽可能多的事。因此对于那些能够在自动化测试领域做出突出成绩的测试人员,企业从来都是一贯地不遗余力地进行奖赏和激励。因此,在自动化测试领域里,一方面如我们前章所说布满了风险和陷阱,同时另一方面,我们更应该看到充满了很多的机会,对测试人员的职业生涯发展有着至关重要的影响。
好,聪明的你上场了,你正在接管一个正在做手工测试的团队,或者你目前就处于这样的一个团队里,而老板对自动化测试概念又知之不多,不能给予你完全信任的强有力支持,你如何在重重困难中,推行自动化测试实施,而最终取得团队和个人的最大成功?这是我们本章要讨论的重点。
一个好的目标,首先它能够赢得老板的眼球,并有可能逐步转化为老板对你自动化测试实施的支持。
自动化测试项目的实施离不开上级领导的支持,这是一个组织上很关键的因素。因为自动化测试前期的准备要投入人,时间,金钱等资源,比如自动化测试需要买工具,工具则需要培训,而开发工具脚本又需要投入人和时间,如果领导不能在这些方面给予支持,测试人员就真的就成了“巧妇难为无米之炊”,自动化测试的成功更无从谈起了。
所以,在自动化测试的启动阶段,一定要先有一个好的而且可行的自动化测试的目标或想法,它会吸引老板的注意力,并可能获得支持。尤其在自动化测试实施已经比较成熟的企业里,在众多自动化测试解决方案里,一个让人耳目一新甚至拍案叫绝的方案会给老板留下深刻的印象。
但是对于自动化测试刚起步的企业来说,有一些需要特别注意和警惕的地方。这是因为,在知识和经验都不丰富到足以洞察自动化测试本质和规律的时候,很多老板表面上对自动化测试是热情的支持,但实际真实的态度却是底气不足,半信半疑。
我曾遇到过两个极端的例子,一个是某通讯企业的研发总监,在软件开发和测试领域都有深厚的经验,但对自动化测试却有着深刻的怀疑,他认为QTP等测试工具并不能真正地从根本上解决测试效率的问题,因此他一直下意识地回避和推迟团队中自动化测试的实施;而另外一个例子是某大型外企的测试经理则是一个技术专家,他对软件自动化测试十分地钟情,几近狂热,认为任何工作都可以交付给程序来做,因此他把自动化测试推到了极致,他的团队开发了大量的脚本和程序,有的只为demo,有的只为验证bug。
这两个极端的例子其实是当前软件业界自动化测试实施的缩影,实际上,这两个人的表现更像是同一个人的两面性格,自动化测试上马时盲目乐观,失败后“恨屋及乌”。一番折腾下来,他们对自动化测试是敏感和谨慎的,对于你提出的任何自动化测试目标,他们表面上会支持,实际上更多采用的是观望态度。换句话说,在这种情形下,老板对自动化测试项目的支持是犹豫的和脆弱的。因此,老板是否能够保持对你强有力和持续的支持,不光你要有一个好的自动化测试目标,而是更取决于后续的自动化测试实施能带来实实在在的效益。
【案例】:
测试主管小王打算在自己的测试部门实施系统测试自动化,在经过工具评估后(有关评估详见第三章Evaluation一节),他和他的团队决定使用java开源的selenium做为测试工具。这个想法获得了小王上级张总的认可和支持。
挑战:小王在着手实施的时候,有如下疑惑和困扰:
1)小王和他的团队没有丰富的自动化测试实施经验,因此,虽然经过了前期的测试自动化效益估算,但对于selenium的解决方案到底能否在项目中实施成功,要开发投入多少人力,维护量有多大,小王依然心里没有十足的把握。
2)小王的上级张总是一个雷厉风行的人,他对这次自动化测试的实施也抱有很高的希望,小王如何能够说服张总认识到自动化测试实施的风险,并能给予理解和持续的支持,这是一个要考虑的问题。
对策:小王决定采取以下的措施来最大程度地减小风险,并获得张总的理解和支持。
1)对于第一个问题,由于对测试脚本程序的规模和功能都无法准确预测,小王决定采用快速原型法来开发自动化测试程序,首先在部分核心功能模块中做试点,一边实施一边总结经验,然后再将成功经验进一步推广到整个产品模块。
2) 关于和张总的沟通交流问题,小王决定先准备一个自动化测试的演示程序,邀请张总参加演示会。在演示会上,小王准备了三个演示点,一个是有关自动化测试能替我们做那些工作,一个是自动化测试不能替我们做的工作,另外一个是自动化测试运行中的各种风险和干扰因素。
结果:最后实施的结果是:
(a)小张通过快速原型开发方法,以时间为代价换来了自动化测试实施的稳定和高质量,这为自动化测试的成功实施提供了技术保障。
(b)张总对演示会的内容十分感兴趣,并且和小王约定每隔一个月就进行一次演示会,以便了解自动化测试的状态和进展,并及时解决中间出现的问题。这为自动化测试的成功实施提供了组织保障。
在录制会话过程中或在编辑测试或组件时添加检查点。在录制了初始测试或组件之后,通常可以更为方便地定义检查。有几种方法可以添加检查点。
在录制或编辑时添加检查点
◆ 使用“插入”菜单上的命令,或者单击“测试”工具栏上的“插入检查点”按钮旁边的箭头。这将显示与关键字视图的选定步骤相关的检查点选项的菜单。
只在编辑时添加检查点
◆ 右键单击关键字视图中您要添加检查点的步骤,然后选择“插入标准检查点”。
◆ 右键单击 Active Screen 中的任意对象,然后选择“插入标准检查点”。可使用该选项为 Active Screen 中的任意对象创建检查点(即使该对象不是关键字视图中任一步骤的组成部分)。
注意:
如果使用“Active Screen”方法,请确保 Active Screen 包含有关待检查对象的充足数据。
了解检查点类型
检查点类型 | 描述 | 用法示例 |
标准检查点 | 检查对象的属性值。 | 检查是否选中某单选按钮。 |
图像检查点 | 检查图像的属性值。 | 检查图像源文件是否正确。 |
表检查点 | 检查表中的信息。 | 检查表单元格中的值是否正确。 |
页面检查点 | 检查网页的特性。 | 检查加载网页所需的时间,或者检查网页是否包含中断链接。 |
文本/文本区域检查点 | 检查文本字符串是否显示在网页或应用程序窗口中的适当位置。 | 检查预期的文本字符串是否显示在网页或对话框上的预期位置。 |
位图检查点 | 将网页或应用程序的某个区域捕获为位图后对其进行检查。 | 检查网页或网页的任何部分是否能按预期显示。 |
数据库检查点 | 检查应用程序或网站所访问的数据库内容 | 检查数据库查询中的值是否正确。 |
可访问性检查点 | 对网站区域进行识别,以检查是否符合 508 部分。 | 检查网页上的图像是否包含 ALT 属性(该属性是 W3C Web 内容可访问性规则所要求的)。 |
XML 检查点 | 检查 XML 文档的数据内容。 | 注意:XML 文件检查点用于检查特定的 XML 文件;XML 应用程序检查点用于检查网页中的 XML 文档。
|
您可以插入下列检查点类型以检查网站或应用程序中的各种对象。
◆ “标准检查点”检查应用程序或网页中对象的属性值。标准检查点会检查各种对象,如按钮、单选按钮、组合框、列表等等。例如,您可以检查在选择单选按钮之后它是否处于激活状态,或者可以检查编辑字段的值。标准检查点在所有加载项环境中都受到支持。
◆ “图像检查点”检查应用程序或网页中的图像的值。例如,您可以检查所选图像的源文件是否正确。
注意:可以通过在图像对象上插入标准检查点来创建图像检查点。图像检查点在 Web 环境中受到支持。
◆ “位图检查点”检查位图格式的网页或应用程序区域。例如,假设您有一个网站,可以显示用户指定的城市的地图。该地图具有用于缩放的控制键。在单击放大地图的控制键后,您可以录制所显示的新地图。使用位图检查点,您可以检查该地图是否正确放大。位图检查点在所有加载项环境中都受到支持。
◆ “表检查点”检查表内部的信息。例如,假设您的应用程序或网站包含一个表,该表列出了从纽约到旧金山的所有可用航班。您可以添加一个表检查点,以检查该表中的第一个航班的时间是否正确。
注意:可以通过在表对象中插入标准检查点来创建表检查点。表检查点在 Web 和 ActiveX 环境中受到支持。表检查点还在很多外部加载项环境中受到支持。
◆ “文本检查点”检查文本字符串是否显示在应用程序或网页的适当位置中。例如,假设您的应用程序或网页显示句子:“从纽约到旧金山的航班”。您可以创建一个文本检查点,检查词语“纽约”是否显示在“从”与“到旧金山的航班”之间。文本检查点在所有加载项环境中受到支持(请参阅下面的“受支持的检查点” )。
◆ “文本区域检查点”检查文本字符串是否按照指定的条件显示在 WindowsApplications 中所定义的区域内。例如,假设您的 Visual Basic 应用程序有一个按钮,显示“查看文档< 号码>”,其中< 号码> 会被输入到应用程序中其他位置的窗体的四位数字代码替换。您可以创建一个文本区域检查点,以确认在该按钮上显示的号码与在窗体中输入的号码相同。文本区域检查点在标准 Windows、Visual Basic 和 ActiveX 加载项环境中受到支持。文本区域检查点还在一些外部加载项环境中受到支持。
◆ “可访问性检查点”确定可能不符合万维网联盟 (W3C) Web 内容可访问性规则的网站区域。例如, W3C Web 内容可访问性规则的规则 1.1 要求您为每个非文本元素提供等效文本。您可以添加“Alt”属性检查,检查按照该规则要求具有“Alt”属性的对象是否确实具有这样的标记。可访问性检查点在 Web 环境中受到支持。
◆ “页面检查点”检查网页的特性。例如,您可以检查加载网页所需的时间,或者检查网页是否包含损坏的链接。
注意:可以通过在页面对象上插入标准检查点来创建页面检查点。页面检查点在 Web 环境中受到支持。
◆ “数据库检查点”检查由您的应用程序访问的数据库的内容。例如,您可以使用数据库检查点来检查网站上包含航班信息的数据库的内容。数据库检查点在所有环境中都受支持(请参阅下面的“受支持的检查点” )。
◆ “XML 检查点”检查 XML 文件中的 XML 文档的数据内容,或检查网页和帧中的 XML 文档的数据内容。有关 XML 检查点的详细信息,请参阅第 11 章“检查 XML”。XML 检查点(网页/ 帧)在 Web 环境中受到支持; XML 检查点(文件)在所有环境中受到支持(请参阅下面的“受支持的检查点” )。
版权声明:本文出自 悄无声息143 的51Testing软件测试博客:http://www.51testing.com/?384065
原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。