zoukankan      html  css  js  c++  java
  • Airtest之iOS API汇总

    上期回顾:Airtest之安卓API汇总


    以下基于airtest1.2.0
    Airtest核心API文件路径:
    your_python_path/site-packages/airtest/core/api.py
    iOS API文件路径:
    your_python_path/site-packages/airtest/core/ios/ios.py

    ios.py中定义了一个IOS类,继承自Device基类,Device类里只有方法名定义,具体实现是在各个设备类里,比如苹果设备的实现就是在ios.py中的IOS类里。
    初始化方法里定义了很多类变量,比如cap方式、_is_pad、info(设备信息)等,这个自己看代码吧,下面我们重点介绍一下iOS类里都有哪些方法。

    def __init__(self, addr=DEFAULT_ADDR):
        super(IOS, self).__init__()

        # if none or empty, use default addr
        self.addr = addr or DEFAULT_ADDR

        # fit wda format, make url start with http://
        # eg. http://localhost:8100/ or http+usbmux://00008020-001270842E88002E
        if not self.addr.startswith("http"):
            self.addr = "http://" + addr

        """here now use these supported cap touch and ime method"""
        self.cap_method = CAP_METHOD.WDACAP
        self.touch_method = TOUCH_METHOD.WDATOUCH
        self.ime_method = IME_METHOD.WDAIME

        # wda driver, use to home, start app
        # init wda session, updata when start app
        # use to click/swipe/close app/get wda size
        wda.DEBUG = False
        self.driver = wda.Client(self.addr)

        # record device's width
        self._size = {'width': None, 'height': None}
        self._current_orientation = None
        self._touch_factor = None
        self._last_orientation = None
        self._is_pad = None
        self._device_info = {}

        info = self.device_info
        self.instruct_helper = InstructHelper(info['uuid'])
        # start up RotationWatcher with default session
        self.rotation_watcher = RotationWatcher(self)
        self._register_rotation_watcher()

        self.alert_watch_and_click = self.driver.alert.watch_and_click

    在细讲之前,让我们再来回顾一下iOS设备的链接方法:airtest之使用tidevice工具轻松连接iOS

    ios.py中方法详细说明

    1.decorator_retry_session
    装饰器,当因为session失效而操作失败时,尝试重新获取session,最多重试3次


    2.decorator_retry_for_class
    装饰器,为IOS类里的所有method添加装饰器 decorator_retry_session


    以下为IOS类中内容

    3.uuid
    类属性

    返回
    连接字符串,如http+usbmux://231ad3452c53a702

    实际案例

    auto_setup(__file__, devices=["ios:///http+usbmux://231ad21953be1eaf92"])
    print(G.DEVICE.uuid)

    4.is_pad
    类属性,判断是否是ipad(或 6P/7P/8P),如果是,在横屏+桌面的情况下,坐标需要切换成竖屏坐标才能正确点击(WDA的bug)

    返回
    是返回True,否返回False


    5.device_info
    类属性,获取设备信息

    返回:

    dict for device info,
    eg. AttrDict({
        'timeZone': 'GMT+0800',
        'currentLocale': 'zh_CN',
        'model': 'iPhone',
        'uuid': '90CD6AB7-11C7-4E52-B2D3-61FA31D791EC',
        'userInterfaceIdiom': 0,
        'userInterfaceStyle': 'light',
        'name': 'iPhone',
        'isSimulator': False})

    6.window_size()
    返回窗口大小

    返回
    namedtuple:
       Size(wide , hight)

    实际案例

    auto_setup(__file__, devices=["ios:///http+usbmux://231ad21953be1eaf92"])
    print(G.DEVICE.window_size())

    7.orientation
    return device oritantation status in LANDSACPE POR
    类属性,返回设备方向状态

    返回:    
    竖屏返回PORTRAIT,横屏返回LANDSCAPE


    8.get_orientation()
    self.driver.orientation只能拿到LANDSCAPE,不能拿到左转/右转的确切方向
    因此手动调用/rotation获取屏幕实际方向

    返回:    
    摄像头朝左的横屏返回LANDSCAPE
    摄像头朝右的横屏返回UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT


    9.display_info
    类属性,显示信息

    返回:    
    {'width': 640, 'height': 1136, 'orientation': 'PORTRAIT', 'physical_width': 640, 
    'physical_height': 1136, 'window_width': 320, 'window_height': 568}


    10.touch_factor
    类属性
    use session.scale can get UIKit scale factor
    so self._touch_factor = 1 / self.driver.scale, but the result is incorrect on some devices(6P/7P/8P)

    返回:    
    self._touch_factor = float(self._size['window_height']) / float(height)


    11.get_render_resolution()
    返回旋转后的渲染分辨率

    返回:    
    (offset_x, offset_y, offset_width and offset_height of the display)
    如(0, 0, 640, 1136)


    12.get_current_resolution()
    返回当前分辨率

    返回:
    如:
    竖屏(640, 1136)
    横屏(1136, 640)


    13.home()
    点击home键


    14.snapshot(filename=None, strType=False, quality=10, max_size=None)
    截屏

    参数:    
    filename: 截图文件名称
    quality: 截图质量,范围为[1, 99]
    max_size: 限制图片最大尺寸,如1200

    返回:    
    display the screenshot

    示例:
    详见Airtest核心API汇总


    15.touch(pos, duration=0.01)
    点按

    参数:    
    pos: 坐标(x, y), 可以是相对坐标或绝对坐标
    duration(optional): 点按持续时间

    返回:    
    None

    示例:

    touch((100, 100))  # 点击绝对坐标(100,100)
    touch((0.5, 0.5), duration=1)  # 点相对坐标(0.5,0.5),屏幕中心

    16.double_click(pos)
    双击

    参数:    
    pos: 坐标(x, y)


    17.swipe(fpos, tpos, duration=0, *args, **kwargs)
    滑动

    参数:    
    fpos – start point
    tpos – end point
    duration (float) – start coordinate press duration (seconds), default is 0

    返回:    
    None

    示例:

    swipe((1050, 1900), (150, 1900))  # 绝对坐标滑动
    swipe((0.2, 0.5), (0.8, 0.5))  # 相对坐标滑动

    18.keyevent(keyname, **kwargs)
    在设备上执行keyevent,只支持home/volumeUp/volumeDown

    参数:    
    keyname – home/volumeUp/volumeDown

    示例:

    keyevent("volumeUp")  # 音量增加
    keyevent("volumeDown")  # 音量减少

    19.text(text, enter=True)
    输入文本

    参数:
    text:  要输入的文本
    enter: 是否按回车

    返回:    
    None

    示例:

    text("qasite")  # 输入“qaiste”并回车
    text("测试工程师小站", enter=False)  # 输入"测试工程师小站"

    20.start_app(package, *args)
    启动应用

    参数:
    package: the app bundle id, e.g com.apple.mobilesafari

    返回:    
    None

    示例:

    start_app('com.apple.mobilesafari')

    21.stop_app(package)
    停止应用

    参数:    
    package: the app bundle id, e.g com.apple.mobilesafari

    返回:    
    None

    示例:

    stop_app('com.apple.mobilesafari')

    22.app_state(package)
    获取应用当前状态

    参数:    
    package: the app bundle id, e.g com.apple.mobilesafari

    返回:    
    1(not running) 2(running in background) 3(running in foreground) 4(running)
    我个人理解running in foreground是指有UI界面的app被HOME后,但仍在运行;running in background应该是本身就是以服务的形式在后台启动运行的0
    如:

    {
        "value": 4,
        "sessionId": "0363BDC5-4335-47ED-A54E-F76A65"
    }

    示例:

    dev = device()
    start_app("com.apple.mobilesafari")
    sleep(2.0)
    print("此时的包体状态为:"+str(dev.app_state("com.apple.mobilesafari")["value"]))

    home()
    sleep(2.0)
    print("此时的包体状态为:"+str(dev.app_state("com.apple.mobilesafari")["value"]))

    stop_app("com.apple.mobilesafari")
    sleep(2.0)
    print("此时的包体状态为:"+str(dev.app_state("com.apple.mobilesafari")["value"]))

    输出:
    此时的包体状态为:4
    此时的包体状态为:3
    此时的包体状态为:1

    23.app_current()
    返回当前运行的应用。可能在某些型号设备无效

    返回:AttrDict

    示例:

    dev = device()
    start_app("com.apple.mobilesafari")
    print(dev.app_current())

    keyevent("HOME")
    sleep(1.0)
    print(dev.app_current())

    输出:
    AttrDict({'processArguments': {'env': {}, 'args': []}, 'name': 'AX error -25205', 'pid': 226, 'bundleId': 'com.apple.mobilesafari'})
    AttrDict({'processArguments': {'env': {}, 'args': []}, 'name': 'AX error -25205', 'pid': 58, 'bundleId': 'com.apple.springboard'})

    24.is_locked()
    判断设备是否锁屏。可能在某些型号设备无效

    返回:    
    锁屏返回True,没锁返回False


    25.unlock()
    解锁设备、解锁屏幕、按2下HOME键。可能在某些型号设备无效

    返回:    
    None


    26.lock()
    设备锁屏。可能在某些型号设备无效

    返回:    
    None


    27.alert_accept()
    点击有2个按钮的弹窗的右边的按钮。可能在某些型号设备无效
    对于拥有2个按钮的iOS弹窗来说,一般情况下,确认按钮都在右边,所以alert_accept会点击右边的按钮。这只是一个方便使用的接口,不一定适用于所有的情况,如果遇到点击情况不符合预期,可以用按指定按钮名字来点击的接口alert_click()

    返回:    
    None


    28.alert_dismiss()
    点击有2个按钮的弹窗的左边的按钮。可能在某些型号设备无效
    对于拥有2个按钮的iOS弹窗来说,一般情况下,取消按钮都在左边,所以alert_dismiss会点击左边的按钮。这只是一个方便使用的接口,不一定适用于所有的情况,如果遇到点击情况不符合预期,可以用按指定按钮名字来点击的接口alert_click()

    返回
    None


    29.alert_wait(time_counter=2)
    判断X秒内弹窗是否出现。可能在某些型号设备无效

    参数:    
    time_counter – 等待时间,默认2秒

    返回:    
    X秒内弹窗出现返回True,否则False


    30.alert_buttons()
    获取弹窗按钮文本。可能在某些型号设备无效

    返回:    
    如,("设置", "好")


    31.alert_exists()
    判断弹窗是否存在。可能在某些型号设备无效

    返回:    
    True or False


    32.alert_click(buttons)
    点击弹窗的指定按钮。可能在某些型号设备无效

    参数:
    buttons:按钮列表,如['设置', '允许', '好']

    返回:    
    按顺序查找弹窗是否有列表中的按钮,有则点击第一个匹配的;没有则报错

    示例:

    dev = device()
    dev.alert_click(['允许','好'])

    33.home_interface()
    判断是否在HOME页。可能在某些型号设备无效

    返回:    
    True or False


    34.alert.text
    返回弹窗上的提示文字(非按钮)

    示例:

    dev = device()
    print(dev.driver.alert.text)

    35.alert_watch_and_click(buttons: Optional[list] = None,interval: float = 2.0)
    监控弹窗出现并且点击指定按钮

    参数
    buttons: 要点击的按钮列表,如["确定", "允许", "以后"]
    interval: 检查间隔,默认2秒

    示例:

    from airtest.core.ios.ios import IOS, wda
    ios = IOS("http://localhost:8100/")

    # 默认情况下监控此类弹窗:["使用App时允许", "好", "稍后", "稍后提醒", "确定", "允许", "以后"]
    with ios.alert_watch_and_click():
        sleep(5)

    # 监控指定弹窗出现并点击
    with ios.alert_watch_and_click(["Cancel"]):
        sleep(5)

    # 设置监控的时间间隔为2.0s
    with ios.alert_watch_and_click(interval=2.0):
        sleep(5)

    这里为什么要用with呢,因为其实现啊,看看源码:

    # your_python_path/site-packages/wda/__init__.py
    @contextlib.contextmanager
    def watch_and_click(self,
                        buttons: Optional[list] = None,
                        interval: float = 2.0):
        """ watch and click button
        Args:
            buttons: buttons name which need to click
            interval: check interval
        """
        if not buttons:
            buttons = self.DEFAULT_ACCEPT_BUTTONS

        event = threading.Event()

        def _inner():
            while not event.is_set():
                try:
                    alert_buttons = self.buttons()
                    logger.info("Alert detected, buttons: %s", alert_buttons)
                    for btn_name in buttons:
                        if btn_name in alert_buttons:
                            logger.info("Alert click: %s", btn_name)
                            self.click(btn_name)
                            break
                    else:
                        logger.warning("Alert not handled")
                except WDARequestError:
                    pass
                time.sleep(interval)

        threading.Thread(name="alert", target=_inner, daemon=True).start()
        yield None
        event.set()

    新手的你可能还有疑问,那就了解一下with和yield吧,另外也去了解一下threading。
    python的with用法Python yield 使用浅析

    ---------------------------------------------------------------------------------

    关注微信公众号即可在手机上查阅,并可接收更多测试分享~

  • 相关阅读:
    redis的间隔性速度慢的问题
    centos增加静态路由
    排查问题的一些基本命令
    laradock
    python之sqlalchemy基本
    ssl证书之certbot
    mysql 多实例
    模块和包
    异步
    WSGI
  • 原文地址:https://www.cnblogs.com/songzhenhua/p/15315241.html
Copyright © 2011-2022 走看看