我发现很多人,包括论坛上的网友,还有很多身边的同事都对UI自动化充满了一些恐惧感,从而不敢触及它。当然也有一定的原因是觉得UI自动化没太深的技术含量,这也是我讨厌UI自动化的唯一原因。但是,一旦让这些人去做UI自动化的话,是很难做好的,因为UI自动化需要一定的经验,而我个人认为一年的经验,一个正规的项目应该都能具备编写良好UI自动化测试的能力。因此,对于后来的人,我想把UI自动化关键的几条再谈一谈,UI自动化确实没什么技术含量,你掌握了以下几点也能成为一个小专家了。
1. 用高级语言编写自动化程序,在UI的部分调用UI自动化工具。我反对纯用UI自动化工具去写自动化,因为那样就太死板了,而且功能不强大,不灵活。我推荐学好一门高级语言,把大多数的自动化都用这门高级语言实现,只在需要UI操作的时候才调用UI工具。
2. 只在你测试的UI模块上进行自动化的测试,其他地方避免用UI去操作,使用高级语言去实现。这样你需要用UI的地方就进行了最小化,从而使得只有在真正需要UI的地方才自动化UI,因此测试程序会相对更稳定。
3. UI自动化最基本的操作就是发现控件和操作控件。尽量避免用text来发现控件,而使用一些固定的控件属性来发现,比如Control ID等等。这样的话,测试程序会更稳定,开发改变文本不会影响到你,而你也不用担心localization的问题。
4. 操作控件分为模拟用户操作和事件驱动。简单的例子就是,模拟用户操作就是鼠标真的去点一下,而事件驱动则是跳过点击直接引发点击的事件。我以前用过具有这种功能的工具,但是最近几年用的工具不具备这个功能。
5. 解决好同步问题。UI自动化最不稳定的地方就是同步问题了,你不能连续点击,而需要等待到一定的情况才能进行下一次点击。各种情况都不太一样,需要一些经验进行良好的程序设计。但是,简单来讲,要做到等待的情况发生能立刻返回到程序,不能空等。
6. 减少其他UI对你自动化程序的影响,比如关闭Windows balloon,等等。一般来说是发现了有其他UI影响你的情况,就想一下workaround, 不会有什么大问题。
从我的经验上来看,一般UI自动化有问题都能归结于以上几点,而一旦你解决了以上几点的话,UI自动化就变成了一个熟练工的工作了,没什么挑战性。我本人的有些模块的UI自动化基本可以达到100%的通过率,而所有模块的自动化也能达到95%以上的通过率。不过我基本已经脱离UI自动化了,因为太没有技术含量了,不过我还是认为如果你刚刚进入测试的工作,或者从来没有接触过UI自动化,或者从来都没有做好过UI自动化的话,在这上边工作个2,3年会有一定的收获的。
控件类型 | 大分类 | 小分类 | 检查内容 | 结果判定 | |
TextBox | 数值型 | 边界值 | 输入[最小值-1] | 程序应提示错误 | |
输入[最小值] | OK | ||||
输入[最大值] | OK | ||||
输入[最大值+1] | 程序应提示错误 | ||||
位数 | 输入[最小位数-1] | 程序应提示错误 | |||
输入[最小位数] | OK | ||||
输入[最大位数] | OK | ||||
输入[最大位数+1] | 程序应提示错误 | ||||
允许输入小数位的控件,小数位的长度做以上同样测试 | 同上 | ||||
异常值、特殊值 | 输入[空白(NULL)]、空格或‘“~!@#$%^&*()_+-={}[]|\:;”’<>,./?;”等可能导致系统错误的字符 | 程序应提示错误 | |||
禁止直接输入特殊字符时,使用“粘贴”、“拷贝”功能尝试输入,并测试能否正常提交保存。 | 只能使用“粘贴”、“拷贝”方法输入的特殊字符应无法保存,并应给出相应提示 | ||||
word 中的特殊功能,通过剪贴板拷贝到输入框:分页符,分节符,类似公式的上下标等 | 程序应提示错误 | ||||
输入[负值] | 根据设计书要求判定 | ||||
输入设计书中明确指出禁止输入的数字 | 根据设计书要求判定 | ||||
输入[英文字母] | 程序应提示错误 | ||||
数值输入的长度:整型----32位 最大值 65535,最小值-65535;16位 最大值 32767,最小值-32767 | 根据设计书要求判定 | ||||
带符号的数值:带正号的正数,带负号的负数 | 根据设计书要求判定 | ||||
小数:小数点后的位数,小数的四舍五入问题,小数点前零舍去的情况,如 .12;多个小数点的情况;0值:0.0,0.,.0 | 根据设计书要求判定 | ||||
分数:如 2/3 | 根据设计书要求判定 | ||||
首位为零的数值:如01=1 | 根据设计书要求判定 | ||||
科学技术法是否支持:如 1.0E2 | 根据设计书要求判定 | ||||
指数是否支持 | 根据设计书要求判定 | ||||
全角数字和半角数字的情况 | 根据设计书要求判定 | ||||
数字与字母的混合:16进制数值,8进制数值 | 根据设计书要求判定 | ||||
货币型输入项:允许小数点后几位 | 根据设计书要求判定 | ||||
字符型 | 字符种类 | 输入[全角字符] | 根据设计书要求判定 | ||
输入[半角字符] | 根据设计书要求判定 | ||||
数字字符 | 根据设计书要求判定 | ||||
邮政编码输入项的输入限制,如只能输入半角数字字符或某几个指定字符 | 根据设计书要求判定 | ||||
电话号码和传真输入限制,如只能输入半角数字字符和半角括号“()”及半角减号“-”;电话或传真只能输入数字和减号。 | 根据设计书要求判定 | ||||
E-mail地址的格式检查,如输入字符串中必须包含“@”和半角“.”字符。 | 根据设计书要求判定 | ||||
年龄的输入限制检查,一般<=200即可。 | 根据设计书要求判定 | ||||
输入设计书中明确指出禁止输入的字符 | 程序应提示错误 | ||||
输入[空白(NULL)]或“~!@#$%^&*()_+-={}[]|\:;”’<>,./?;”等可能导致系统错误的字符 | 程序应提示错误 | ||||
密码输入项的特殊处理 | 登录验证时大、小写是否区分 | 根据设计书要求判定 | |||
登录只能输入半角字符 | 根据设计书要求判定 | ||||
是否允许输入特殊字符 | 根据设计书要求判定 | ||||
多行文本框输入 | 允许回车换行 | 根据设计书要求判定 | |||
保存后再显示能够保持输入时的格式 | 根据设计书要求判定 | ||||
仅输入回车换行,检查能否正确保存;若能,查看保存结果。若不能,查看是否有正确提示 | 根据设计书要求判定 | ||||
仅输入空格,检查能否正确保存;若能,查看保存结果。若不能,查看是否有正确提示 | 根据设计书要求判定 | ||||
长度检查 | 输入[最小字符数-1] | 程序应提示错误 | |||
输入[最小字符数] | OK | ||||
输入[最大字符数] | OK | ||||
输入[最小字符数+1] | 程序应提示错误 | ||||
文件名输入项的测试 | 输入不存在的文件名 | 程序应提示错误 | |||
输入文件名称超长(256个字符) | 程序应提示错误 | ||||
输入带路径的文件名和不带路径的文件名 | 根据设计书要求判定 | ||||
手工输入后缀名称 | 根据设计书要求判定 | ||||
对于文件大小的限制,需要采用边界值法测试系统的处理方式是否符合需求;考虑磁盘空间不足/满的情况 | 程序应提示错误 | ||||
文件名的非法字符集:/\:*?"<>| | 程序应提示错误 | ||||
不输入文件名和输入空格 | 程序应提示错误 | ||||
输入中间有空格的路径名和文件名 | 根据设计书要求判定 | ||||
输入合法字符,但影响系统判断文件名有效性的情况,如输入a;b-20003.5.8 | 根据设计书要求判定 | ||||
日期型 | 合法性检查 | 日输入[0日] | 程序应提示错误 | ||
日输入[1日] | OK | ||||
日输入[32日] | 程序应提示错误 | ||||
月输入[1、3、5、7、8、10、12月]、日输入[31日] | OK | ||||
月输入[4、6、9、11月]、日输入[30日] | OK | ||||
月输入[4、6、9、11月]、日输入[31日] | 程序应提示错误 | ||||
输入非闰年,月输入[2月]、日输入[28日] | OK | ||||
输入非闰年,月输入[2月]、日输入[29日] | 程序应提示错误 | ||||
(闰年)月输入[2月]、日输入[29日] | OK | ||||
(闰年)月输入[2月]、日输入[30日] | 程序应提示错误 | ||||
月输入[0月] | 程序应提示错误 | ||||
月输入[1月] | OK | ||||
月输入[12月] | OK | ||||
月输入[13月] | 程序应提示错误 | ||||
异常值、特殊值 | 输入[空白(NULL)]或“~!@#$%^&*()_+-={}[]|\:;”’<>,./?;”等可能导致系统错误的字符 | ||||
时间型 | 合法性检查 | 时输入[30时] | 允许输入30时制的项目“OK"; 不允许输入30时制的项目程序应提示错误 | ||
时输入[31时] | 程序应提示错误 | ||||
时输入[00时] | 程序应提示错误 | ||||
30时制是否允许存在1点~5点 | ?? | ||||
分输入[59分] | OK | ||||
分输入[60分] | 程序应提示错误 | ||||
分输入[00分] | OK | ||||
秒输入[59秒] | OK | ||||
秒输入[60秒] | 程序应提示错误 | ||||
秒输入[00秒] | OK | ||||
异常值、特殊值 | 输入[空白(NULL)]或“~!@#$%^&*()_+-={}[]|\:;”’<>,./?;”等可能导致系统错误的字符 | 程序应提示错误 | |||
特定值(如:只允许输入:"0","1"等) | 合法性检查 | 分别输入所有允许输入的特定值 | OK | ||
输入任意不属于特定值范围的字符 | 程序应提示错误 | ||||
异常值、特殊值 | 输入[空白(NULL)]或“~!@#$%^&*()_+-={}[]|\:;”’<>,./?;”等可能导致系统错误的字符 | 程序应提示错误 | |||
ChcecBox | 复选 | 连续选择 | 连续选择相邻的checkbox | OK | |
跳跃选择 | 跳跃选择不连续的checkbox | OK | |||
ComboBox | 单选 | 选择某一个列表项 | 被选中项目高亮或底色显示 | ||
复选 | 使用ctrl选择多个列表项 | 根据设计书要求判定 允许多选时,所有被选中项目高亮或底色显示; 不允许多选时,只有第一次被选中的项目高亮或底色显示,再点击其他项目应无反应; | |||
0, 11, 92, 23, 0, 60, 93, 11 Bitmap
| 鼠标操作 | 上键头 | 鼠标点击按件的“上箭头” | text框中数量自动+1 | |
下键头 | 鼠标点击按件的“下箭头” | text框中数量自动-1 | |||
键盘操作 | 上键头 | 按下键盘的“上箭头” | text框中数量自动+1 | ||
下键头 | 按下键盘的“下箭头” | text框中数量自动-1 | |||
箭头控制输入值 | 边界值 | 输入[最小值-1] | 程序应提示错误 | ||
输入[最小值] | OK | ||||
输入[最大值] | OK | ||||
输入[最大值+1] | 程序应提示错误 | ||||
text框输入值 | 同TextBox输入测试 |
最近还是发现有一些文章,个人对于自动化测试报有很大的怀疑态度,本人也对相关的文章给与了驳斥。我个人和公司对自动化测试都是报有很积极的态度的。这里我想再次的写一篇文章来阐述到底UI自动化测试可以做什么,作为一个优秀的UI自动化测试工程师应该具备有什么方面的技能,以及本人对UI自动化的一些经验和体会。
首先还是要强调一点,API和command line程序都是非常适合用自动化来进行测试的。我想这个观点,即使那些反对自动化测试的人也不应该否认吧?至少我觉得他们应该有这个意识。因此,对于他们反对自动化就集中在了UI自动化方面,我这里也完全站在UI自动化测试的角度来写这篇文章,后边就不再强调了。
再次套用朋友的一句话,"自动化测试听起来很神秘,学起来很简单,用起来很麻烦"。我想有过自动化测试经验的人,可能大多都有这个体会吧?前边的过程我就不提了,以后主要探讨为什么用起来会麻烦和怎样简单化自动化测试。总而言之,想搞好自动化测试,还是需要测试人员比较高的技术水平,尤其是编程能力和解决问题,分析问题的能力。
首先,我要谈谈自动化测试工具和编程语言的关系。作为一个优秀的自动化测试人员,他的最基本的能力就是编程水平了。所谓编程就是至少要精通一门高级语言,比如Java,C#等等,脚本语言不计算在内。请记住,不是熟悉,是精通。高级编程语言给我们提供很强的能力来实现一些东西。你所精通的语言能力越强,你在自动化测试可以做的事情就越多,越好。简单来讲,论程序的能力来排序是这样的,测试工具-〉脚本语言-〉高级语言(Java,C#)-〉 C/C++-〉C++/CLI。根据这个语言能力的排序,结合你自己的语言能力,你可以想想你到底具备多少自动化测试能力。我所强调的是,如果你想优秀,你至少要精通一门高级语言,这是必不可少的。如果很多人还只是用测试工具,脚本语言工作而抱怨自动化,我要强烈的建议他们好好去学习一下编程能力先了。他们的问题在于,由于编程能力的不足,使得自动化测试的很多问题没有能力和办法去解决。再谈一下自动化测试工具,无论哪种测试工具,无论他们设计的多么强大,从编程语言来讲,他们最多能够达到脚本语言的能力。也就是说,如果你完全用测试工具来进行自动化的开发,很多问题你还是无法解决的。因此,我推荐的自动化开发方法是高级语言结合测试工具。我的自动化测试逻辑是,用测试工具只是完成UI操作,其他部分完全用高级语言来实现。我们不能否认高级语言所具有的能力,他们创造出了世界上这么多丰富多彩,这么多优秀的软件,难道开发测试程序会有问题吗?因此,我们的焦点就落在了测试工具的UI操作部分。
第二,关于测试工具。开发语言重要,选择一个合适的测试工具也同样的重要。一个灵活,强大的测试工具可以使你的自动化开发起到事半功倍的作用。结合不同的项目,不同的语言,你可能会有不同的选择。不过,这里我想解释的是,具有了高级语言的开发能力之后,我们期望测试工具来为我们做什么。我前边也说过了,我们所要求自动化测试工具所做的就是UI的操作。这里边比较重要的是三个方面,一是找到UI对象,二是操作UI对象,三是同步。如果一个工具能够让你找到所有的UI对象,并且能成功操作这些对象,就完全满足我们的自动化开发需要了。如果,工具能够提供同步的功能,就使你能够如虎添翼,不然的话要自己去实现,会麻烦不少。到了这里,你已经具有了所有UI的操作能力(测试工具提供),并且具有了高级语言的实现能力(高级语言提供),你才有了基本的能力去做一个优秀的自动化开发。没有这些能力的人,我严重怀疑能否做出好的自动化测试。
第三,怎样自动化。我的自动化的原则是,尽量少的进行UI的操作,除非是你本身要测试的UI。道理很简单,UI操作由于可能受各种问题的干扰,很容易失败。通过非UI的方法去实现是更加可靠和快速的。这也是我为什么要强调对于高级语言的精通,具有高级语言的开发能力,你就能过把大量的任务从UI操作转向了程序操作,使得你的自动化程序的可靠性大大的增强。这里还需要强调的一点能力就是系统应用的能力,比如Windows使用的能力。Windows的很多的操作是有相关的命令来实现的,不一定非得通过大家熟悉的UI。记住这个原则:除非是你要测试的UI,否则尽可能的通过高级语言来实现。我想大家对于高级语言来实现的工作应该还是有信心吧?因此,下边我要谈的内容就完全的与你要测试的界面相关了。
第四,怎样进行UI测试。首先要尽量的减少UI操作,除非是你必须要测试的操作。比如简洁快速的启动你要测试的界面,用快捷键代替鼠标操作等等。总而言之,理想状态下我们进行的每一次UI操作,都是我们需要测试的,其他操作尽量避免,不能避免用最可靠的方式去实现。那么我们现在的焦点就变成了,怎样来处理我们真正要测试的UI了。UI测试的开发基本上就三个问题:发现对象,操作对象和同步。简单解释一下同步,同步就是有一个机制告诉你何时可以执行一个 UI操作。很多人是用sleep的方式,等待一定的时间去执行下一个操作,这是我非常反对的。我的原则是,尽量少用sleep,就算要用每次最多不要超过一秒。滥用sleep会严重影响测试程序的性能(具体的UI自动化过程,大家可以参考我的其他文章)。
第五,UI测试错误/异常的解决和Debug。通过以上的解释,我们只是在自己需要测试的UI操作才进行UI操作,否则通过高级语言或者系统命令来实现。是不是我们的UI自动化就完美了呢?绝对不是,这只是一个基础,还远远没有达到完美。我们在自动化开发和应用的过程中,大部分的时间其实是花费在了异常/错误处理和Debug上面。这跟真正的程序开发非常的类似,你如果去看代码的话,大量的是在进行返回值得检验和异常的处理。如果我们的程序在运行过程中出了问题怎么办,或者如果没有出现我们期望的结果怎么办?一般来说有三种问题,第一是产品的问题,我们可以报bug了,第二是你测试程序的bug,你需要fix。第三是其他的问题,比如测试工具,甚至高级语言本身的问题,你需要workaround。总而言之,优秀的测试程序最终的目的是,一旦程序的运行发现了问题,就是产品的问题,就是可以报bug的。能够达到这种境界才能算自动化测试的完美,才能算是一个真正优秀的测试人员。(当然了,正如软件产品不可能没有bug,你的测试程序也不可能完全没有bug。但是,由于软件产品是有大量的用户来使用,而你的测试程序只是很小范围内来使用,使得你消除影响测试过程的bug成为完全可能)
综上所述,一个优秀的自动化测试工程师必须要具备高级语言的开发能力,自动化工具的灵活应用能力,系统命令和使用的熟练能力等这些基本功,还更要具备优秀的Debug,Fixbug的能力,和保持程序稳定性能力。换句话讲,一个优秀的自动化测试工程师必定也是一个优秀的软件开发工程师。
最后谈一下我为什么要转向C++/CLI?从上边的排序大家可以看到,C++/CLI是目前Windows平台最强大的编程语言。在我的自动化开发的过程中,我需要高级语言和系统命令都不能完成的功能。如果没有C++/CLI我就必须要通过UI来实现,从而降低我程序的可靠性。而有了C++/CLI的功能,我就可以绕过UI操作了。总之,能够绕过UI操作的能力也体现出一个自动化测试人员的能力。从这个角度讲,测试人员有很多东西要学的。最后说一下,我自动化工作的要求是100%可靠,我还不能完全满足,因为使用我程序的人是那些手工测试的人,他们的使用环境的变化有可能引起一些问题的产生,基本上还不是我程序的问题,而是测试工具,或者其他模块的问题,我需要想办法去workaround。不过,随着一定时间问题的积累和解决,如果环境不变,应该可以达到100%可靠。(可是环境的变化是不会停止的,因此实际上很难达到永久的可靠,不过一段时间的可靠还是应该可以达到的,或者说我们的测试开发必须有这样一个目标,就如同软件开发的目标一样)
本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/