• Airtest API精讲之连续滑动swipe_along()


    上期回顾:Airtest API精讲之swipe()

    以下基于
    python3.8;airtestIDE1.2.11;airtest1.2.2;pocoui1.0.83

    上期我们讲了swipe(),可以从一个图片或坐标滑动到另一个图片或坐标,简单讲就是一个点到另一个点的滑动,那么多个点的滑动怎么操作呢?最典型的就是9宫格解锁,可以通过swipe_along()来实现。

    老规矩开场白,我们今天要讲的是Airtest框架的swipe_along(),不是Poco框架的,一般我们说Airtest,其实应该指的是Airtest Project,具体这些概念的关系是什么,可以看之前文章:Airtest Project——UI自动化利器介绍

    首先说明一点,某些模拟器如果你选择的连接参数中有"Use Adb Touch",可能将无法使用swipe_along(),不行就换真机吧。

    源码解析

    我们先来看下swipe_along()的源码(不想看源码的可以直接跳到后面的演示实例):

     1# 文件位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
    2
    3    def swipe_along(self, coordinates_list, duration=0.8, steps=5):
    4        """
    5        Perform swipe event across multiple points in sequence.
    6
    7        Args:
    8            coordinates_list: list of coordinates: [(x1, y1), (x2, y2), (x3, y3)]
    9            duration: time interval for swipe duration, default is 0.8
    10            steps: size of swipe step, default is 5
    11
    12        Returns:
    13            None
    14
    15        """
    16        tuple_from_xy = coordinates_list[0]
    17        swipe_events = [DownEvent(tuple_from_xy, pressure=self.default_pressure), SleepEvent(0.1)]
    18        for tuple_to_xy in coordinates_list[1:]:
    19            swipe_events += self.__swipe_move(tuple_from_xy, tuple_to_xy, duration=duration, steps=steps)
    20            tuple_from_xy = tuple_to_xy
    21
    22        swipe_events.append(UpEvent())
    23        self.perform(swipe_events)

    参数:
    coordinates_list:坐标列表,如[[10,20],[20,20],[30,20]]
    duration:执行每2个点之间的等待时间,默认0.8秒
    steps:执行每2个点之间的运行步数,默认5

    第16行tuple_from_xy = coordinates_list[0]将坐标列表中的第一个坐标赋值给tuple_from_xy,意为起点

    第17行:

    swipe_events = [DownEvent(tuple_from_xy, pressure=self.default_pressure), SleepEvent(0.1)]

    定义了一个滑动事件列表swipe_events,并向列表中加入了2个事件:起点的按下事件,0.1秒的等待事件

    第18-20行,从坐标列表的第2个坐标开始,循环给滑动事件列表swipe_events追加每2个相临坐标之间的移动事件

    第22行swipe_events.append(UpEvent())给滑动事件列表swipe_events追加一个抬起事件

    第23行self.perform(swipe_events)将滑动事件列表中的每个事件依次执行


    再来看下swipe_along()第19行中self.__swipe_move()移动事件的详细实现:

     1# 文件位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
    2    def __swipe_move(self, tuple_from_xy, tuple_to_xy, duration=0.8, steps=5):
    3        """
    4        Return a sequence of swipe motion events (only MoveEvent)
    5
    6        minitouch protocol example::
    7
    8            d 0 0 0 50
    9            c
    10            m 0 20 0 50
    11            c
    12            m 0 40 0 50
    13            c
    14            m 0 60 0 50
    15            c
    16            m 0 80 0 50
    17            c
    18            m 0 100 0 50
    19            c
    20            u 0
    21            c
    22
    23        Args:
    24            tuple_from_xy: start point
    25            tuple_to_xy: end point
    26            duration: time interval for swipe duration, default is 0.8
    27            steps: size of swipe step, default is 5
    28
    29        Returns:
    30            [MoveEvent(from_x, from_y), ..., MoveEvent(to_x, to_y)]
    31        """
    32        from_x, from_y = tuple_from_xy
    33        to_x, to_y = tuple_to_xy
    34
    35        ret = []
    36        interval = float(duration) / (steps + 1)
    37
    38        for i in range(1, steps):
    39            ret.append(MoveEvent((from_x + (to_x - from_x) * i / steps,
    40                                  from_y + (to_y - from_y) * i / steps)))
    41            ret.append(SleepEvent(interval))
    42        ret += [MoveEvent((to_x, to_y), pressure=self.default_pressure), SleepEvent(interval)]
    43        return ret

    第36行interval = float(duration) / (steps + 1)2个坐标之间的总等待时间/步数+1

    第39行,因为把2个坐标分成了steps步,所以这里相当于把2个坐标之间的移动,又分成了steps-1次移动,将依次添加每一个小步的移动事件

    第41行ret.append(SleepEvent(interval)),同上,因为把2个坐标之间的移动,又分了成steps-1次,所以等待时间也要均分,并添加均分后时间的等待事件

    第42行,添加终点坐标的滑动事件和等待事件

    第43行return ret将整个移动事件列表返回


    继续看下swipe_along()第23行中self.perform()执行方法的详细实现:

     1# 文件位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
    2    def perform(self, motion_events, interval=0.01):
    3        """
    4        Perform a sequence of motion events including: UpEvent, DownEvent, MoveEvent, SleepEvent
    5
    6        Args:
    7            motion_events: a list of MotionEvent instances
    8            interval: minimum interval between events
    9
    10        Returns:
    11            None
    12        """
    13        for event in motion_events:
    14            if isinstance(event, SleepEvent):
    15                time.sleep(event.seconds)
    16            else:
    17                cmd = event.getcmd(transform=self.transform_xy)
    18                self.handle(cmd)
    19                time.sleep(interval)

    大致逻辑就是循环判断滑动事件列表,如果是SleepEvent类就等待相应时间,否则就执行具体类中的getcmd()方法。
    那除了SleepEvent类,通过上面几个方法的源码可以看到,还有DownEvent、UpEvent、MoveEvent三个类,每个类中的getcmd()方法返回了minitouch的协议命令,我们以DownEvent为例看一下:

     1# 文件位置:your_python_path/site-packages/airtest/core/android/touch_methods/base_touch.py
    2class DownEvent(MotionEvent):
    3    def __init__(self, coordinates, contact=0, pressure=50):
    4        """
    5        Finger Down Event
    6        :param coordinates: finger down coordinates in (x, y)
    7        :param contact: multi-touch action, starts from 0
    8        :param pressure: touch pressure
    9        """
    10        super(DownEvent, self).__init__()
    11        self.coordinates = coordinates
    12        self.contact = contact
    13        self.pressure = pressure
    14
    15    def getcmd(self, transform=None):
    16        if transform:
    17            x, y = transform(*self.coordinates)
    18        else:
    19            x, y = self.coordinates
    20        cmd = "d {contact} {x} {y} {pressure} c ".format(contact=self.contact, x=x, y=y, pressure=self.pressure)
    21        return cmd

    其中contact为手指的意思,就是第几根手指,pressure是按压强度(默认50),填入完整参数后的一个协议示例,手指0在[100,0]以力道50按下:

    1d 0 100 0 50
    2c

     

    演示实例

    画一个四边形

    先分别在手机上取四个点,不会的可以看之前的文章AirtestIDE基本功能(二)中的Device栏。
    然后编写脚本:

    1# -*- encoding=utf8 -*-
    2__author__ = "测试工程师小站"
    3
    4from airtest.core.api import *
    5
    6dev = device()  # 获取当前手机设备
    7# 依次滑过四个坐标,每2个坐标之间间隔3秒,分3小步
    8dev.touch_proxy.swipe_along([[250, 819],[738, 824],[744, 1312],[248, 1312],[250, 819]], duration=3, steps=3)

    我用的画板App会自动处理为圆角

    图片

    可以看到每个边是分为3步,每一步间隔1秒,是不是对duration=3, steps=3这两个参数有了直观的理解。四边形会画了,圆形、三角形还是问题吗?

    解锁九宫格

    1# -*- encoding=utf8 -*-
    2__author__ = "测试工程师小站"
    3
    4from airtest.core.api import *
    5
    6# 获取当前手机设备
    7dev = device()
    8# 解锁九宫格每一步没必要再拆分,所以steps设为1
    9dev.touch_proxy.swipe_along([[246, 1186],[547, 1182],[537, 1470],[540, 1768],[835, 1772]], duration=1, steps=1)

    图片

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

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

  • 相关阅读:
    MPTCP
    【Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) D】Bash and a Tough Math Puzzle
    【Henu ACM Round #12 D】 Longest Subsequence
    【Henu ACM Round #12 C】 Alice, Bob, Two Teams
    【Henu ACM Round #12 B】 Alice, Bob, Two Teams
    【Henu ACM Round #12 A】 Grandma Laura and Apples
    【Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) C】 Travelling Salesman and Special Numbers
    【Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) B】 Conan and Agasa play a Card Game
    【Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) A】 Perfect Squares
    【Codeforces Round #457 (Div. 2) C】Jamie and Interesting Graph
  • 原文地址:https://www.cnblogs.com/songzhenhua/p/15452303.html
Copyright © 2020-2023  润新知