自动化工具 测试开发之路--UI 自动化设计军规

孙高飞 · 2018年08月12日 · 最后由 陈煜恒 回复于 2022年09月23日 · 9647 次阅读
本帖已被设为精华帖!

前言

有段时间没碰过 UI 自动化的东西了。 最近出了新产品要搞 UI 自动化,所以又开始把以前的东西捡回来。 在这里分享一下我们使用的 UI 自动化设计军规。
PS: 此军规是在 java 1.8 的背景下设计的

总体规则

所有模块设计均遵循 page object 结构

  • 用例层:测试人员编写测试用例代码的地方,可以调用 page 层和封装层。
  • page 层:一个页面一个类,包含该页面的业务逻辑封装以及部分控件定义。
  • 封装层:根据业务需要,封装常用的业务逻辑 (相比于 page 层的业务逻辑封装,它的范围更广,有些时候是跨页面的业务逻辑。 属于模块级的业务封装)

页面设计规则

所有导航,页面辅助以及会跨越多个页面的逻辑均涉及为接口,接口中定义默认实现。

如上图的导航,二级导航以及页面辅助功能都会在不同的主页面上出现。 一级导航为几乎所有页面都会用到, 二级导航为该模块下所有页面会用到。 页面辅助功能为不同的页面会用到不同的页面辅助功能。比如 DAG 页面会使用元素列表和算子列表。 但是 notebook 文件只使用元素列表。 基于此种特性, 我们将这些功能设计为接口并提供默认实现。哪个页面需要用到就去 implement。以此来达到代码复用的目的。例如:

由于 jdk 1.8 的接口有 default 实现的功能。所以需要用到相应功能的子类直接实现接口以继承相应的能力。 这也是为什么选择用 jdk1.8 的主要原因。

每个 page 类只负责自己页面的逻辑

page 类遵循一个原则---- 产品 UI 上这个页面能做什么, 这个 page 类就只能做什么。 不准许跨页面逻辑合并在一个类中实现 (页面可以有跨页面和模块级功能,但是具体每个页面的逻辑必须由每个页面自己实现)。 出现多个页面共用的功能参考上一条规则将其实现为接口。

页面类的类名以 Page 为结尾。 接口 (共用逻辑) 不得使用 Page 结尾

页面较多的时候用来区分页面和共用逻辑的规则

每个页面以封装业务逻辑为主,通过参数控制调用不同的业务逻辑。 无特殊情况下不要让外界知道控件的信息。

如上图,这是一个设置 FE 算子的逻辑,其他任何页面或者测试用例都通过此逻辑来设置 FE 算子。外界不感知任何控件信息。 如需要不同的算子设置,可以在初始化该类对象的时候,set 不同的属性值。如下:

所有页面逻辑皆返回特定页面对象,以保证测试用例使用 workflow 式 API。

以登录为例。 如下图:

登录后,进入导航页,然后在导航页的方法如下:

在进入模型 IDE 的时候返回模型 IDE page 的对象。
这样可以保持测试用例始终保持 workflow 式的调用。 如下:

除特别简单的逻辑外。所有业务逻辑的参数均使用 java bean 以及枚举封装,禁止使用基本数据类型 (int,String, long 等),并按照 UI 实际情况设计默认值

为防止产品设计变化,所有的业务逻辑参数都由 java bean 封装。 因为如果不使用 java bean 而是使用基本数据类型。那么在产品变化的时候,比如 UI 上多了一个必填的元素的时候。方法签名就会变化,导致所有调用此方法的调用方都要变化。 而是使用 java bean 封装的参数可以在其中直接增加一个属性并设置默认值即可。

如下图:图 1 为 FE 算子的配置类,图二为调用方。

所有状态吗,产品特定文案,内置类型等均使用枚举定义。并使用枚举来规范入参。

产品文案会变化,状态流转会变化。 有些时候我们会使用相应的文案来搜索页面控件, 有时候我们也会以查询数据库的方式来跟踪任务的状态, 并且这些会在整个测试的各个地方使用到。 所以严禁在 case 中或者 page 类中直接使用字符串或者数据类型的变量直接使用。 而是要将他们提取为枚举来使用。如下图:

上图是数据库中一个任务当前状态的枚举类型,在 case 运行时会动态查询数据库中此任务的 status 字段来判断任务当前状态。在 case 中调用等待任务完成的时候,需要传入此枚举表示这个用例期望这次任务的结果是哪种状态,如下图表示期望 dataload 运行成功。 当然也有些 case 会期望任务失败。

模块间有数据依赖的时候。每个模块自己负责提供对外接口。

比如测试模型中心或者预估服务的时候,首先必须要有模型事先产出。而产出一个模型需要在模型 IDE 中执行很复杂的步骤,跳转多个页面。 那么模型 IDE 负责对外提供一个封装了所有逻辑的简单接口对外使用。 例如:

ModelIDE 负责提供 modelFactory,调用方只需要传递一个模型训练算法的默认配置就可以产出相应算法的模型出来。 至于里面如何创建 project 和 dag, 使用什么数据,怎么抽取特征等等都不是调用方关心的。 他们只要一个模型出来,至于这个模型怎么出来的逻辑,不要暴露给调用方。

所有业务逻辑使用@Step标注进行标记 (allure 的特性).

用例编写规则

每个 case 都必须使用 Features,Stroies, Title 标注来为 case 添加 report 信息 (我们使用的是 allure 这个 report 框架), 根据情况可以添加 Description 标注。

具体如下:

case 中涉及 UI 上创建的实体名称,比如项目,数据,模型,用户等都需要使用随机名称。 不能使用固定名称。 以防一个环境多次运行的时候因为名称冲突而失败
case 中不准许出现页面元素信息,所有页面元素的封装和业务逻辑的封装要写在 page 层中

结尾

到这里差不多了,主要是一些设计上的规范,剩下的什么命名规范之类的就不讲了。 下一次更新一把 UI 自动化中常用的设计模式。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 33 条回复 时间 点赞

果断收藏先~

UI 自动化的技能、实现门槛不高,主要还是 ROI,这是很多公司搞不起来的主要原因。

收藏学习

赞一个,全能呀

思寒_seveniruby 将本帖设为了精华贴 08月13日 21:16

$(ByText("立即登录")).click()这个$是怎么玩的?

AngryTester 回复

这个是 selenide 的方法, 就是个以 $ 命名的方法,然后用 static import 引入过来的而已

孙高飞 回复

噢噢 多谢解答

期待下一篇的设计模式讲解

大神,问你一个问题,没有实际项目的情况下,没有实际应用下,如何深度掌握测试相关的技术,举例:接口测试

我问问 回复

在没有实际应用的前提下, 深度掌握 是不太可能的。 技术的深度取决于遇到问题的复杂度。 如果连问题都没有遇到过~~ 那就没什么深度造诣了

多谢分享,学到一种新的 UI 自动化思路。

感觉自己的虽然在做页面自动化但是和这个模型比起来简直差太多了,虽然有些地方不太理解。但是还是受到了很多收益,感谢

学习成本太高 对开发要求有点高 自动化 主要的体现应该在易用性和可维护性以及稳定性上面 可维护性体现在 对象 数据 和业务的抽离。

我目前也在做基于 PageModel 模型的自动化框架,但是用的技术比较基础,没啥技术含量,但是我也觉得 LS 的朋友说的也有一定道理,UI 自动化主要的体现应该在易用性和可维护性以及稳定性。

学习一下

红客联盟 python 常用 UI 自动化设计模式总结 中提及了此贴 11月15日 15:54

期待 pageobject 模式有深入讲解,pageobject 提了一下概念没有完整代码解释还是有点雾里看花的感觉,网上百度的都是两层封装,很少有三层封装。

飞哥学习了,打卡

Java:page 层:单页面的所有元素;business 层:一个页面的上串联的操作;testcase 层:测试用例层;对应 resource:page 层 xml 文件:存储元素的属性;testcase 层 excel:测试数据的来源。 Java 和 resource 下的 page,testcase 保证命名路径完全一样,使用反射读取。

nore 回复

兄弟可以看看我在开源项目里开源的框架,和你说的一模一样。

维护成本高啊。换 UI 换交互以后要改多少代码都不知道。现在快节奏的 ui 变动,成本高。可以针对稳定的页面做。反而现在基于视觉识别的 ui 自动化才是王道,前端控件的训练识别,省去 sikuli 的截图。

大佬请教一下,贵司 UI 自动化应该做的比较成熟了,
我一直有个疑问,就是贵司对 UI 自动化的信任程度有多高,回归时候直接自动化全覆盖,不再手动回归,还是自动化跑完,核心业务还要手动回归,只把非核心业务信任自动化?如果这样的话,投入产出比难以说服领导

那么现在的困境在于,UI 自动化不敢写太深的逻辑(变动较大,如果把所有用例都自动化,耗时可想而知,再者一旦变动都废弃了,贵司用例 3000 多,想必写的很深,把很大比例的用例都自动化了,贵司如何平衡这个问题的),

秦岭 回复

凡是自动化了的,我们就不再人肉跑了, 完全信任自动化的结果。 否则我们也不堆这么多的自动化了。 当然这也跟我们做 TO B 产品有关系, 商业模式上决定了我们业务流程不会变的那么疯狂。 比较少出现那种比如直接颠覆了现有业务形态和流程的那种事。所以极少出现直接废弃的情况。 都是页面变动, 功能变动,就跟着改就行了。 只要代码设计好了,某个功能变动了或者页面元素更改了, 那我们也只需要改一个地方就行了。 所以其实都还好。

孙高飞 回复

那么我还有个疑问,比如通常情况我们做 UI 自动化都是逻辑断言,判断逻辑正确即 Ok,到某个页面判断这个元素以及 text 文本与预期一致就 ok

但是 UI 层的,比如这次改动阴错阳差动到了一个控件的显示,造成折叠,显示上的出问题,逻辑上没问题自动化断言 pass,
UI 层的遗漏可以接受吗?

秦岭 回复

在一定程度遗漏是可以的,看你们的测试策略。 没有一个方案是效率和质量都能到 100 分的。 效率和质量是要取舍的。 我们能接受这种页面样式的 bug 遗漏。 说白了就是我们如果人肉的挨个页面检查, 这样的效率损耗我们接受不了, 所以我们就不检查了, 我们也愿意承担这种风险,如果生产出了这样页面样式的 bug,那就认命。 我从来就没追求 100% 的没 bug 状态。 而且其实新需求你怎么地都得人肉测,测新需求的时候好多页面其实能覆盖的到。 所以出这种 bug 的概率在我们这也很低。 所以直接放弃人肉测试

孙高飞 回复

那么再请教下,贵司 3000 用例,在我猜来应该不只是正向用例,逆向用例(比如输入框输入表情 非法字符)是否也自动化了?另外这个用例转化自动化的比例有多高,是能自动化就自动化,只要不是环境难建(比如人脸识别)或者价值不高(写很多代码只能覆盖一个长尾场景),就自动化吗?

秦岭 回复

只要能自动化的就自动化, 除非是太难自动化了,或者就算自动化了稳定性也太差的。

孙高飞 回复

感谢大佬解惑

孙高飞 专栏文章:UI 自动化中的分层设计 中提及了此贴 11月07日 20:02
ABEE ycwdaaaa (孙高飞) 在 TesterHome 的发帖整理 中提及了此贴 01月12日 13:47

既然已经通过 $(byText("数据中心")).click() 定位点击了,为什么还需要 this.clickProductionButton(),这一步实现了啥呢?

phoenix 回复

好几年了, 我依稀记得这个是我们 UI 上的一个图标,点击一下就回到桌面了。我们跳转模块的时候需要先点一下回到桌面。这个桌面你理解为首页把

飞哥,我在 UI 自动化上有个困扰,你有经历过白板内的产品么?这种进入白板后,无法定位元素有什么好的方法可以定位元素么?

testwu 回复

可以试试 airtest 这个库,基于图像识别的 ui 自动化

测试新人 web 自动化想法 中提及了此贴 01月11日 10:38
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册