自动化工具 聊一聊低代码自动化测试平台的设计思路

Chras · 2022年04月19日 · 最后由 thinker543 回复于 2022年06月13日 · 2869 次阅读

自 18 年起,一直在思考如何把自动化测试框架转化为测试平台,让自动化测试告别代码。中间搁置两年,20 年底于上家单位尝试在做,最后效果还算不错,但是很多设计在使用中发现仍不完善,因此后来下定决心自己一个人重做一版。

通常来说,设计自动化测试框架时模块大概可以拆分为:测试对象(API/UI)、测试用例、测试数据、测试环境、测试计划、测试日志、测试报告以及一些辅助功能如公共参数、测试文件等。那么我们将其平台化后,也可以参考这个思路来做,但是有些功能需要做适当的变更:

  1. 首先是测试用例和测试数据,常规的测试框架遵循 POM 设计模式,用例代码和数据是分离的,从而方便管理。平台化后,理论上也该如此,最早我也是这么做的,采用用例模板和用例数据分离的模式,但最终发现写用例时极为不便,而且也有各种各样的问题。其实平台化后,没有必要再做用例和数据分离,框架做分离是为了数据管理更加直观,不受代码影响,更加容易维护,但是平台化后,代码几乎为 0,用例采用配置化来写,因此用例步骤与数据结合在一起维护反而更加直观。

  2. 其次,平台化后虽然不用写代码,但也会带来很多局限性,一些特殊的处理不易实现。比如说参数加密,框架只需要写一个公共加密函数,用例步骤中调用。平台化后,要想支持这一点,那么就应该有函数管理功能,支持统一维护函数,并在用例调用。函数管理应该有常用的内置函数,同时也要支持自定义。

  3. 还有就是 UI 自动化的实现,我们可以将驱动代码翻译成关键字,其实 UI 测试脚本每一步无非就是包含三个内容:操作动作、页面元素、输入数据。平台化,可以这些步骤封装成一个个操作控件,并赋予其言简意赅的关键字,同时页面元素也可以统一在一个地方维护,方便管理。写用例时通过选择关键字,带出其所需的元素和数据,就能完成一步步的 UI 测试。此外,操作控件也应该支持自定义,毕竟总归有一些特殊使用。

  4. 最后就是测试执行,为了避免执行资源、网络限制等问题,分布式执行、可视化调试、跨环境执行很重要。这样就需要把测试执行独立在平台之外,封装成一个单独的项目,我称之为测试引擎。测试引擎既可以部署在服务器上,也可以在办公电脑上启动,与平台的通信通过 http 接口,这样就可以解决诸多问题,后面我会详细介绍。

接下来,我按照自己已实现的平台来详细介绍一些关键的功能点设计:

一、测试对象管理

自动化测试包括了 API 和 UI 以及 APP,其中 UI 和 APP 的测试对象都是页面元素,只不过一个是 Web 页面元素,一个是 Activity 页面元素。所以测试对象管理,可以分为接口管理和元素管理。无论哪种管理,一定要支持模块化管理,这样才能逻辑清晰和维护方便。因此我们可以采用常见的左树右表来进行管理,接口管理列表如图所示(元素同理):
接口列表

接口管理相对于元素管理较为复杂,元素管理只需要维护其名称、定位方式即可。但是接口需要维护的数据很多,这里我们可以参考 postman 的接口请求,除了接口基本信息外,可以将其请求信息按照 TAB 展示,如图所示:
接口详情

二、测试用例管理

测试用例的管理和对象管理一样,也应该按照模块化管理。其次,API 用例和 UI 用例的管理和使用是一样的,没有必要分开管理,只是写用例的模板不一样而已。但用例编写是平台化的重中之重,需要注意的地方有很多 (用例细节 DEMO 图片太多,我就不贴了):

  1. 测试数据与环境的解耦 我认为一个合格的测试用例不应该和环境耦合,这也是我没有再做测试用例和测试数据分离的主要原因。一个合格的测试用例应该是数据可回收的,即便是那种复杂流程的用例,也应该是一个用例集合的数据是可回收的。因此测试用例不会关联测试环境,环境只是作为标签告诉使用者,这个测试用例适用于哪些环境,方便执行时选择环境。
  2. 测试对象如何关联环境 测试用例不关联环境后,那么 API 测试的请求域名和 UI 测试打开的页面域名如何一个个环境关联上呢。在我的设计中通过两种方式即可完美覆盖,一是路由匹配,通常来说在多个微服务域名的环境中,每个接口属于那个微服务通常都会以接口地址的首位路由来识别。其次,如果这种方式不适用,那么我们可以对每个接口设置域名标识,每个环境也维护相关标识的域名,强关联后,无论如何也不会出错。
  3. 断言和提取参数如何做 ①API 测试是很简单的,参考 jmeter 即可。正常接口返回都是 json 数据,那么只需要通过 jsonpath 表达式即可提取响应值,并对其做断言和参数提取即可。如何是其他响应数据,也可以通过使用正则表达式进行提取。 ②UI 测试也不困难,UI 断言和提取的对象无外乎就是元素是否存在、元素文本、元素坐标等等相关信息。因此我们可以将断言和关联作为操作步骤来维护,写用例时直接使用即可,道理和普通操作动作一样。
  4. 动态变量的提取和使用 常见的动态变量有随机函数、关联变量、公共参数,我们可以通过占位符方式来标识使用,比如说{{@func}}表示函数,{{$name}}表示公参, {{name}}表示关联参数,并且可以混合使用。比如说提取的关联参数需要进一步处理,那么我们可以写个自定义函数,并将关联参数作为入参,最终得到结果,如{{@func({{name}})}}。这些占位符在用例执行前会被测试引擎里渲染成实际的值,并最终使用。此外,测试用例的提取参数应该有个作用域,不应该只是作用于当前用例,遇到一些流程用例可能更希望用于一整个测试流程,因此可以引入测试集合的概念,一个测试集合内的用例是串行的,从上而下执行,提取的参数也会在整个测试集合内被使用。
  5. 一些附加的逻辑控件 接口测试多少需要一些逻辑控制,比如说接口之间公用 session、接口请求成功后设置静默时间等。此外,为了避免仍有一些无法适用的测试场景,可以参考 jmeter 设置 beanshell 等。但这多少会带来管理困难,所以我也还没做。

当然还有很多其他小细节,这个一一叙述过于占用篇幅,因此就不再继续赘述了。

三、测试集合和测试计划
测试集合这一层的作用有两点,一是如二中所说,为了用例串行和动态变量作用域的设计,二是测试集合可以理解为一个模块,将用例按照模块来执行,能更好的分析结果。
测试计划就是最终产出测试报告的用例集。执行支持定时、支持手动、支持外部调用 (集成到 CI/CD)。测试计划可以按照测试集合的维度来并发执行,如此就可以提升测试效率。
简而言之,用例执行时需要考虑串行和并行,因而设计成两个层级。

四、测试报告
平台化后的测试报告其实与测试框架的报告差不多,都是按照模块化出结果,并且展示用例执行过程中的详细日志,UI 用例还要显示截图。报告页面无须多花里胡哨,能清晰看到失败和错误,方便分析即可,如图所示:
报告详情

五、测试引擎
测试引擎是测试平台的核心,负责测试平台的执行。一个平台可以注册多个引擎,每个引擎由独立的 code 和秘钥,当引擎被启动时,向平台每分钟发送心跳,平台接收后则默认引擎可用状态为在线,超过三分钟没有收到心跳监控,设置为离线不可用。其次引擎有获取任务接口,拿到属于自己的执行任务。也有任务终止接口,避免一些用例卡死引擎,引擎拥有者可以自己选择关闭引擎当前执行任务。

引擎执行的原理其实很简单,使用 python 的 unittest 作为核心来管理用例执行,并对其做一些二开。其次当用例开始执行时,先会对用例进行渲染,将动态变量渲染成最终值,完成渲染后才会进行最终的执行。最终执行的驱动,接口用例使用 request、UI 用例使用 selenium。

简而言之,引擎其实就是在原有的测试框架上包一层平台通信,使用很简单。附上我做的测试引擎代码:测试引擎 GIT 地址

主要功能设计就是这些,还有些细枝末节下次补充。小伙伴们有兴趣可以试试看我发布的 DEMO,因为测试执行会发邮件的,避免我的邮箱爆炸,所以先不提供测试账户,可以手机号注册用户,账号仅作试用体验,不作他用。平台 DEMO 地址

共收到 22 条回复 时间 点赞

又是一个轮子😓

赞一个,设计的比较好。缺前置处理,后置处理。

nico 回复

我在做这个平台设计的时候还不知道市面上有哪些测试平台,全都是自己一点点思考出来的。后来也有发现一些接口测试平台,但还没有遇到把 API 和 UI 融合在一起的,可能是我平时关注的少。不知道您有没有试用过,相比其他接口平台,自我觉得有不足但也有我的创新和特点,我的理念是简洁易用,所以功能都设计的比较简单。或许与其他平台有相似之处,但我是不认同您的重复造轮子的说法。

sillybug 回复

谢谢。确实还没做前后置处理,其实我也有考虑过。做个类似 jmeter 那样的 beanshell 其实不难,关键这样就与低代码理念有点相悖。前置处理如果是请求参数相关的处理是可以用自定义函数来覆盖大部分场景,后置处理如果仅用于提取参数的话其实大部分情况也能支持。但其实确实有很多其他相关的使用场景,因为还没有具体遇到,所以目前还没想出来有什么好的替代设计方案,后续会继续收集优化。最后再次谢谢您的建议。

但凡稍微复杂的场景,用低代码平台就是痛苦

干饭狂人 回复

肯定有利有弊的。写的时候麻烦,但是后期用例管理和维护总归更清晰方便。之所以不想再用框架也是因为各种弊端,看实际取舍了。

LuckyFrame 就是接口 +ui 混合的。这个是看个人,融合起来在实际情况中使用场景有限且不便于管理。
你这个想法挺好,加油

兔子 回复

谢谢鼓励。其实混合只是多提供一个可用性,管理方面其实无外乎就是放在两个菜单还是一个菜单,这些我还在探索更有效的办法。
主要目的还是希望能用一套方案解决所有的测试,我目前正在做 APP 测试的设备管理和云测平台,去补齐最后一环

看着就头疼,特别是定位问题的时候,没有代码来的直接和方便,更别提 debug 了

平台看着不错,其实实用效果不强。现在的接口平台都是集成接口管理,接口自动化,Mock 平台,监控,项目管理,持续集成一体化的,单一的接口平台只是工具,简化了 PostMan 而已。WebUI 为什么没有人做平台呢?因为不适合做平台,UI 自动化维护成本高,录制回放的方式都没有流行起来,更不用说使用平台写用例了。这个项目你用来做练习还可以,如果想通用,这个是远远不够的。

Chras #11 · 2022年04月21日 Author
树叶 回复

针对定位问题,常见错误处在日志中都有提示,比如请求参数格式、断言、提取参数等。如果是其他不可控错误,日志中会打印出堆栈信息。当然如果使用者代码能力不错的话,测试引擎本地启动,也是支持像框架 debug 一样的调试。我做的这个平台根本上就是在常规测试框架上面包了一层,不懂代码可以用,懂代码的人能更好的用。但是比框架来说,用例管理和维护就方便了许多

框架设计合理的话,还是写代码效率高,并且灵活。我觉得低代码就是一个伪命题,各种框架或者库的封装就是为了少写代码提高效率。很多的低代码实际上是往无代码上靠,而完成业务肯定需要实现逻辑,低代码平台就变成了另一种形式的编程语言。即使不写常规意义上的代码也需要掌握技术理论和编程思维,如果缺乏基础,小白上手很慢,会代码的人可能又不太愿意使用,不过造轮子的精神还是值得肯定

Chras #13 · 2022年04月21日 Author
爱偷懒的QA 回复

感谢讨论。确实这些是很重要的功能模块,除了 mock 功能,其实在我设计的平台上都是有的,只不过是简化版。
您所说的这些其实更像是在做一个一站式平台,但我的观念可能不太支持一站式。因为不论测试平台这些功能做的再好,研发也不会用的,比如说接口管理,开发可能更喜欢使用 swagger 等专业工具,最终导致测试平台做了很全面的接口管理,最终还是外部导入。那我们做这些功能的价值是什么呢?所以我的观念是自动化测试平台就该是一个简单易用的工具,而不是去替代研发管理等方面的东西。
其次,针对 UI 测试,目前实现方式还是相当于用关键字翻译测试框架的脚本代码,因为测试引擎是可以本地跑的,等同于在使用测试框架。当然平台上写用例关键字步骤确实不如脚本便捷,但还会继续优化的。我想如果大家都认为事不可为,技术怎么进步呢。总归是在不断尝试中前进。
以上都是我在实际工作中产生的一些感悟,再次感谢提醒。

Chras #14 · 2022年04月21日 Author
回复

您说的对,低代码确实相当于另一种编程语言。但是这种语言门槛相对较低,我想既然能做业务测试,那至少基本的测试理论和逻辑思维还是有的。相比使用框架而言,至少不再需要他们去学习一门或多门脚本语言,更容易培训上手。就好像会用 postman 就能上手接口测试,学会 selenium 定位和基础就能做 UI 测试。
另外,平台化相对框架的优势在于管理方便、容易持续集成、输出可视化等方面,但是有得必有舍,牺牲一些用例编写的便捷性就看实际的利弊了。不是所有项目都适合用低代码平台,但还是有大部分项目适合用的,这也是一个不断探索的过程。

从楼主的设计初衷看,应该是主要针对相对复杂度不那么高的项目快速建立自动化用例用。从这个角度来看,建议楼主可以针对这个方向进一步优化,比如加上一些自动生成用例或者说录制生成基础用例的手段?

低代码平台一般初衷是相对代码经验弱一些的同学,或者通过高度的封装极大降低代码量。看楼主的思路,应该属于前者。对于代码经验弱的同学来说,自动生成/录制生成会比在界面拖拉拽写用例吸引力更大。如果不写代码但还得要求有编程思想,容易不上不下,写代码的人不喜欢用,不怎么写代码的人也觉得写起来不如自己直接执行方便。

Chras #16 · 2022年04月21日 Author
陈恒捷 回复

感谢建议。我也在不断思考一些优化手段,设计这个平台主要是因为发现框架后期维护很难,而且产出量化困难,很容易失去作用。
设计成低代码但又支持自定义代码的原因主要还是为了拓展性,可能我心目中理想化的测试团队应该是一到两个有经验的测开带着数个业务测试。在推进自动化的时候,那些比较麻烦的业务逻辑由测开来通过自定义代码封装成函数或控件,然后业务测试只需要调用即可。当然使用前总归需要一些培训工作。这个模式在之前工作中也实践过,效果还算不错,我也在不断探索。
层主建议的的录制和自动生成我也在调研中,感谢您的建议。

爱偷懒的QA 回复

非常同意这一楼的观点。

这个项目更多是帖主展示自己的思考和技术,很值得肯定。
但是如果让我来用或者让我给其他同学推广,我其实不太情愿,这个平台从实用性上看还处于比较浅层的封装,从产品化的角度来看,我觉得更有实际意义的方向还是如何一站式或体系化地解决问题,而不是单纯把一个工具上升为一个平台。(不是在贬低帖主的平台,只是一些实际看到的经验)

Chras #18 · 2022年04月22日 Author
王稀饭 回复

感谢讨论。我想可能是每个人的经历不一样导致最终这方面的看法不一致。我是赞成体系化的,但是不赞成一站式。
我没在一线大厂待过,就我待过的公司而言,一站式测试平台的其他功能基本不会被使用。比如说目前我司正在使用 ms,这个平台的体系化功能够全了,组织空间、项目管理、接口管理、用例评审、迭代计划等等功能,可是实际上呢,真正的研发线根本不会使用这些功能,毕竟原有的研发管理平台已经覆盖了这些功能,想让别人使用,很难,更何况我们又不能保证这些能力比专业的研发管理更完善,即便做的完善那么测试平台也会很臃肿。
但是我是支持体系化的,自动化测试是要融入到研发管理中去,但仅作为体系里的一环嵌入进去,所以我也加了研发管理相关的字段,但是仅做对接使用。我的想法就是让自动化平台就做自动化,不做其他的。
其实我的目标是做一个工具平台而不是完整的测试管理平台,当然如您所说,目前确实封装不够深。主要我是觉得封装的越深,耦合性就越强,拓展性就越差,那么可能就不能通用,需要对不同项目做定制化开发。目前我还刚从 0 到 1,需要解决的是整体架构设计和可拓展性,保障更广泛的适用性。未来还会从 1 到 100+,不断探索去找到一个平衡点来保障通用性。

Chras 回复

“体系化” 和 “一站式” 不完全是两个概念,“体系化” 是一种思想,而 “一站式” 只是一个表象或者一种实现,一起谈容易出现误解。

自动化平台确实就应该先做好自动化,但是在这个探讨语境中,我认为自动化平台最重要的不仅仅是自动化,用例管理、与 CICD 系统的集成或被集成等其他很多外围功能,也是平台的生命线。之所以这样说,是因为观察过实际工作,大家不会因为一件好像不是那么重要的事而不断给自己的工作引入复杂度(比如我要在代码 Merge 时跑个自动化,我不希望还要切到 CICD 其他平台看这看那的,我只需要一个测试结论)。所以 “体系化” 这里可以指代系统被外界集成的可行性和复杂度,甚至是信息信噪比(假设日常工作是围绕 CICD 来开展,以被集成到 CICD 作为设计目标 “之一”)。

另外,个人理解自动化是一个上层概念,它代表某种提效的手段,那么就底层就可以引入更多能力来让自动化做得更好,如 Mock 就是一个很大加分项。不过需要谨慎看待,实际工作中要结合内部已有的能力来建设就会少人喷一些……

而 “一站式”,更多时候像是在搞重复建设,卷其他部门,实际工作中见到好多这种皮包平台,把别人做好的能力拉过来集成包装一下就美其名曰是效率提升,实际上没有任何实际额外内容在里面,随着内部平台的大一统治理肯定会被干掉。

所以个人建议是帖主可以考虑围绕着自动化场景去引入更多能力,这些能力应该能让自动化做得更高效更准确更舒服,也是从 1 到 100 的过程。

这几年写过纯接口功能用例自动化的平台。UI 自动化平台。推广几乎都失败。因为要使用成本。而且针对稍微复杂的场景又不太够用。最终放弃了。然后今年参考了某个公司的写了另外一种接口自动化测试平台。就是框架搭好。公共方法类都自己写好。稍微简单培训会写代码或者不会写代码的人去写测试用例。然后在解析每个测试人员写的用例到平台上。平台只负责解析写的代码用例转化成可视化平台去执行维护。这样大部分测试觉的自己能过学到一定的代码能力。又能因为可视化出来大家都能看到自己写的。也方便统计 kpi

有收获

总让我想起来 robotframework 和 cucumber

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册