这几天作者接手了一个 ui 自动化项目,原来的负责人离职了。
我就临危受命交接了过来。本来应该交接给另一个女孩,结果她看了俩眼后果断拒绝接手。
我为了不让 ui 自动化这个端直接废掉,就干脆一咬牙,答应接手。等到我们实际用了半小时交接后,我做了个决定。我放弃了,然后关机。。。
这之后。我用了大概 7 天时间,重做了整个这个移动端的 ui 自动化 包括我们 app 的全量用例。代码行直逼 1w+。。。
以下是我这 7 天工作内容:
第一天:找一个合适的服务器,要性能极好,抗燥,长时间不关机。干净的环境 (没找到,手动清理了一顿)。找一个可以长期运行脚本的手机,并且不太卡。然后作出设计,我要弄个好交接,好维护,好理解,好操作的 ui 自动化测试平台。
第二天:搭建 appium+pythoon 环境,研究在 windows(第一天只找到一台符合条件的 windows)上如何能自动每次中断/重 lanuch appium 的命令。并使得 appium 脚本可以成功运行在真机上,然后在配置 django+python 的环境。跑起一个 django 服务,能成功打开第一个空白页面为止。
第三天:搭建这个 django 平台,一个大页面就好。要有菜单栏,工具栏,用例列表,监控设置,用例运行测试报告 等等。主要技术:django+python+appium+reuqest+sql/rom+unittest+linuxshell+htmltestrunner+html/css+js/jquery+bootstrap3+..... 菜单栏开发:进入后台,用例的增删改查和关联实际脚本.py ,执行全部用例 + 全部用例结果统计 ,执行核心用例 + 核心用例结果统计。
第四天:搭建好平台后,测试启动第一个脚本,运行成功。测试监控轮询子线程执行成功。开发小工具(正所谓磨刀不误砍柴工):如重启 adb 服务,杀死 appium,一键登陆某身份账号 等。这些小工具在我之后写具体用例脚本的时候会很常用。(比如:执行的时候手机键盘会被 appium 屏蔽,我要是手动要登陆某个账号查看/调试一些特定数据的时候,还需要每次去设置里面修改输入法,用这个点一下就自动登陆那几个账号了(因 app 的用户身份不同,所以准备了三个账号))
第五天:开始写第一个模块的用例,很多,很繁琐。也思考了很多。所以大笔时间用来写一些绝对可靠的 公用函数了。如:屏幕上滑/下滑 正好一个页面,
确保某身份制定账号的确保登陆函数,退出函数,无限返回到首页的函数,快速清空输入框函数,快速 adb 输入文字函数,自动定位函数 (针对 id/class 不唯一,只能通过 text 定位的元素),自动断言元素应该存在或不应该存在函数,最符合本 app 和该手机风格性能的智能等待,等等等等呢。
这些函数可以确保我少写代码的同时,还能确保用例的稳定性。
第六天:写用例,优化公共函数
第七天:写用例。
在这个过程中,我说我思考了很多事情,关于 ui 自动化的。到底都要注意一些什么呢?或者说相对于我第一次会写 ui 自动化脚本的时候,我现在会多思考哪些事呢?毕竟自己也是平时给人培训过自动化的讲师。要是一出手就水的一批,那就太没排面了。
到底要不要采取 page-object 模式:这个设计模式,是主要用来后续维护方便的,但是如果功力不够,为了使用而使用,那么就会造成,我在用例逻辑脚本中完全看不懂这些代码是干什么的,我还需要打开元素维护的脚本,一个一个去搜,这中间把你的思绪撕扯到零碎,理论上来说,元素定位发生变更后,我们只需要去维护元素定位模块。逻辑发生变更后,我们只需要维护逻辑脚本。看起来省了很多时间。但是实际情况更多是同时变更,我们要同时去修改元素定位,和元素操作逻辑顺序等。这样你就需要维护俩个模块的脚本,你的思维很难去整合在一起,非常费心。
数据分离/驱动:千万不要为了数据分离就去分离数据。本来你的数据都是很死的,比如用户名,你整个脚本中也就使用几次,那么你的这个用户名,你还要单独去弄个 csv/excel/sql 去存放么?然后每次用的时候从这里调取?这样无疑增加了执行时间,也增大了脚本出错的概率。最主要的是,以后交接或者自己维护的时候,看到脚本这里,心想这里写的是什么东西,具体是哪个账号呢?还要赶紧去打开 excel 表查了半天,哦,原来这里断言的字符串是这个啊。。。。我的结论就是,需要大量数据验证的/重复使用多次的用例具体字符串,才可以去做数据分离。还有不要验证太多的写死的数据,要学会动态获取并验证。比如:我登陆这个用户叫王大锤,然后我把王大锤写在 csv 文件里。然后我要去测试在另一个页面断言,这个用户名能不能显示正确。每次都去调用这个文件。如果有一天这个账号换了呢?你还要改这个王大锤三个字。所以更好的办法是动态获取和验证,就是我在登陆的时候获取这个账号的用户名,然后存在缓存(unittest 可以用类名.变量名来记录数据),然后之后用例去缓存取这个用户名做断言。不要小看这一个字符串。当你的用例几十几百处这种断言的时候,不动态获取数据那后续维护你会想死的。最怕过些日子你自己都不知道这个字符串是啥意思了(比如在 csv 文件看到一行:ABcdqwije12 ,你也不知道这是啥,但现在账号换了,我要把新账号的数据更新到这 csv 里。但是这行是什么来着?昵称?id?完全不记得。。。还是去研究代码脚本推断出来吧。)跟前面第 1 条说的类似,大道至简,凡事都有双面性,找到一条最适合的适用场景来使用才是王道。不要一味的为了炫技加入太多的各种设计 思路 框架。
3.用例的分段:可能大家都会苦恼这个,流程就是这一大堆步骤,我放在一个用例也可以,分成 10 个小用例也行。那到底怎么分才是最好的呢?
我在这里给出建议:按照你手工写用例的基本思想,每条用例只注重一个测试点,不然包含的功能太多,用例失败你都不知道后续测试点是否成功。每条小用例千万别包含太多代码,不然一个错,后面都不执行了。而且分的多,你领导看着也好,知道你写了好几百条用例的辛苦。
4.用例的断言:unittest 框架中,若是你用例如 test_001 断言失败了,那么这条方法里后面的语句可就都不执行了。后面大多数人会写成返回页面/还原数据 等操作,来给下一条用例创造环境。但是如果这条断言失败,那么后面不执行,下一条用例没有一个正确的环境,所以也会失败,这就是误报失败了。到时候你看着密密麻麻的爆红结果,脑子也疼吧,虽然可能仅仅是第一条报错/失败 的用例的问题,后面用例其实都是好的。。。所以这种还原操作,尽量放在下一条用例中,以便杜绝前一条失败带来的风险,当然不是绝对。
5.unittest 框架中的 setup 一定要用好。也就是说,根据高内聚,低耦合 原则。用例和用例之间一定不要有太多的 联系。我喜欢根据不同模块 分成大用例,大用例内 不同小功能 分成小用例,小用例直接可以有关联。也可以没有。大用例之间 必须毫无关联。确保我执行顺序混乱都可互不影响。所以在大用例执行之前,最好干掉 appium,然后重新启动 appium 服务。
6.断言:这是一个非常头疼的事。断言详细了。你后续维护会累死,断言太简单了。那脚本失去了价值。所以断言我觉得一定要是非常非常智能的。各种 ai 测试,大数据测试,智能匹配 模糊匹配 ,图片相似度 等算法,都可以在断言上放光发热。我这边运用了许多黑科技,包括自动维护,智能断言等,当然名字也不贴切。您要是有兴趣,欢迎找我讨论或关注我博客,可以点击下方菜单:联系作者。
7.代码注释:我别的不说了。我所有用例代码,每一行,全都后面写着中文注释,点了什么,断言什么。必须全部写清楚。不然你怎么之后交接给别人,怎么应对频繁的 ui 变化维护脚本。这个习惯可是个好习惯。不要以为这个注释太简单,没什么用。定位某个元素并点击的代码多简单,谁会看不懂呢?当然单个拿出来都能看懂,但是具体点了什么 ,谁知道?一大堆放在一起,这是啥?写了汉字注释后,针对后续复杂的变更和逻辑,你大脑也可以快速思考并作出调整。而不至于增加无谓的理解成本。
8.项目结构:任何新建一个包/层级,都是要经过深思熟虑的,千万不要图爽随便去弄,看着层级很多就牛逼么?东一个配置文件,西一个脚本的,南一个封装,北一个包的。 仔细一看,到处都发现其实不分这么多包 和层级,可以更好的理解和维护。那这种复杂到没法看的项目结构叫什么?我们称之为:屎山~ 没人敢随便改什么,谁知道会出什么问题?
9.支撑服务:你一个自动化 ui 项目,目的就是为了节省时间,如果支撑服务过多,那么风险就会增大,稳定性就会降低。也就更加需要我们花费时间在大量的支撑服务上。(比如就一个轮询脚本,每小时执行一次,你至于要本地搭建一套 jeknins 节点,然后去主 jenkins 站上次次下载文件,然后链接,然后设置项目等一大堆操作,最终只为了在上面可以定时发送命令过来执行脚本。)我不建议这种做法,任何做法都需要有理由,有利也有弊,都是需要进行讨论和分析的,而不是单纯的掺杂越多就越好。
10.一个优秀的自动化项目,一定要是好交接给其他人,可以容易的让多人协作开发的。所以,你要有良好的易学性,易理解性,易分析型,易测试性,可移植性等等等等,具体的可以参考 iso9126 质量体系,我的文章中也有专门讲解过这个。不能只会读,自己开发的时候也要用上才行啊。
好了,暂时就想到这 10 点,欢迎小伙伴们补充和讨论哦~
最后,转载请注明出处。欢迎分享~