appium API 之 TouchAction,TouchActions,MultiAction

最近在做一些安卓自动化的项目,新手踩了一些坑,总结一下。
现在用过的常用库包括TouchAction、TouchActions、MultiAction。总结一下api和使用。

TouchAction

TouchAction是appium的辅助类,主要是一些手势操作。

from appium.webdriver.common.touch_action import TouchAction
  • tap:对元素执行点击操作

跳进函数看一下源码

def tap(self, element=None, x=None, y=None, count=1):
    """Perform a tap action on the element

    Args:
        element (`appium.webdriver.webelement.WebElement`): the element to tap
        x (:obj:`int`, optional): x coordinate to tap, relative to the top left corner of the element.
        y (:obj:`int`, optional): y coordinate. If y is used, x must also be set, and vice versa

    Returns:
        `TouchAction`: self instance
    """
    opts = self._get_opts(element, x, y)
    opts['count'] = count
    self._add_action('tap', opts)

    return self

这里可以看出来参数应该如何传,注意第一个参数传的是webElement,它将‘tap‘append到action队列中,在执行perform时,发指定指令执行。

使用

def Tap(self, data):
    _driver = self._cache.current
    ele = self._element_find(data[0], True, True)
    TouchAction(_driver).tap(ele).perform()

还有一些其他的接口:
看源码:

  • press
def press(self, el=None, x=None, y=None, pressure=None):
    """Begin a chain with a press down action at a particular element or point

    Args:
        el (:obj:`appium.webdriver.webelement.WebElement`, optional): the element to press
        x (:obj:`int`, optional): x coordiate to press. If y is used, x must also be set
        y (:obj:`int`, optional): y coordiate to press. If x is used, y must also be set
        pressure (:obj:`float`, optional): [iOS Only] press as force touch. Read the description of `force` property on Apple's UITouch class
                            (https://developer.apple.com/documentation/uikit/uitouch?language=objc) for more details on possible value ranges.

    Returns:
        `TouchAction`: self instance
    """
    self._add_action('press', self._get_opts(el, x, y, pressure=pressure))

    return self
  • long_press
    多了一个时间参数
def long_press(self, el=None, x=None, y=None, duration=1000):
    """Begin a chain with a press down that lasts `duration` milliseconds

    Args:
        el (:obj:`appium.webdriver.webelement.WebElement`, optional): the element to press
        x (:obj:`int`, optional): x coordiate to press. If y is used, x must also be set
        y (:obj:`int`, optional): y coordiate to press. If x is used, y must also be set
        duration (:obj:`int`, optional): Duration to press

    Returns:
        `TouchAction`: self instance
    """
    self._add_action('longPress', self._get_opts(el, x, y, duration))

    return self
  • move_to
def move_to(self, el=None, x=None, y=None):
    """Move the pointer from the previous point to the element or point specified

    Args:
        el (:obj:`appium.webdriver.webelement.WebElement`, optional): the element to be moved to
        x (:obj:`int`, optional): x coordiate to be moved to. If y is used, x must also be set
        y (:obj:`int`, optional): y coordiate to be moved to. If x is used, y must also be set

    Returns:
        `TouchAction`: self instance
    """
    self._add_action('moveTo', self._get_opts(el, x, y))

    return self

看一下perform函数,执行action列表里的指令

def perform(self):
    """Perform the action by sending the commands to the server to be operated upon

    Returns:
        `TouchAction`: self instance
    """
    params = {'actions': self._actions}
    self._driver.execute(Command.TOUCH_ACTION, params)

    # get rid of actions so the object can be reused
    self._actions = []

    return self

这里拿出了action里的指令,执行后,清空action。可以跳进command看一下,是一个包含指令的类。

TouchActions

TouchActions是Seeleniumd的辅助类,可以作为补充。
用法类似,
看一下源码:

class TouchActions(object):
    """
    Generate touch actions. Works like ActionChains; actions are stored in the
    TouchActions object and are fired with perform().
    """

    def __init__(self, driver):
        """
        Creates a new TouchActions object.

        :Args:
         - driver: The WebDriver instance which performs user actions.
           It should be with touchscreen enabled.
        """
        self._driver = driver
        self._actions = []

    def perform(self):
        """
        Performs all stored actions.
        """
        for action in self._actions:
            action()

    def tap(self, on_element):
        """
        Taps on a given element.

        :Args:
         - on_element: The element to tap.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.SINGLE_TAP, {'element': on_element.id}))
        return self

    def double_tap(self, on_element):
        """
        Double taps on a given element.

        :Args:
         - on_element: The element to tap.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.DOUBLE_TAP, {'element': on_element.id}))
        return self

    def tap_and_hold(self, xcoord, ycoord):
        """
        Touch down at given coordinates.

        :Args:
         - xcoord: X Coordinate to touch down.
         - ycoord: Y Coordinate to touch down.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.TOUCH_DOWN, {
                'x': int(xcoord),
                'y': int(ycoord)}))
        return self

    def move(self, xcoord, ycoord):
        """
        Move held tap to specified location.

        :Args:
         - xcoord: X Coordinate to move.
         - ycoord: Y Coordinate to move.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.TOUCH_MOVE, {
                'x': int(xcoord),
                'y': int(ycoord)}))
        return self

    def release(self, xcoord, ycoord):
        """
        Release previously issued tap 'and hold' command at specified location.

        :Args:
         - xcoord: X Coordinate to release.
         - ycoord: Y Coordinate to release.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.TOUCH_UP, {
                'x': int(xcoord),
                'y': int(ycoord)}))
        return self

    def scroll(self, xoffset, yoffset):
        """
        Touch and scroll, moving by xoffset and yoffset.

        :Args:
         - xoffset: X offset to scroll to.
         - yoffset: Y offset to scroll to.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.TOUCH_SCROLL, {
                'xoffset': int(xoffset),
                'yoffset': int(yoffset)}))
        return self

    def scroll_from_element(self, on_element, xoffset, yoffset):
        """
        Touch and scroll starting at on_element, moving by xoffset and yoffset.

        :Args:
         - on_element: The element where scroll starts.
         - xoffset: X offset to scroll to.
         - yoffset: Y offset to scroll to.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.TOUCH_SCROLL, {
                'element': on_element.id,
                'xoffset': int(xoffset),
                'yoffset': int(yoffset)}))
        return self

    def long_press(self, on_element):
        """
        Long press on an element.

        :Args:
         - on_element: The element to long press.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.LONG_PRESS, {'element': on_element.id}))
        return self

    def flick(self, xspeed, yspeed):
        """
        Flicks, starting anywhere on the screen.

        :Args:
         - xspeed: The X speed in pixels per second.
         - yspeed: The Y speed in pixels per second.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.FLICK, {
                'xspeed': int(xspeed),
                'yspeed': int(yspeed)}))
        return self

    def flick_element(self, on_element, xoffset, yoffset, speed):
        """
        Flick starting at on_element, and moving by the xoffset and yoffset
        with specified speed.

        :Args:
         - on_element: Flick will start at center of element.
         - xoffset: X offset to flick to.
         - yoffset: Y offset to flick to.
         - speed: Pixels per second to flick.
        """
        self._actions.append(lambda: self._driver.execute(
            Command.FLICK, {
                'element': on_element.id,
                'xoffset': int(xoffset),
                'yoffset': int(yoffset),
                'speed': int(speed)}))
        return self

    # Context manager so TouchActions can be used in a 'with .. as' statements.
    def __enter__(self):
        return self  # Return created instance of self.

    def __exit__(self, _type, _value, _traceback):
        pass  # Do nothing, does not require additional cleanup.

driver也可直接调用一些触摸操作。

MultiAction

模拟多指操作,与aition一起使用.
源码:

class MultiAction(object):
    def __init__(self, driver, element=None):
        self._driver = driver
        self._element = element
        self._touch_actions = []

    def add(self, *touch_actions):
        """Add TouchAction objects to the MultiAction, to be performed later.

        Args:
            touch_actions (`TouchAction`): one or more TouchAction objects describing a chain of actions to be performed by one finger

        Usage:
            a1 = TouchAction(driver)
            a1.press(el1).move_to(el2).release()
            a2 = TouchAction(driver)
            a2.press(el2).move_to(el1).release()

            MultiAction(driver).add(a1, a2)
        """
        for touch_action in touch_actions:
            if self._touch_actions is None:
                self._touch_actions = []

            self._touch_actions.append(copy.copy(touch_action))

    def perform(self):
        """Perform the actions stored in the object.

        Usage:
            a1 = TouchAction(driver)
            a1.press(el1).move_to(el2).release()
            a2 = TouchAction(driver)
            a2.press(el2).move_to(el1).release()

            MultiAction(driver).add(a1, a2).perform()
        """
        self._driver.execute(Command.MULTI_ACTION, self.json_wire_gestures)

        # clean up and be ready for the next batch
        self._touch_actions = []

        return self

放大&缩小

def ZoomScreen(self,data):
    driver = self._cache.current
    zoom_action = MultiAction(driver)
    action1 = TouchAction(driver)
    action2 = TouchAction(driver)
    x = driver.get_window_size()['width']
    y = driver.get_window_size()['height']
    action1.press(x=x * 0.4, y=y * 0.4).wait(1000).move_to(x=x * 0.2, y=y * 0.2).release()
    action2.press(x=x * 0.6, y=y * 0.6).wait(1000).move_to(x=x * 0.8, y=y * 0.8).release()

    zoom_action.add(action1, action2)
    zoom_action.perform()

def PinchScreen(self,data):
    driver = self._cache.current
    zoom_action = MultiAction(driver)
    action1 = TouchAction(driver)
    action2 = TouchAction(driver)
    x = driver.get_window_size()['width']
    y = driver.get_window_size()['height']
    action1.press(x=x * 0.2, y=y * 0.2).wait(1000).move_to(x=x * 0.4, y=y * 0.4).wait(1000).release()
    action2.press(x=x * 0.8, y=y * 0.8).wait(1000).move_to(x=x * 0.6, y=y * 0.6).wait(1000).release()

    zoom_action.add(action1, action2)
    zoom_action.perform()

你可能感兴趣的:(python,自动化测试)