Skip to content

常见控件交互方法

常见的交互方法

简介

与 Web 元素操作一样(参考 Selenium Web 元素操作),定位到 APP 控件元素后,可以对控件进行一系列的操作,实现与 APP 交互,比如点击、文本输入、元素属性获取等。

控件交互常用方法

常见操作

  • 点击元素:element.click()
  • 点击坐标:driver.tap([(x, y)], 1000)
  • 元素中输入内容:element.send_keys('appium')
  • 清除元素中内容:element.clear()

状态判断

  • 是否可见 element.is_displayed() 返回 True/False。
  • 是否可用 element.is_enabled() 返回 True/False。
  • 是否被选中 element.is_selected() 返回 True/False。

获取元素属性

  • 获取元素属性:element.get_attribute() - resource-id - text - class - content-desc - checkable、checked、clickable、enabled、focusable、focused 等
  • 获取元素文本:element.text
  • 获取元素坐标:

    - 格式:element.location - 结果:{'y': 19,'x: 498}

  • 获取元素尺寸(高和宽):

    - 格式:element.size - 结果:{'width':500,'height':22}

控件操作交互示例

  • 使用 appium 官方 Demo apk 进行练习,apk 网盘地址
  • 打开 ApiDemos.apk。
  • 点击 Animation 进入下个页面。
  • 点击 Seeking 进入下个页面。
  • 查看【RUN】按钮是否显示/是否可点击。
  • 查看【滑动条】是否显示/是否可点击。
  • 获取【滑动条】长度。
  • 点击【滑动条】中心位置。

Python 代码示例

from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy

class TestEleOper:

    def setup_class(self):
        '''
        完成 capability 设置
        初始化 driver
        :return:
        '''
        # 设置 cpability
        caps = {
            # 设置 app 安装的平台(Android,iOS)
            "platformName": "Android",
            # 设置 appium 驱动
            "appium:automationName": "uiautomator2",
            # 设置设备名称
            "appium:deviceName": "emulator-5554",
            # 设置被测 app 的包名
            "appium:appPackage": "io.appium.android.apis",
            # 设置被测 app 启动页面的 Activity
            "appium:appActivity": ".ApiDemos"
        }

        # 初始化 driver
        self.driver = webdriver.Remote(
            "http://127.0.0.1:4723",
            options=UiAutomator2Options().load_capabilities(caps)
        )
        # 设置全局隐式等待
        self.driver.implicitly_wait(5)

    def teardown_class(self):
        '''
        关闭 driver
        :return:
        '''
        self.driver.quit()

    def test_ele_oper(self):
        '''
        点击滑动条中心位置
        :return:
        '''
        # 点击 Animation
        self.driver.find_element(
            AppiumBy.ACCESSIBILITY_ID, "Animation"
        ).click()
        # 点击 Seeking
        self.driver.find_element(
            AppiumBy.ACCESSIBILITY_ID, "Seeking"
        ).click()
        # 查看【RUN】按钮是否显示/是否可点击
        run_btn_ele = self.driver.find_element(
            AppiumBy.ID, "io.appium.android.apis:id/startButton"
        )
        print(f"RUN 按钮是否显示 {run_btn_ele.is_displayed()}")
        print(f"RUN 按钮是否可用 {run_btn_ele.is_enabled()}")
        print(f"RUN 按钮是否可点击 {run_btn_ele.get_attribute('clickable')}")
        # 查看【滑动条】是否显示/是否可点击
        seek_bar_ele = self.driver.find_element(
            AppiumBy.ID, "io.appium.android.apis:id/seekBar"
        )
        print(f"滑动条是否显示 {seek_bar_ele.is_displayed()}")
        print(f"滑动条是否可点击 {seek_bar_ele.get_attribute('clickable')}")
        # 查看【滑动条】的属性
        print(f"滑动条的 resource-id 属性为 {seek_bar_ele.get_attribute('resource-id')}")
        print(f"滑动条的 text 属性为 {seek_bar_ele.get_attribute('text')}")
        print(f"滑动条的 class 属性为 {seek_bar_ele.get_attribute('class')}")
        print(f"滑动条的 content-desc 属性为 {seek_bar_ele.get_attribute('content-desc')}")
        # 获取【滑动条】长度
        seek_bar_ele_width = seek_bar_ele.size.get('width')
        print(f"滑动条长度为 {seek_bar_ele_width}")
        # 获取【滑动条】起始位置坐标
        seek_bar_ele_start = seek_bar_ele.location
        print(f"滑动条起始位置坐标为 {seek_bar_ele_start}")
        # 获取【滑动条】中间位置坐标
        seek_bar_center_x = seek_bar_ele_start.get("x") + seek_bar_ele_width / 2
        seek_bar_center_y = seek_bar_ele_start.get("y")
        seek_bar_center = (seek_bar_center_x, seek_bar_center_y)
        print(f"滑动条中间位置坐标为 {seek_bar_center}")
        # 点击【滑动条】中间位置
        self.driver.tap([seek_bar_center], 1000)

Java 代码示例

package org.example;

import io.appium.java_client.AppiumBy;


import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;

import io.appium.java_client.touch.WaitOptions;
import io.appium.java_client.touch.offset.PointOption;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.PointerInput;
import org.openqa.selenium.interactions.Sequence;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.Collections;


public class TestEleOper {

    private static AndroidDriver driver;

    @BeforeAll
    public static void setUp() 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);
    }

    @AfterAll
    public static void teardownClass() {
        if (driver != null) {
            driver.quit();
        }
    }

    @Test
    public void testEleOper() {
        // 点击 Animation
        driver.findElement(AppiumBy.accessibilityId("Animation")).click();

        // 点击 Seeking
        driver.findElement(AppiumBy.accessibilityId("Seeking")).click();

        // 查看【RUN】按钮是否显示/是否可点击
        WebElement runBtnEle = driver.findElement(AppiumBy.id("io.appium.android.apis:id/startButton"));
        System.out.println("RUN 按钮是否显示: " + runBtnEle.isDisplayed());
        System.out.println("RUN 按钮是否可用: " + runBtnEle.isEnabled());
        System.out.println("RUN 按钮是否可点击: " + runBtnEle.getAttribute("clickable"));

        // 查看【滑动条】是否显示/是否可点击
        WebElement seekBarEle = driver.findElement(AppiumBy.id("io.appium.android.apis:id/seekBar"));
        System.out.println("滑动条是否显示: " + seekBarEle.isDisplayed());
        System.out.println("滑动条是否可点击: " + seekBarEle.getAttribute("clickable"));

        // 查看【滑动条】的属性
        System.out.println("滑动条的 resource-id 属性为: " + seekBarEle.getAttribute("resource-id"));
        System.out.println("滑动条的 text 属性为: " + seekBarEle.getAttribute("text"));
        System.out.println("滑动条的 class 属性为: " + seekBarEle.getAttribute("class"));
        System.out.println("滑动条的 content-desc 属性为: " + seekBarEle.getAttribute("content-desc"));

        // 获取【滑动条】长度
        int seekBarEleWidth = seekBarEle.getSize().getWidth();
        System.out.println("滑动条长度为: " + seekBarEleWidth);

        // 获取【滑动条】起始位置坐标
        Point seekBarEleStart = seekBarEle.getLocation();
        System.out.println("滑动条起始位置坐标为: " + seekBarEleStart);

        // 获取【滑动条】中间位置坐标
        int seekBarCenterX = seekBarEleStart.getX() + seekBarEleWidth / 2;
        int seekBarCenterY = seekBarEleStart.getY();
        System.out.println("滑动条中间位置坐标为: (" + seekBarCenterX + ", " + seekBarCenterY + ")");

        // 点击【滑动条】中间位置
        PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
        Sequence sequence = new Sequence(finger, 1)
                .addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), seekBarCenterX, seekBarCenterY))
                .addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()))
                .addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
        driver.perform(Collections.singletonList(sequence));

    }
}

总结

  • 常见操作
  • 状态判断
  • 获取元素属性