Mobile App UI自动化locator

   在开展mobile app UI层自动化测试时,编写目标元素的locator是比较耗时的一个环节,弄清楚locator背后的逻辑,可以有效降低UI层测试维护成本。此篇博客以webdriverio+appium作为UI自动化工具为例子,看看有哪些selector方法,以及在实现应用时,如何有效提供元素ID,让UI自动化测试更加容易。

WebDriverIO提供哪些IOS的locator

  如果IOS10以及以上版本,基本都是用XCUITest driver,所以这里介绍的locator也是XCUITest框架支持的locator。实际总共就提供了三种类型的locator,-ios predicate string,-ios class chain,Accessibilty ID。下面是官网给出的三种不同locator方式的example。

// predicate string locator
const selector = `type == 'XCUIElementTypeSwitch' && name CONTAINS 'Allow'`
const switch = await $(`-ios predicate string:${selector}`)
await switch.click()// class chain locator
const selector = '**/XCUIElementTypeCell[`name BEGINSWITH "D"`]/**/XCUIElementTypeButton'
const button = await $(`-ios class chain:${selector}`)
await button.click()// Accessibility ID locator
const elem = await $('~my_accessibility_identifier')
await elem.click()

其中predicate string实际是WebDriverAgent提供的通过元素属性定位元素的方法,上面的example code中使用了type、name属性,除这些属性外还支持value,label等属性对元素进行定位。class chain也是WebDriverAgent提供的另外一种定位元素的方法。除了通过name属性进行定位外,还可以支持label,value等。例如: 

XCUIElementTypeWindow[`name == "you're the winner"`]/XCUIElementTypeAny[`visible == 1`],XCUIElementTypeWindow/XCUIElementTypeAny[`value == "bla1" OR label == "bla2"`]。上面的元素定位中accessibility id是最简单的,如何保证app的常用元素都有唯一的标识呢?实际很简单

ReactNative开发的应用设置

  WebdriverIO官方提供的被测app是由ReactNative开发的,使用WebDriverIO作为客户端工具,如果期望通过$('~xxx')进行元素定位,如果是IOS,则输入的xxx属性是accessibility ID,如果是Android,则输入的xxx属性是content-desc。在使用ReactNative开发应用的时候,如果期望转换出来的ios app有accessibility ID属性,那么需要为元素设置唯一的TestID属性,如果期望转换出来的Android app有content-desc属性,那么需要为元素设置accessibilityLable属性。当然,如果只给元素设置了TestID也是ok的,因为对于Android的app,TestID会转变成app的resource-id,有了resource-id,那么可以使用new UISelector().resourceId("xxx")来进行定位。

  下图是使用Appium Inspector查看WebDriverIO官方提供的测试app,以登录为例,email,password输入框都有accessibility id属性,在下面的属性中accessible属性是true。

  在ReactNative中,如何保证元素都有accessbilityID值呢?下面是app的source code,以上面的email输入框为例子,在Input component中引用了testProperties对象,testProperties对象中根据Platform是ios或者Android,设置了testID或者accessibilityLabel属性。开发在实现应用的时候可以约定为页面可见元素增加testID,这样定位app的元素会节省很多时间。

Flutter开发的应用

  上面介绍了ReactNative开发的应用,如果是Flutter开发的应用支持设置唯一ID么?在Appium Flutter Driver文档中有介绍,从Flutter 3.19版本开始,Flutter支持设置唯一ID,即通过设置semanticLabel属性,转换成app后,就会变成Android的resource-id或者IOS的accessibilityID。下面是一段example代码,在这个Button中设置了semanticLabel属性,值是‘my_button_label',当转换成mobile apple后,如果是Android,那么该button的resource-id就是‘my_button_label',如果是IOS,这个button的accessibilityID就是'my_button_label'.

import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('Accessibility Identifier Example')),body: Center(child: ElevatedButton(key: ValueKey('my_button_key'), // 设置 Key 用于测试onPressed: () {},child: Text('Press Me'),semanticLabel: 'my_button_label', // 设置语义标签),),),);}
}

  可以看到,如果采用跨平台的框架开发mobile app时,进行统一的属性设置,后续开展UI自动化测试时,定位页面元素会变得更加容易。当然,如果是采用纯原生开发,那么就分别针对IOS和Andorid设置每个元素的accessibilityID和resource-id即可。

 如果是一些老的app,让开发统一为每个元素设置ID会有些困难,当目标app中大部分元素没有accessibiltiyID值时,我们需要熟悉另外两个常用的元素定位方法-ios predicate thing:和-ios class chain:,以下面简单app为例子,我们不使用accessibilityID进行定位,用其他方式进行定位操作。

  下面是定位和操作目标元素代码,可以看到在定位元素的时候,基本把Appium inspector中显示的Selector copy过来即可。如果是android前面需要添加前缀android=,如果是ios,需要添加前缀-ios predicate string:或者-ios class chain:,需要注意一点:后面不要有空格,否则会出现parse失败的错误。


class NewLoginScreen {public async goToLoginScreen() {await $('~Login').click();}public async login(email: string, password: string) {const emailInput = driver.isAndroid? 'android=new UiSelector().resourceId("input-email")': '-ios predicate string:name == "input-email"';const passwordInput = driver.isAndroid? 'android=new UiSelector().resourceId("input-password")': '-ios class chain:**/XCUIElementTypeSecureTextField[`name == "input-password"`]';const loginButton = driver.isAndroid? 'android=new UiSelector().text("LOGIN")': '-ios predicate string:name == "LOGIN" AND label == "LOGIN" AND type == "XCUIElementTypeOther"';const alertOK = driver.isAndroid ? 'android=new UiSelector().name("OK")' : '-ios class chain:**/XCUIElementTypeButton[`name == "OK"`]'await $(emailInput).setValue(email);await $(passwordInput).setValue(password);await $(loginButton).click();await $(alertOK).click();}
}
export default new NewLoginScreen();import NewLoginScreen from "../screenobjects/NewLoginScreen.js";
import TabBar from '../screenobjects/components/TabBar.js';describe("can login successfully", () => {beforeEach(async () => {await TabBar.waitForTabBarShown();await TabBar.openLogin();})it("can login", async () => {await NewLoginScreen.goToLoginScreen()await NewLoginScreen.login("test001@gmail.com", "12345678")})
})

 WebDriverIO提供的Android locator

 上面介绍的都是IOS,对于Android,前面的博客有介绍Android的locator。如果采用WebDriverIO这个工具,Android选用UIAutomator2 Driver,那么定位目标元素主要有两种方式,方式一:通过content-desc,即$('~content-desc')定位目标元素,方式二:通过UISelector()定位目标元素。UISelector()中常用的有resourceId,className,text,index进行元素定位。其他text包括textStartsWith,textContains,更多信息查看here。下面是一些example code。

const selector = 'new UiSelector().text("Cancel").className("android.widget.Button")'
const button = await $(`android=${selector}`)
await button.click()public async checkScreenshotFirstLineMenu() {const selector = driver.isAndroid? 'android=new UiSelector().className("androidx.compose.ui.platform.ComposeView").instance(1)': '//XCUIElementTypeButton[@name="xx"]';await browser.checkElement(await $(selector), "firstLineMenuForHome", {enableLayoutTesting: true})}public async clickMore() {const selector = driver.isAndroid? 'android=new UiSelector().text("更多")': '//XCUIElementTypeButton[@name="xx"]';await $(selector).click()}

  总结而言,如果是新项目,为每个元素定义TestID或者semanticLabel,后续开展UI自动化测试时会更加容易,如果是老项目,需要结合多种元素定位方式进行元素定位。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82683.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

44、web实验-后台管理系统基本功能

44、web实验-后台管理系统基本功能 “44、web实验-后台管理系统基本功能”通常指的是在Web开发学习过程中,关于构建后台管理系统的实践环节,主要涉及实现一个具备基本功能的后台管理系统。以下是该实验的主要内容: #### 实验目标 - 掌握后台管…

【Flask】:轻量级Python Web框架详解

什么是Flask? Flask是一个用Python编写的轻量级Web应用框架。它被称为"微框架"(microframework),因为它核心简单但可扩展性强,不强制使用特定的项目结构或库。Flask由Armin Ronacher开发,基于Werkzeug WSGI工具包和Jin…

MAC电脑怎么通过触摸屏打开右键

在Mac电脑上,通过触摸屏打开右键菜单的方法如下: 法1:双指轻点:在触控板上同时用两根手指轻点,即可触发右键菜单。这是Mac上常用的右键操作方法。 法2:自定义触控板角落:可以设置触控板的右下角或左下角作为右键区域…

AI炼丹日志-26 - crawl4ai 专为 AI 打造的爬虫爬取库 上手指南

点一下关注吧!!!非常感谢!!持续更新!!! Java篇: MyBatis 更新完毕目前开始更新 Spring,一起深入浅出! 大数据篇 300: Hadoop&…

java32

1.反射 获取类: 获取构造方法: 获取权限修饰符: 获取参数信息: 利用反射出来的构造器来创建对象: 获取成员变量: 获取成员方法: 综合练习: 动态代理:

OpenStack组件:放置服务(Placement)安装

OpenEuler的安装_openeuler5.1.0-249-CSDN博客 OpenStack云计算平台基础环境准备_openstack基础环境配置-CSDN博客 OpenStack组件:镜像服务(Glance)安装-CSDN博客 OpenStack组件:认证服务(Keystone)安装…

整合swagger,以及Knife4j优化界面

因为是前后端项目&#xff0c;需要前端的参与&#xff0c;所以一个好看的接口文档非常的重要 1、引入依赖 美化插件其中自带swagger的依赖了 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter&…

STM32——CAN总线

STM32——CAN总线 1. CAN总线基础概念 1.1 CAN总线简介 控制器局域网&#xff08;Controller Area Network, CAN&#xff09;是由Bosch公司开发的串行通信协议&#xff0c;专为汽车电子和工业控制设计&#xff0c;具有以下核心特性&#xff1a; 多主控制架构&#xff1a;所有…

什么是数据倾斜?如何优化?

什么是数据倾斜?如何优化? 一、数据倾斜的定义与表现 数据倾斜是指在大规模数据处理系统中,数据分布严重不均匀的现象,导致某些计算节点负载远高于其他节点。这种现象在分布式计算框架(如Hadoop、Spark)和分布式数据库(如Hive、HBase)中尤为常见。 关键特征:少数节点…

大模型数据流处理实战:Vue+NDJSON的Markdown安全渲染架构

在Vue中使用HTTP流接收大模型NDJSON数据并安全渲染 在构建现代Web应用时&#xff0c;处理大模型返回的流式数据并安全地渲染到页面是一个常见需求。本文将介绍如何在Vue应用中通过普通HTTP流接收NDJSON格式的大模型响应&#xff0c;使用marked、highlight.js和DOMPurify等库进…

第11期_网站搭建_极简云 单码网络验证修复版本 虚拟主机搭建笔记

系统搭建环境 1、Nginx 最佳 2、php 7.2 3、MySql 5.6 后台地址 域名/admin 后台账号 admin 密码 123456 我使用宝塔面板的后门校验&#xff0c;没有发现有后门的现象&#xff0c;使用的话&#xff0c;建议再次核查一下。也希望各位 有能力的也核查一下。 夸克网盘下载地址&…

.net ORM框架dapper批量插入

.NET ORM 框架 Dapper 批量插入全解析 在 .NET 开发中&#xff0c;与数据库交互是常见需求。Dapper 作为轻量级的 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;在简化数据库交互方面表现出色。今天我们就来深入探讨 Dapper 实现批量插入的几种方法。 为什么需要批…

虚拟机CentOS 7 网络连接显示“以太网(ens33,被拔出)“、有线已拔出、CentOS7不显示网络图标

文章目录 一、问题描述二、解决方法1、查看网络连接方式2、开启相关服务3、确认虚拟机网络连接 一、问题描述 问题描述&#xff1a;在VmWare中安装CentOS7, 启动后界面不显示网络的图标。 在GONE桌面—》设置中找到网络设置&#xff0c;发现显示线缆已拔出。 二、解决方法 …

安卓Compose实现鱼骨加载中效果

安卓Compose实现鱼骨加载中效果 文章目录 安卓Compose实现鱼骨加载中效果背景与简介适用场景Compose骨架屏与传统View实现对比Shimmer动画原理简介常见问题与优化建议参考资料 本文首发地址 https://h89.cn/archives/404.html 背景与简介 在移动应用开发中&#xff0c;加载中占…

基于C++处理Modbus报文的完整指南

目录 &#x1f4e6; 一、Modbus报文结构解析1. RTU模式帧格式2. TCP模式帧格式 &#x1f527; 二、C实现方案与库选择示例1&#xff1a;libmodbus读取保持寄存器 (TCP) ⚙️ 三、核心处理技术1. 报文构建与发送2. 响应解析与错误处理3. 数据类型转换 &#x1f680; 四、高级应用…

【性能调优系列】深入解析火焰图:从基础阅读到性能优化实战

博客目录 一、火焰图基础&#xff1a;结构与阅读方法二、深入分析火焰图&#xff1a;关键观察点与性能瓶颈识别1. 识别最宽的函数块2. HTTP 请求处理分析3. 数据库操作分析4. 业务逻辑分析 三、性能优化实战&#xff1a;从火焰图到解决方案1. 线程池性能优化2. 数据库访问优化3…

基于 OpenCV 和 DLib 实现面部特征调整(眼间距、鼻子、嘴巴)

摘 要 本文介绍如何利用Dlib面部特征点检测和OpenCV图像处理技术&#xff0c;通过Python实现面部特征的精准调整。我们将以改变眼间距为例&#xff0c;演示包括地标检测、三角剖分变形等关键技术&#xff0c;该方法可扩展至嘴唇、眉毛等面部特征的调整。 技术栈 Python 3.8 …

Spring Data Redis 实战指南

Spring Data Redis 核心特性 Spring Data Redis 是基于 Redis 的 NoSQL 内存数据结构存储解决方案,为 Spring 应用程序提供与 Redis 交互的高级抽象层。其核心架构设计体现了对现代应用需求的深度适配,主要技术特性可归纳为以下维度: 数据结构支持体系 作为多模型数据存储…

AI IDE 正式上线!通义灵码开箱即用

近期&#xff0c;通义灵码AI IDE正式上线&#xff0c;即日起用户可在通义灵码官网免费下载开箱即用。 作为AI原生的开发环境工具&#xff0c;通义灵码AI IDE深度适配了最新的千问3大模型&#xff0c;并全面集成通义灵码插件能力&#xff0c;具备编程智能体、行间建议预测、行间…

如何搭建Z-Blog PHP版本:详细指南

Z-Blog是一款功能强大且易于使用的博客平台&#xff0c;支持PHP和ASP两种环境。本文将重点介绍如何在PHP环境下搭建Z-Blog博客系统&#xff0c;帮助您快速上线自己的个人博客站点。 准备工作 1. 获取Z-Blog PHP版本 首先&#xff0c;访问Z-Blog官方网站下载最新版本的Z-Blog…