目前的自动化测试工具使用了 RobotFramework,把自己使用的方式大致分享一下。具体来说就是,只用 RF 作为一个执行器,其它底层 API、业务 API 和测试用例全部用 python 来实现。
本文章纯属个人见解,水平也有一定限制,各位看官可以发表看法,但是勿喷。
最近把 RF3.2 的英文原手册看得差不多了,也对这个工具一定的了解。从 RF 本身的发展来看,除了向 Python3 靠近、增加 Task、增加 BDD 之外,有几个地方是为了增强执行原生 python 代码的能力。这一点与我最初接触 RF 的感触是相符合的,就是普通 API 操作尚可,灵活操作和深入细致操作的能力欠缺。
=======================================================================================
2019 年之前我一直用的是自己用 python 写的测试框架,包括测试执行工具,基本够用。RF 的大名早就听过,但是没用过。19 年 4 月-5 月短暂在某本地化外企待过,接触了 RF 和 REST 测试。后来因为多头管理及一些其它因素离职了,但在这两个月中,也是把该公司 (后简称 A 公司) 的几套自动化测试都摸清了。虽然在这家公司的经历并不是重点,但是我还是觉得有必要把它的自动化测试情况大致介绍一下。
A 公司做的是边缘网络设备,跟华为有类似产品。主要做接口测试,协议包括 REST、NETCONF、SNMP 当然还有 CLI,自动化测试工具是用 Python + RobotFramework。A 公司有三套东西,第一套 X 是总部的 Python REST 库,第二套 Y 是中欧某国分部的 RF 库 (API、业务 API 和测试用例都用 Robot 来实现),第三套 Z 是中国分部的 RF 用例库 +Python 库。X 就是一个纯粹的 python 库,按照 RF 的规则来实现的,提供 JSON 合成/解析、REST 消息打包和收发等功能,非常基础。Y 则 98% 是 Robot 代码,调用 X 库,包装一层基础关键字,在上面再套一层业务基础关键字,接着网上套混合关键字、性能关键字、验收业务关键字,最后是基础用例、上层用例、等等,总共叠了八层。Z 则是因为觉得 Y 不好,又做的一套,具体点就是二次用 python 包装 X,形成了协议接口 + 基础业务接口的 python RF 库,上面则是用 Robot 代码写的测试用例了。
总体感受到的痛点如下:
1. 参数定义和传递累赘
每个特性负责人写 robot 用例的时候,都一定会出现独特的需求,感觉每个特性的 suite 下面总要带个额外的参数配置文件和一组自定义关键字文件。
参数传递的时候,有些还需要单独指定哪个需要传递给下面的子 suite。当时第一次直接使用 RF,对于哪些参数要指定传递模糊不清,即使现在我也觉得模糊不清。
2. 代码阅读难
这个点是相对的,如果只是简单的用别人写好的关键字来写用例和执行用例,其它的都不用关心和负责,那对于没有代码基础的人来说,会没有什么感觉。
但是如果是一个需要负责解析业务流程,学习新业务特性的人来说,花费的时间就要多很多了。Robot 语言本来就很松散,大小写和下划线不敏感,再加上一些参数的特殊文本表达方式,加上那八层架构,绕来绕去把我搞得晕头转向。当时的 Y 架构,我花了大半个月的时间才摸清楚。设计说明?没有;关键字说明?没有;代码注释?没有;skype 或邮件求教?对不起,上班时间不一样,也懒得义务回答。一般情况下,我觉得除了最后那个 skype 交流的问题外,其它的问题大家都会有的,别说自己的公司是大公司如何如何规范,在国内的工作量和进度压力面前,规范不值一提。
3. Robot 代码堆砌成一堆垃圾
基于前面的第二点,在我看来,Y 套的 Robot 代码,已经形成了一堆屎山。我好歹搞自动化测试也陆陆续续有十年的经验了,看那堆东西都有点吃力,那些三四年或四五年经验的年轻人来搞?
松散关键字和用例的堆叠,每个人的水平和习惯都不一样,写出来的内容就五花八门,慢慢地形成了一堆垃圾。内容各式各样,看吧又不容易看懂,动又不敢随便动,有些关键字接口呢扩展性很差,不得不重新写一个,像我这样有代码洁癖的人看起来都想吐又无可奈何。
Z 套就比 Y 套好多了,起码要是垃圾的话也是分成了两堆,看起来没那么难受。先不评价 python RF 库那边的情况,Robot 用例这边,还是充斥着各种各样的参数和补充关键字,原因就是 python 库的定义的关键字不够用。
4. Robot 语法表达能力不足
这个其实是一个重要的问题,代码表达能力不足,而且表达的方式也很松散。这个松散可以是优点也可以是缺点,大小写不敏感,空格不敏感,这样表达也可以,那样写也没错。但是这种基于文本的松散,可能对于阅读者的理解会带来一些困扰,特别是在参数的表达方面,由于受到文本处理的限制,所以就搞了好多特殊类型参数的文本表达方式。
至于代码表达能力不足,这个就显而易见了,从 RF 加强原生 python 代码执行能力这点就可以看出来了。在测试用例中那些灵活度很大或者比较深入细节操作的地方,RF 是有欠缺的。但是就我个人而言,这些改进仍然是不足的,当然不是说它不好。也许这些表达能力不足的地方也就是占了整个测试的 10% 不到,也还可以嵌入 Python 脚本来实现,但是这样我就感觉复杂化了。参数无法表达可以用 python 代替,代码逻辑无法表达的部分也可以 python 代替,那我干嘛不直接用 python?统一化、干净、不混乱。
从目前我用的方式来看,普通用例的 python 代码量与 Robot 可以持平,灵活场景或细节场景的代码量 python 可以少得多,唯一的不同就是需要懂 python。但是如果从真实的情况来评估的话,学习一个 python 跟学习一个 robot 的成本是一样的,因为用 python 来写用例的话都是基础语法,没什么难的,又不是写底层框架。再说,学完基础 python,还能进阶提升,学学爬虫搞搞工具开发,学完 robot 语法除了写个测试用例,还能干什么?
5. 测试报告太大难受
如果像 Y 套那样,堆叠了多层关键字,跟踪业务流程的时候,我点测试日志页面上的加号都点得手痛。
测试日志上面那一层层花花绿绿的太多,别人我不知道,反正我是被晃得眼花缭乱。
6. 可能的多线程
这个是痛点之外的东西,顺便提一下。RF 文档里面说明了,Robot 无法多线程,想搞多线程必须用 Python/Java 库来实现,而且在多线程中的 log 打印是延后的。
我现在也没有多线程的需求,但是 log 方面我是自定义修改的,所以即使有多线程需求,也不会有问题。
=======================================================================================
只干了两个月就离职了,反正感受到的东西就是这些,也不怎么全面。在新公司 (简称 B 公司) 也是用 Python + RobotFramework,经过前面的一些总结,所以我现在使用 RF 的方式就是简单化、好用、够用就行,把 RF 仅仅当成一个库和执行器。当然这跟我现在的工作现状有关系,公司就七八个人,我一个人负责全部的测试设计、自动化框架、自动化脚本、版本执行等等,按老板的意思,你干好测试就行了,不管你怎么搞。
我现在的项目自动化的内容包含了 Serial、SSH 和 WEB,除了 WEB 页面使用了 PO,其它的都是面向过程的。大概使用 RF 的特点有如下几个:
1. 独立配置参数
一个产品只有一个参数配置文件,并不多,所有二十个特性加一起也就六十多个,而且每次测试需要修改的参数只在六七个左右,大多是产品型号、软件版本、产品 IP 等这些。
参数配置文件用一个 ini 文件管理,放在 robot 测试套路径中,每次测试执行前就会自动加载。
这个参数与 RF 的命令行变量并不冲突,如果觉得需要,可以增加 robot 命令行变量,我因为不需要所有没用。
2. 额外的日志系统
前面说到了,RF 默认的测试报告里面的 log 过多,而且如果关键字存在多层叠加的话,看 log 很累人。
因为我的测试用例其实是关键字,而测试用例调用的 API 都是 python 代码,所以在测试报告上面,基本上就只会有一层用例关键字,而用例关键字下面那些 API 是否需要打印则是由 API 的装饰器来控制,总体不会太多;所有的打印,都同时会打印到另外的本地日志文件中,用 TimedRotatingFileHandler 来处理,比 report 网页中的详细,它包括了所有级别的打印。
3. 用例是函数形式的关键字
除了 WEB 页面是面向对象之外,其它的 API 都是面向过程的函数。(在大量资源申请/释放的业务中,千万不要对节点资源使用面向对象方式,要不然会很慢;A 公司的 REST 采用 OOP 来定义每个层级节点,包括资源和配置,结果在性能测试的时候不得不重新写一套面向过程的关键字。)
使用 Pyerial、SSHLibrary、SeleniumLibrary,虽然 SSHLibrary 和 SeleniumLibrary 已经是标准的 RF 库了,但是我把它进行了整合包装,既保留了原生的关键字,又添加了一套符合自己习惯的关键字。
业务 API 函数是关键字,我称为 Action 关键字,当然 Fixture 也是关键字。
最上层的相互函数独立的测试用例关键字,每个测试用例是一个函数,可带参数。
最终,在 python 库的 init.py 中,定义库同名的类,将需要导出的关键字函数绑定到该类上。我绑定了基础协议 SSH/Selenium 的关键字、业务 Action 关键字、测试用例关键字,原生的 SSHLibrary 和 SeleniumLibrary 的关键字也绑定了。实际上除了测试用例关键字以外,其它都还没有用到。
4. robot 测试套文件
文件里面只包含导入测试库、设置 Setup/Teardown 和测试用例。一个测试用例只包含一个名称和一个测试用例关键字,携带可能的测试用例参数。
这样的话,robot 有用的功能又没有丢失,比如测试标签,而且另外复杂性的东西都交给了更灵活的 python 来实现。
5. 测试用例函数如何识别以及参数如何恢复
测试用例用简单的装饰器来包裹属性,在 python 库的 init.py 中读取识别并绑定。
参数恢复的话,是在具体的测试用例代码前设置本用例触碰的参数,在测试用例的 Teardown 中根据设置的参数来恢复产品设置。
A 公司的 Z 套 robot 脚本没有参数恢复这个概念,只有一个全局的资源池,要用的时候就去资源池申请,用完了就释放。可问题是下次重跑的时候,资源池根本不知道资源在产品中是不是真的都没有使用,还需要人工去检查一番或者用个专门的脚本去释放。Y 套 robot 脚本就更加离谱了,根本没有全局管理这个概念。
=======================================================================================
以上就是我的 RF 框架的大致使用方式,总体看起来就是 ‘懒’,我只想用最少的改变来完成一个够用的工具来工作。能力有限,有些想法和概念,也无法用一些工程化的思想来表述,也有不少东西我不懂所以讲不出来。反正在我这里,很多框架或模块都是自己写的,够自己用就行,在具体的产品实施中,感觉用得还不错,没有碰到什么特别棘手的问题。
这种层次的测试接口和测试用例,就是三层:基础协议 API、业务 API、测试用例函数,比较扁平化,普通测试用例写起来不含糊,复杂用例实现起来也不痛苦,简简单单。
至于底层在实现上,肯定会用到一些装饰器之类的技巧,至少初级别的 python 工程师是看不懂的东西。有个好处,保证自己不容易被优化,免得教会徒弟饿死师傅。都三十多了,碰到新冠肺炎了,谁还敢随便丢掉自己的饭碗啊!这个话题就不多说了,社会实践感悟而已。
以上内容属个人实践和见解,仅供参考~