Appium API操作教程

# 点击

el = driver.find_element('id', 'com.bilibili.app.blue:id/agree')
el.click()

# 输入

el.send_keys('words')

# 等待页面跳转

app很多操作比较耗时,比如进入首页就要很长的时间。如果还没等页面跳转完成就运行代码,大概率是无法操作成功的。

在执行操作之前,一定要确保已经进入该页面,判断已经进入页面的方法是 wait_activity 方法,传入 activity 名称和超时时间,等待该 activity 出现再执行其他操作

driver.wait_activity('tv.danmaku.bili.MainActivityV2', 10)
...
do_something_else()

# 快速进入页面

driver.start_activity('pkg', 'activity')

获取 pkg 和 activity

adb logcat | findStr -i displayed

# 滑动

driver.swipe(startx, starty, endx, endy)

appium提供的 swipe 有一个比较大的问题:用起来不方便,每次都要获取坐标传参,而且每个手机的分辨率不同,坐标也不一样,在这个手机上执行可以,换一个手机代码就不一定能正确滑动了。

因此我们要自己提供一种更方便的方法滑动。思路是这样的:通过appium获取当前手机的分辨率,然后根据分辨率的比例计算滑动距离。

适配手机:

time.sleep(2)

size = driver.get_window_rect()

startx = size['width'] * 0.9
endx = size['width'] * 0.1
starty = size['height'] * 0.1
endy = size['height'] * 0.1

driver.swipe(startx, starty, endx, endy)

封装:

class Swiper: 
    def __init__(self,driver: Remote):
        self.driver = driver

    @property
    def width(self):
        return self.driver.get_window_size().get('width')

    @property
    def height(self):
        return self.driver.get_window_size().get('height')

    def swipe_left(self, duration=2000):
        return self.driver.swipe(
            self.width*0.9,
            self.height*0.5,
            self.width*0.1,
            self.height*0.5,
            duration=duration
        )

    def swipe_right(self, duration=2000):
        return self.driver.swipe(
            self.width*0.1,
            self.height*0.5,
            self.width*0.9,
            self.height*0.5,
         duration = duration
        )

    def swipe(self, direction, duration=2000):
        if direction == 'left':
            self.swipe_left(duration)
        elif direction == 'right':
            self.swipe_right(duration)
				...

flink 的作用基本和 swipe 差不多。

# 进入指定页面

app 的路径依赖是很严重的,如果需要测试某个单独的页面,但是进入这个页面有很长的路径,则会严重影响效率,而且路径过长,会让测试程序不稳定。

start_activity 可以快速进入指定界面,只需要指定 activity 的名称。

获取当前页面的名称:

adb shell dumpsys activity | find "mResumedActivity"
driver.start_activity('com.lemon.lemonban','.activity.LoginActActivity')

# 放大

参考: Appium实现图片放大缩小 (opens new window)

以前的封装

def zoom_screen(rect):
    print(rect)
    width = rect['width']
    height = rect['height']
    x = rect['x']
    y = rect['y']

    m = MultiAction(driver)
    a1 = TouchAction(driver)
    a2 = TouchAction(driver)

    # a1.press(x=x+width/2, y=y+height/2).move_to(x=x+width, y=y+height/2)
    # a2.press(x=x+width/2, y=y+height/2).move_to(x=x, y=y+height/2)
    print()

    a1.press(x=width / 2, y=height / 2).move_to(x=width, y=height / 2).release()
    a2.press(x=width / 2, y=height / 2).move_to(x=0, y=height / 2).release()

    m.add(a1,a2)
    m.perform()
def zoom(self, offset):
        """放大"""
        action_1 = TouchAction(self.driver)
        action_1.press(x=self.width / 2, y=self.height / 2).move_to(
            x=self.width / 2, y=self.height / 2 - offset).release()
        action_2 = TouchAction(self.driver)
        action_2.press(x=self.width / 2, y=self.height / 2).move_to(
            x=self.width / 2, y=self.height / 2 + offset).release()

        m = MultiAction(self.driver)
        m.add(action_1, action_2)
        m.perform()

    def pinch(self, offset):
        """缩小"""
        action_1 = TouchAction(self.driver)
        action_1.press(x=self.width / 2, y=self.height / 2 - offset).move_to(
            x=self.width / 2, y=self.height / 2).release()
        action_2 = TouchAction(self.driver)
        action_2.press(x=self.width / 2, y=self.height / 2 + offset).move_to(
            x=self.width / 2, y=self.height / 2).release()

        m = MultiAction(self.driver)
        m.add(action_1, action_2)
        m.perform()

安卓图片放大(只能在控制台生效)

caps = {
        "deviceName": "emulator-5554",
        "platformName": "Android",
        "appPackage": "com.android.gallery3d",
        "appActivity": ".app.GalleryActivity",
        "newCommandTimeout": 1200
}

driver = Remote(command_executor='<http://127.0.0.1:4444/wd/hub>',
              desired_capabilities=caps)

time.sleep(3)
rect = driver.get_window_rect()
m = MultiAction(driver)
a1 = TouchAction(driver)
a2 = TouchAction(driver)
width = rect['width']
height = rect['height']
a1.tap(x=width / 2, y=height / 2).perform()

a1.long_press(x=width / 2, y=height / 2).move_to(x=width, y=height / 2).release()
a2.long_press(x=width / 2, y=height / 2).move_to(x=0, y=height / 2).release()
m.add(a1, a2)
m.perform()

# 后台执行

driver.backgroud_app(10)
driver.active_app('com.android.settings')

# 按键操作

# 发数字
driver.press_keycode(8)
driver.press_keycode(9)
driver.press_keycode(10)

# 浏览器
EXPLORER = 64
# 电源键
POWER = 26
# 音量键
VOLUME_UP = 24
VOLUME_DOWN = 25
# 输入数据之前还需要点击。
ENTER = 66
# 可能出现的问题:
#首页
HOME = 3
# 模拟器拨号、拍照用不了

https://www.jianshu.com/p/f7ec856ff56f (opens new window)

https://blog.csdn.net/qq_14908027/article/details/78880578 (opens new window)

# Toast 弹框处理

前提

登录:Toast,是 viewer 识别不到的。但是我们需要确认文本是否正确。

  1. appium server 1.6.3 以上
  2. 代码中必须制定 automationName为:UiAutomator2
  3. UIAutomator2只支持安卓版本 5.0+
  4. jdk1.8 64位以上。配置 JAVA_HOME 环境变量;

定位

driver.find_element('xpath', '//android.widget.Toast')
driver.find_element('xpath', " //*[contains(@text, '手机号码不能为空')]")

显性等待用 presence, 不要用 visibility。

实战

  • 注意:轮询周期非常短。
  • 确保你的信息只有你有,其他的元素没有。

UiAutomator2 报错

# 输入中文

在b站搜索关键字的例子:

driver.find_element('id', 'com.bilibili.app.blue:id/agree').click()  
driver.find_element('id', 'com.bilibili.app.blue:id/expand_search').click()  
driver.find_element('id', 'com.bilibili.app.blue:id/search_src_text').send_keys('老照片')  
driver.press_keycode(66)

在真机中输入中文时,可能需要使用支持 unicode 的键盘,加上这两个参数。

caps = dict(
	unicodeKeyboard=True,
	resetKeyboard=True
)

# 隐藏键盘

# 发短信

# 打电话

# 其他操作

所有的 api 都在 官网 (opens new window) 很方便的查看到。

  • driver.hide_keyboard(), 隐藏键盘
  • driver.get_screenshot_as_file()
  • shake,摇一摇。可以
  • lock
  • unlock

# 截屏

driver.get_screenshot_as_base64()

# 录屏

Screen recording does not work on emulators running Android API level less than 27

换成真机或者高于27 API 的安卓模拟器。

# TODO:九宫格绘制

# TODO: Commands Appium 指令

Commands 列表 (opens new window)

Desired Caps 说明 (opens new window)

本文完,感谢你的耐心阅读,如有需要可加我微信,备注「博客」并说明原因,我们一起进步,下次见。

上次更新: 2022/05/31, 07:30:39
最近更新
01
02-Cypress如何在写代码时获取提示
08-27
02
02-Cypress安装
08-27
03
0-Python怎么才能快速学好
08-27
更多文章>