UI自动化测试中选择页面元素

UI自动化测试中选择页面元素

这里讨论的问题,主要是基于 HTMLCucumber + Puppeteer 技术栈的UI自动化测试(以下简称UI自动化)中遇到的问题。

UI自动化的一线困境

UI自动化测试在前端的开发测试中,是一件政治正确的事情。

作为一名前端工程师(FE),很少有人敢于说出自己的心声,UI自动化没有什么用处。但大家的身体都很诚实,或者心照不宣的在实际开发中不考虑UI自动化,或者DEMO一下点到为止,或者轰轰烈烈地搞一场虎头蛇尾的UI自动化运动。

实践出真知,一线开发者的真实体验都是用真金白银换来的,需要得到尊重。不过,尊重常识也很重要。高速机枪的杀伤效率一定高于拉栓的步枪,自动化生产线的生产效率一定高于手工作坊。为什么UI自动化测试会比人工的UI测试效率低呢?

政治正确也没毛病,我们需要确立一个基本信念,自动化的效率一定高于人工,而且是数量级压制的差异。

在一线实践中,发现UI自动化效率不能尽如人意的时候,千万不要轻言放弃。要认真研究一下,我们的使用方法是不是科学,成本结构的瓶颈在什么地方?

总结UI自动化实践的制约因素,会发现不管是在用法上,还是在成本结构上,选择页面元素都是一处很重要的瓶颈。

选择页面元素的问题

从UI自动化最小DEMO演示(打开 1 个页面,选择 1 个按钮,点击 1 下),到全流程、全要素UI自动化回归测试,选择 HTML 页面上的元素都是基础中的基础。剧本(Feature)和场景(scenario)从简单到复杂,选择元素的重要性呈线性增长。如果选择的效率低,场景剧本在开发调试上耗时长、成本高,日常维护的返工概率高、频率高、幅度大。在规模较大的复杂UI自动化中,选择元素的效率有一点微小变化,都会给总体成本带来巨大影响,甚至成为制约UI自动化规模的天花板。

在传统前端的 jQuery 时代,使用 $ 函数选择页面元素,基本上是其他代码运行的前提。在 VUEReact 等现代前端实践中,代码与 HTML 页面产生了隔离,通过引用对象或回调函数等手段与页面元素交互,不再需要使用 CSS 选择器、 XPath等手段选择元素。从最终的 HTML 页面上看,没有什么可以捕获元素的把柄,弱化了UI自动化选择元素的能力。

HTML 页面直接贴近最终用户,是系统中变动频率比较高的部分。用户交互类的产品需求,又基本上都会带来页面变化,很容易导致日常维护中的UI自动化用例失败。

在页面不断变化的背景下,识别和提炼具有稳定性质的选择器(Selector),是UI自动化成功的关键因素之一。

选择器(Selector)的稳定性质

选择器(Selector)的稳定性质,是相对的、动态的,不总是那么显而易见,需要认真的观察和思考,需要精心的提炼。

HTML 页面上有很多标签(tag)。一般来说,使用标签(tag)做选择器(Selector)很不稳定,不过也有例外。例如,一个管理系统的列表页,上面是查询表单,下面是数据列表,可能整个页面只有一个查询按钮。或者,虽然有多个按钮,但只有一个提交查询请求的 submit 按钮。那就可以把 button 或者 button[type="submit"] 作为稳定的选择器(Selector)使用。

有的文档结构片断,也具有稳定的性质。例如,一个用户端的页面,分为 HeaderBodyFooter 三个部分,在 Header 中有一个搜索条件文本框和一个按钮用来提交搜索请求。那么 header form.search input 用来选择文本框,选择搜索按钮使用 header form.search button ,可能就是一个稳定的选择器(Selector)。

通过认真的观察,我们可以从杂乱无章的页面中,从易变的文档结构中,识别和提炼出具有稳定性质的部分,用来选择元素。找到这种稳定性质后,我们就获得了想要抒发的诗意。但要想写出优美的诗歌,光有诗意可不行,还需要丰富的词汇和对词汇的灵活运用。从另一方面来说,词汇掌握的好,也可以更容易的获得诗意,更容易的识别和提炼页面中具有稳定性质的选择器(Selector)。

选择页面元素的词汇

从UI自动化的角度,我们可以把选择页面元素的词汇不严谨的归纳为 4 类:标识类、属性类、文档结构类和组合应用类。

标识类

id 的元素,是UI自动化测试最喜欢的,因为 id 属性在设计上就是用来标识唯一元素的。

样式类(class)在设计上,本来是用来定义外观的,不应该用于选择页面元素。但是,如果某种外观本身具有稳定的性质,那就可以作为稳定的选择器(Selector)使用。例如,在一篇文章的页面,.title 样式类(class)可能就具有用于选择标题元素的稳定性。

说句题外话,虽然 idclass 基本上就可以选择到元素了,但加上元素标签(tag)可以增加可读性。例如,input#driverId 表示填写司机ID的文本框,h1.title 表示文章的标题,是一种好的编码习惯。

页面元素的 data-testid 属性,从语义上看就是为测试服务的标识。不管是前端单元测试的遗产,还是专门为UI自动化提供的标识,data-testid 一般都具有稳定性质。当然,关于是否应该使用 data-testid 属性的争论,则是另外一个故事。

属性类

其实 idclassdata-testid 都是属性类的特殊形式,也可以用属性类的词汇来表达。

在前端框架、组件库中,或者优雅的业务代码中,前端工程师(FE)经常会语义化的使用一些属性。例如,antd 的 Select 选择器有一个 role="listbox" 的属性,就具有稳定性质。

之所以作为一类单列出来,是因为属性选择器拥有类似正则表达式一样的强大语法,在UI自动化中可以很有效的选择页面元素。

li[item] 可以选择带有 item 属性的一组元素。在属性选择器前加上元素标签(tag),也是为了增加代码的可读性。

a[href="https://ant.design/"] 可以选择跳转到 antd 的超链接。

其他诸如元素的属性中包含某字符串、以某字符串开头、以某字符串结尾等属性选择器用法,就不再一一列举。

文档结构类

相比于标识类和属性类的页面元素选择器(Selector),具有稳定性质的文档结构就不总是那么一目了然,需要更多的观察、识别和提炼。

类似 button,直接使用页面元素的标签(tag),那就是选择所有的

你可能感兴趣的:(UI自动化测试中选择页面元素)