常见控件定位方法
接下来,我们来学习 app 自动化测试中常见的控件定位方法有哪些。
简介
在 Appium 中,控件定位是指通过一些特定的属性来定位和识别应用程序界面中的元素或控件。
当进行自动化测试时,需要与应用程序进行交互,例如点击按钮、输入文本、验证文本内容等。为了执行这些操作,就需要在应用程序的界面中准确定位所需的 UI 元素,例如按钮、文本框、标签等。
通过控件定位,自动化测试脚本可以在应用程序的不同界面中定位和操作特定的 UI 元素,以验证应用程序的功能和交互是否正常工作。控件定位是自动化测试的关键步骤之一,准确和可靠的控件定位对于成功执行自动化测试非常重要。
首先,我们需要了解控件定位的基础。控件定位是指通过一些特定的属性来准确地找出应用程序界面中的元素。比如,我们要进行点击、输入文本或验证页面内容等操作,这些都需要通过准确的控件定位来实现。在自动化测试中,控件定位非常重要,它决定了我们测试是否能顺利进行。只有准确地定位到所需的元素,我们才能进行进一步的操作。
控件基础知识
在定位元素之前,我们先来了解一下控件相关的基础知识。
Android 应用程序页面源码结构
Android 应用程序的页面源码结构通常使用 XML(可扩展标记语言)来定义界面布局。以下是 Android 页面源码的典型结构:
- 布局文件(Layout File):以
.xml
为扩展名的文件,定义了界面的布局结构、视图组件和其属性。 - 根元素(Root Element):通常是一个布局容器(如 LinearLayout、RelativeLayout、ConstraintLayout 等),作为根视图容器,包含其他视图组件。
- 视图组件(Views):例如 TextView、Button、ImageView 等,它们是界面中的可见元素,定义了元素的外观、行为和属性。
- 属性(Attributes):每个视图组件可以具有不同的属性,用于定义元素的特性,例如大小、位置、颜色等。
- 嵌套视图(Nested Views):可以在布局文件中嵌套其他视图组件,形成层次结构。
在 Android 应用程序中,界面结构一般是通过 XML 来定义的。每个页面有不同的布局文件,它们描述了界面的结构、视图组件以及它们的属性。布局文件通常是一个根元素,下面包含许多视图组件,如按钮、文本框等。每个视图组件都有自己的属性,像大小、颜色、位置等。
iOS 应用程序页面源码结构
iOS 应用程序的页面源码结构使用一种名为 XIB(Interface Builder)或 Storyboard 的文件格式来定义界面布局。以下是 iOS 页面源码的典型结构:
- XIB 文件或 Storyboard 文件:以.xib 或.storyboard 为扩展名的文件,包含了界面的布局和视图控件的配置信息。
- 视图控件(Views):例如 UILabel、UIButton、UIImageView 等,它们是界面中的可见元素,可以通过 XIB 或 Storyboard 文件进行配置。
- 连接线(Connections):通过连接线(Outlets 和 Actions)将视图控件与代码文件(ViewController)进行关联,以便进行交互和事件处理。
- 约束(Constraints):使用 Auto Layout 来定义视图之间的关系和自适应布局,以适应不同尺寸的设备和屏幕方向变化。
在 iOS 应用程序中,界面结构通常通过 XIB 文件或 Storyboard 来定义。iOS 的控件配置也有自己的特点,像 UILabel、UIButton 等是常见的控件类型。而且 iOS 使用约束来定义不同视图之间的关系,从而适应各种设备和屏幕方向。
iOS 与 Android 页面结构的区别
- 节点结构类似
- 名字和属性命名不同
- Android 的 resourceid 和 iOS 的 name
- Android 的 content-desc 和 iOS 的 accessibility-id
尽管 iOS 和 Android 使用不同的技术来定义页面结构,但它们在某些方面是相似的。最主要的区别在于它们的属性命名。例如,在 Android 中,我们使用 resource-id 来标识控件,而在 iOS 中,我们用 name 来标识。另外,Android 使用 content-desc,而 iOS 则使用 accessibility-id。这意味着,在写自动化脚本时,我们需要注意这些差异。
App 页面结构解析
- 节点 node
- 属性 attribute
- clickable
- content-desc
- resource-id
- text
- bounds
在 Appium 中,控件定位不仅仅依赖于控件的名字,我们还可以利用控件的各种属性来定位。例如,控件的 clickable 属性表示控件是否可以点击,resource-id 是 Android 中用来唯一标识控件的标识符,text 属性则是显示的文本内容,而 bounds 属性则定义了控件在屏幕上的位置和大小。理解这些属性有助于我们更精确地进行控件定位。
控件定位方式
在 Appium 中,控件定位是指通过一些标志性的特征来定位应用界面中的元素,以便进行自动化测试操作。Appium 支持多种控件定位方式,以下是一些常见的方法。
定位策略 | 描述 |
---|---|
Accessibility ID | 识别一个唯一的 UI 元素,对于 XCUITest 引擎,它对应的的属性名是 accessibility-id ,对于 Android 系统的页面元素,对应的属性名是 content-desc |
Class name | 对于 iOS 系统,它的 class 属性对应的属性值会以XCUIElementType 开头,对于 Android 系统,它对应的是 UIAutomator2 的 class 属性(e.g.: android.widget.TextView) |
ID | 原生元素的标识符,Android 系统对应的属性名为resource-id ,iOS 为name |
Name | 元素的名称 |
XPath | 使用 XPath 表达式查找页面所对应的 xml 的路径 |
在 Appium 中,我们可以通过多种方式来定位控件。比如,通过 Accessibility ID 来定位一个具有特定标识的元素,或者通过 Class Name 来定位某种类型的控件。另一种常见的方法是通过 XPath 表达式来查找元素,它允许我们通过路径和条件来查找控件。不同的定位方法适用于不同的场景,我们在实际使用时需要根据需求选择最合适的方法。
控件查找方法
- 返回单个元素
WebElement
。 - 返回元素列表
[WebElement, WebElement, WebElement...]
。
# 返回单个元素 WebElement
driver.find_element(AppiumBy.xxx, "xxx属性值")
# 返回元素列表 [WebElement, WebElement, WebElement...]
driver.find_elements(AppiumBy.xxx, "xxx属性值")
在 Appium 中,我们常用的方法有 find_element 和 find_elements。前者用于查找单个元素,后者用于查找多个元素。比如,如果我们只想找到一个特定的按钮,使用 find_element 就足够了;而如果我们想找到多个匹配的文本框,可以使用 find_elements 来返回所有符合条件的元素列表。
常用定位方式
接下来,我们深入了解几种常见的定位方式。
ID 定位
- 通过身份标识 id 查找元素
- 写法:
find_element(AppiumBy.ID, "ID属性值")
首先是 ID 定位,通过控件的 ID 属性来查找元素。通常,我们会使用 find_element(AppiumBy.ID, "ID属性值") 来进行查找。
ACCESSIBILITY_ID 定位
- 通过 accessibility id 查找元素
- 写法:
find_element(AppiumBy.ACCESSIBILITY_ID, "ACCESSIBILITY_ID属性值")
另一个常见的定位方式是 ACCESSIBILITY_ID,它是一个非常可靠的定位方式,尤其适合查找一些具有清晰标识的控件。
XPath 定位
- 单属性定位:
//*[@属性名='属性值']
- 多属性定位:
//*[@属性名='属性值' and @属性名='属性值' ]
接下来,我们来详细讨论 XPath 定位。XPath 是一种非常强大的定位方式,它允许我们通过属性的值来精确匹配元素。
表达式 | 描述 |
---|---|
/ | 从根节点选取(取子节点)。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
xpath 的基本语法是这样的。/ 代表根节点,或者当前节点开始点选取子节点。// 代表从根节点或者开始选择所有匹配的子孙节点。. 代表选取当前节点。.. 代表选取当前节点的父节点。@ 则代表选择属性。
元素定位示例
- 使用 appium 官方 Demo apk 进行练习,apk 网盘地址。
- 安装 ApiDemo.apk。
- 打开应用。
- 定位文字为【App】元素。
在这个页面,我们展示了如何通过 Appium 官方的 Demo APK 进行控件定位练习。我们会用 find_element 方法来定位文本为 "App" 的元素。我们可以通过安装 ApiDemo.apk,并使用 Appium 来进行这个练习。
Python 示例代码:
# test_location.py
class TestLocation:
def setup_class(self):
# Capability 设置定义为字典
caps = {}
# 设置 app 安装的平台(Android、iOS)
caps["platformName"] = "Android"
# 设置 app 的包
caps["appium:appPackage"] = "io.appium.android.apis"
# 设置 app 启动页
caps["appium:appActivity"] = ".ApiDemos"
# 不清空缓存
caps["appium:noReset"] = True
# app 不重启
caps["appium:shouldTerminateApp"] = True
# 初始化 driver
appium_server_url = 'http://localhost:4723'
self.driver = webdriver.Remote(
appium_server_url,
options=UiAutomator2Options(). \
load_capabilities(caps)
)
# 设置隐式等待
self.driver.implicitly_wait(10)
def teardown_class(self):
# 退出driver
self.driver.quit()
def test_id(self):
# 通过 ID 定位
print(self.driver.find_element(
AppiumBy.ID,
"android:id/text1"
))
def test_aid(self):
# 通过 ACCESSIBILITY ID 进行元素定位
print(self.driver.find_element(
AppiumBy.ACCESSIBILITY_ID, "App"
))
def test_xpath(self):
# 通过 XPATH 进行元素定位
print(self.driver.find_element(
AppiumBy.XPATH,
"//*[@text='App']"
))
def test_xpath1(self):
# 通过 XPATH 进行元素定位
print(self.driver.find_element(
AppiumBy.XPATH,
"//*[@text='App' and @resource-id='android:id/text1']"
))
这里我们给出了一个 Python 示例,展示如何通过不同的定位方式来查找控件。比如,在 test_id 方法中,我们通过控件的 ID 属性来查找元素,在 test_aid 方法中,我们则通过 ACCESSIBILITY_ID 来查找。在 test_xpath 方法中,我们使用了 XPath 表达式来找到文本为“App”的元素。每个方法都使用了 Appium 提供的 find_element 方法,返回的是匹配的第一个元素。
Java 示例代码:
// LocationTest.java
package org.example;
import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
public class LocationTest {
private static AndroidDriver driver;
@BeforeAll
public static void setUpClass() throws MalformedURLException {
// 初始化capability
DesiredCapabilities caps = new DesiredCapabilities();
// 设置 app 安装的平台(Android、iOS)
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
// 设置 appium 驱动
caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2");
// 设置设备名称
caps.setCapability(MobileCapabilityType.DEVICE_NAME, "emulator-5554");
// 设置 app 的包名
caps.setCapability("appPackage", "io.appium.android.apis");
// 设置 app 的启动页
caps.setCapability("appActivity", ".ApiDemos");
// 设置 app 不清空缓存
caps.setCapability("appium:noReset", true);
// 设置 app 不重启
caps.setCapability("appium:shouldTerminateApp", true);
// 设置启动url
URL remoteUrl = new URL("http://127.0.0.1:4723");
// 初始化driver
driver = new AndroidDriver(remoteUrl, caps);
}
@Test
public void idTest() {
// 通过 ID 定位
System.out.println(driver.findElement(AppiumBy.id("android:id/text1")));
}
@Test
public void aidTest() {
// 通过 ACCESSIBILITY ID 进行元素定位
System.out.println(driver.findElement(AppiumBy.accessibilityId("App")));
}
@Test
public void xpathTest() {
// 通过 XPATH 进行元素定位
System.out.println(driver.findElement(AppiumBy.xpath("//*[@text='App']")));
}
@Test
public void xpath1Test() {
// 通过 XPATH 进行元素定位
System.out.println(driver.findElement(AppiumBy.xpath("//*[@text='App' and @resource-id='android:id/text1']")));
}
@AfterAll
public static void tearDownClass() {
// 退出driver
driver.quit();
}
}
除了 Python,我们还提供了一个 Java 示例代码。在 Java 示例中,我们使用了 JUnit 和 Appium 提供的 API 来进行控件定位。通过类似的方式,我们使用了 ID、ACCESSIBILITY_ID 和 XPath 来定位控件,并打印出定位的结果。这个示例展示了如何在不同编程语言中使用相同的定位方法。
总结
- 控件基础知识
- 控件定位方式
- 控件查找方法
今天我们学习了控件定位的基础知识、常见的定位方式以及如何在 Appium 中使用这些定位方法。掌握这些基本的定位技巧后,你就能够在移动自动化测试中准确地定位和操作控件,从而实现测试脚本的自动化执行。希望大家能够在实践中灵活运用这些方法,提高测试的效率和准确性。