AirTest 基本操作范例和参数解释(一)

背景:基于目前团队中推广UIAutomation,采用了网易的UI自动化平台,平台兼容iOS、Android和WEB,是个跨平台的多库平台,利用poco和python进行脚本编写和开展自动化,但是在日常使用中有些同学对于一些关键字和参数有时记不住或者使用错误,这里特地整理完备供大家日常参考。

一、基本操作

1.前置用例引用

        可以将一些通用的操作写在一个.air脚本中,然后在其他脚本中import它

from airtest.core.api import using
using("replace_install.air") # 需要使用相对路径,不然找不到.air
import replace_install

2.引用自定义的公共类或方法

        在编写自动化的过程中,有一些自定义的方法或类,需要在.air下的.py中引用时候,需要将项目路径添加到环境变量中 

import sys import os # 必填,将项目目录添加到系统环境变量中 sys.path.append(‘项目路径’)

3.元素定位方式

(1)尽量使用text定位元素

poco(text="立即体验") poco(textMatches="^.*滑动来解锁.*$")#正则来模糊定位

(2)如果不能直接定位,建议使用局部布局

        子元素

poco(text='main_node').child(text='list_item')

        后代

poco(text='main_node').offspring(text='name')

        父

poco(text='main_node').parent()

        所有子元素

poco(text='main_node').children()

        兄弟元素

poco(text='main_node').sibling(text='name')

备注:

  • 因为text变化的概率相对较小,所以建议使用text,且脚本易读;
  • resourceid不建议,因为release版会混淆,除非公司对resourceid进行了统一设计和规划,且release版本不混淆。

4.元素操作

(1)点击元素身上的某一点

        通过相对坐标,控制点击的具体位置。左上角(0, 0),右下角(1, 1),横坐标为x,纵坐标为y。

(2)等待元素出现或消失

        实际写用例时,有一些扫描或缓冲场景,需要等待元素出现或消失,才能进行下一步操作。

        当使用wait_for_appearance或wait_for_disappearance时,建议处理PocoTargetTimeout,并截图,以方便在报告中查看出错时的页面情况

try:
    poco(text='main_node').wait_for_appearance(timeout=10)
    poco(text='main_node').wait_for_disappearance(timeout=10)
except PocoTargetTimeout:
    snapshot(msg="元素出现或未出现")

(3)滑动和拖动

        拖动

poco('star').drag_to(poco('shell'))

        滑动

poco('Scroll View').swipe([0, -0.1]) # 滑动指定坐标 
poco('Scroll View').swipe('up') # 向上滑动 
poco('Scroll View').swipe('down') # 向下滑动

        向量滑动

x, y = poco('Scroll View').get_position()
end = [x, y - 0.1]
dir = [0, -0.1]
poco.swipe([x, y], end)  # 从A点滑动到B点
poco.swipe([x, y], direction=dir)  # 从点A向给定方向和长度进行滑动

(4)获取元素信息(重要手段)

"""
attribute name, it can be one of the following or any other customized type implemented by SDK
- visible: whether or not it is visible to user
- text: string value of the UI element
- type: the type name of UI element from remote runtime
- pos: the position of the UI element
- size: the percentage size [width, height] in range of 0~1 according to the screen
- name: the name of UI element
- ...: other sdk implemented attributes
"""


poco(text="text_content").attr("checkable")
poco(text="text_content").get_position()
poco(text="text_content").get_text()
....

(5)连续滑动与自定义滑动操作

from airtest.core.api import * dev = device() # 获取当前手机设备

        手指按照顺序依次滑过3个坐标,可以用于九宫格解锁

dev.minitouch.swipe_along([(100, 100), (200, 200), (300, 300)])

        自定义操作:实现两个手指同时点击的操作

from airtest.core.android.minitouch import *

multitouch_event = [
DownEvent((100, 100), 0),  # 手指1按下(100, 100)
DownEvent((200, 200), 1),  # 手指2按下(200, 200)
SleepEvent(1),
UpEvent(0), UpEvent(1)]  # 2个手指分别抬起

device().minitouch.perform(multitouch_event)

        自定义操作:三只滑动操作

from poco.utils.track import *

tracks = [
MotionTrack().start([0.5, 0,5]).move([0.5, 0.6]).hold(1).
MotionTrack().start([0.5, 0,5]).move([0.5, 0.6]).hold(1).
MotionTrack().start([0.5, 0,5]).move([0.5, 0.6]).hold(1)
]

poco.apply_motion_tracks(tracks)

        手       势操作:点击ui1保持1秒,拖动到ui2并保持1秒,然后抬起

ui1.start_gesture().hold(1).to(ui2).hold(1).up()

(6)点击元素偏移位置

        点击, focus为偏移值,sleep_interval为点击后的间隔时间

poco(text="立即清理").click(focus=(0.1, 0.1), sleep_interval=5)

(7)隐性等待元素

        隐形等待元素出现,元素出现后,wait()方法结束(隐藏元素常用方法)

poco(text="立即清理").wait(timeout=5)

(8)判断元素是否存在

        判断元素是否存在,存在返回True

poco(text="立即清理").exists()

(9)UI状态清除(请运行完毕之后,务必执行)

        在poco里选择出来的ui都是代理对象,在执行同一个用例里,一个ui控件选出来后能持续多长时间有效这个是要看android那回收ui资源的策略的,每个厂商的差异比较大.

        对于cocos2d-x引擎的poco,由于使用的是快照模式,获取到UI状态后如果UI状态确实发生了改变,需要调用ui.invalidate()进行重新获取。

ui = poco(text="立即清理")
ui.click()
ui.invalidate()
ui.click()

(10)long click

        长按操作,单位:秒

poco(text="立即清理").long_click(duration=2.0)

(11)两指挤压收缩操作

        在给定的范围和持续时间下,在UI上两指挤压收缩操作

poco.pinch(direction='in', percent=0.6, duration=2.0, dead_zone=0.1)

(12)根据UI滑动

        根据UI的给定高度或宽度,滑动距离的百分比:

        从底部上滑5秒

poco.scroll(direction='vertical', percent=1, duration=5)

        从顶部下滑5秒

poco.scroll(direction='vertical', percent=-1, duration=5)

二、异常类

        建议对每一个可能出现异常的地方都进行异常处理,并截图,最后看报告时方便迅速定位问题。

1.InvalidOprationException

        这个异常特指无效的操作,或者不起作用的操作

try:
    poco.click([1.1, 1.1])  # click outside screen
except InvalidOperationException:
    snapshot(msg="出现异常")

2.PocoNoSuchNodeException(经常遇到)

        如果从一个不存在的UI空间读取属性或操作,就会出现该异常。

node = poco("not existed node")
try:
    node.click()
except PocoNoSuchNodeException:
    snapshot(msg="出现异常")
try:
    node.attr('text')
except PocoNoSuchNodeException:
    snapshot(msg="出现异常")

3.PocoTargetTimeout

        这个异常只会在你主动等待UI出现或消失时抛出,和 PocoNoSuchNodeException 不一样,当你的操作速度太快,界面来不及跟着变化的话,你只会遇到 PocoNoSuchNodeException 而不是 PocoTargetTimeout ,其实就是在那个UI还没有出现的时候就想要进行操作。

node = poco("not existed node")
try:
    node.click()
except PocoNoSuchNodeException:
    snapshot(msg="出现异常")
try:
    node.attr('text')
except PocoNoSuchNodeException:
    snapshot(msg="出现异常")

4.PocoTargetRemovedException

        如果操作速度远远慢于UI变化的速度,很可能会出现这个异常。当且仅当访问或操作一个刚才存在现在不在的UI元素时,才会出现,并且一般不会出现。

try:
    poco(text="demo").click()
except PocoNoSuchNodeException:
    snapshot(msg="出现异常")

三、封装API好的函数

1.滚动查找元素(poco_swipe_to)

        滚动查找元素,当找到元素后,滑动元素到页面中间。

        公式:poco_swipe_to(text=None, textMatches=None, poco=None)

# 滚动查找元素
def poco_swipe_to(text=None, textMatches=None, poco=None):
    find_ele = False
    find_element = None
    if poco is None:
        raise Exception("poco is None")
    if text or textMatches:
        swipe_time = 0
        snapshot(msg="开始滚动查找目标元素")
        if text:
            find_element = poco(text=text)
        elif textMatches:
            find_element = poco(textMatches=textMatches)
        while True:
            snapshot(msg="找到目标元素结果: " + str(find_element.exists()))
            if find_element.exists():
                # 将元素滚动到屏幕中间
                position1 = find_element.get_position()
                x, y = position1
                if y < 0.5:
                    # 元素在上半页面,向下滑动到中间
                    poco.swipe([0.5, 0.5], [0.5, 0.5+(0.5-y)], duration=2.0)
                else:
                    poco.swipe([0.5, 0.5], [0.5, 0.5-(y-0.5)], duration=2.0)
                snapshot(msg="滑动元素到页面中间: " + str(text) + str(textMatches) )
                find_ele = True
                break
            elif swipe_time < 30:
                poco.swipe([0.5, 0.8], [0.5, 0.4], duration=2.0)
                # poco.swipe((50, 800), (50, 200), duration=500)
                swipe_time = swipe_time + 1
            else:
                break
    return find_ele

2.等待任一元素出现(poco.wait_for_any)

try:
    poco(text="demo").click()
except PocoNoSuchNodeException:
    snapshot(msg="出现异常了呀")

3.等待所有元素(poco.wait_for_all)

try:
    poco(text="demo").click()
except PocoNoSuchNodeException:
    snapshot(msg="出现异常")

4.观察者函数(watcher)

        说明:利用子进程对页面元素进行监控,发元素后,自动操作。

        适用场景:多用于不可预测的弹窗或元素

        公式:watcher(text=None, textMatches=None, timeout=10, poco=None)

​
def loop_watcher(find_element, timeout):
    start_time = time.time()
    while True:
        # find_element.invalidate()
        if find_element.exists():
            find_element.click()
            print("观察者:发现元素!!!")
            break
        elif (time.time() - start_time) < timeout:
            print("--------------------观察者:等待1秒----------------")
            time.sleep(1)
        else:
            print("观察者:超时未发现!!")
            break

def watcher(text=None, textMatches=None, timeout=10, poco=None):
    print("观察者:启动!!")
    # 目标元素
    find_element = None
    if poco is None:
        raise Exception("poco is None")
    if text or textMatches:
        if text:
            find_element = poco(text=text)
        elif textMatches:
            find_element = poco(textMatches=textMatches)

    # 定义子线程: 循环查找目标元素
    from multiprocessing import Process
    p = Process(target=loop_watcher, args=(find_element, timeout,))
    p.start()

​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/881161.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

模拟自然的本质:与IBM量子计算研究的问答

量子计算可能是计算领域的下一个重大突破&#xff0c;但它的一般概念仍然处于炒作和猜测的现状&#xff1f;它能破解所有已知的加密算法吗&#xff1f;它能设计出治愈所有疾病的新分子吗&#xff1f;它能很好地模拟过去和未来&#xff0c;以至于尼克奥弗曼能和他死去的儿子说话…

【Redis入门到精通二】Redis核心数据类型(String,Hash)详解

目录 Redis数据类型 1.String类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 2.Hash类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 Redis数据类型 查阅Redis官方文档可知&#xff0c;Redis提供给用户的核心数据…

dockercompose指定配置文件

dockercompose指定配置文件 文件名字必须是以下的集中形式&#xff1a; docker-compose.yaml docker-compose.yml compose.yaml compose.yml 其他名字就失败的。 一般白眉大叔都是用 compose.yaml 这个格式&#xff0c; 用习惯了。 但是我们必须知道它有几种格式都是可以…

如何利用nw.js打包vue项目

引言 最近有一个开发windows桌面应用的需求, 需要将vue项目打包成.exe文件&#xff0c;最好是变成可安装版(非绿色版)。特此记录一下如何通过nw.js将vue项目打包成.exe。可能这种方式不是最优&#xff0c;仅供大家参考&#xff01; nw.js简介&#xff08;以下描述来自nw.js官…

C#|.net core 基础 - 扩展数组添加删除性能最好的方法

今天在编码的时候遇到了一个问题&#xff0c;需要对数组变量添加新元素和删除元素&#xff0c;因为数组是固定大小的&#xff0c;因此对新增和删除并不友好&#xff0c;但有时候又会用到&#xff0c;因此想针对数组封装两个扩展方法&#xff1a;新增元素与删除元素&#xff0c;…

大数据概念与价值

文章目录 引言大数据的概念高德纳咨询公司的定义麦肯锡全球研究所的定义什么是大数据&#xff1f; 大数据的特征Volume&#xff08;体积&#xff09;Variety&#xff08;种类&#xff09;Velocity&#xff08;速度&#xff09;Value&#xff08;价值&#xff09;Veracity&#…

【Redis入门到精通三】Redis核心数据类型(List,Set)详解

目录 Redis数据类型 ​编辑 1.List类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 2.Set类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 Redis数据类型 查阅Redis官方文档可知&#xff0c;Redis提供给用户的核…

ASP.NET Core高效管理字符串集合

我们在开发 Web 项目时经常遇到需要管理各种来源的字符串集合&#xff08;例如HTTP 标头、查询字符串、设置的值等&#xff09;的情况。合理的管理这些字符串集合不仅可以减少出bug的几率&#xff0c;也能提高应用程序的性能。ASP.NET Core 为我们提供了一种特殊的只读结构体 S…

多层感知机paddle

多层感知机——paddle部分 本文部分为paddle框架以及部分理论分析&#xff0c;torch框架对应代码可见多层感知机 import paddle print("paddle version:",paddle.__version__)paddle version: 2.6.1多层感知机&#xff08;MLP&#xff0c;也称为神经网络&#xff0…

有关JS下隐藏的敏感信息

免责声明&#xff1a;本文仅做分享&#xff01; 目录 JavaScript 介绍 核心组成 工具 FindSomething ** 浏览器检查 ** LinkFinder URLfinder ** SuperSearchPlus ** ffuf ParasCollector waymore Packer Fuzzer JS逆向 应用&#xff1a; 小结&#xff1a; Ja…

java-----IDE(集成开发环境)

IDE&#xff08;集成开发环境&#xff09; IDE&#xff08;集成开发环境&#xff09;-IDEA IDEA 介绍 1) IDEA 全称 IntelliJ IDEA2) 在业界被公认为最好的Java开发工具3) IDEA是JetBrains 公司的产品&#xff0c;总部位于捷克的首都布拉格4) 除了支持Java开发&#xff0c;还…

54.【C语言】 字符函数和字符串函数(strncpy,strncat,strncmp函数)

和strcpy,strcat,strcmp函数对应的是strncpy,strncat,strncmp函数 8.strncpy函数 *简单使用 cplusplus的介绍 点我跳转 翻译: 函数 strncpy char * strncpy ( char * destination, const char * source, size_t num ); 从字符串中复制一些字符 复制源(source)字符串的前num个…

【专题】2024新能源企业“出海”系列之驶向中东、东南亚报告合集PDF分享(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p37698 在“双碳”目标引领下&#xff0c;中国新能源产业近年迅猛发展&#xff0c;新能源企业凭借技术革新、政策支持与市场驱动实现快速增长&#xff0c;在产业链完备、技术领先、生产效能及成本控制等方面优势显著。面对国内外环境…

MySQL中的LIMIT与ORDER BY关键字详解

前言 众所周知&#xff0c;LIMIT和ORDER BY在数据库中&#xff0c;是两个非常关键并且经常一起使用的SQL语句部分&#xff0c;它们在数据处理和分页展示方面发挥着重要作用。 今天就结合工作中遇到的实际问题&#xff0c;回顾一下这块的知识点。同时希望这篇文章可以帮助到正…

ZXing.Net:一个开源条码生成和识别器,支持二维码、条形码等

推荐一个跨平台的非常流行的条码库&#xff0c;方便我们在.Net项目集成条码扫描和生成功能。 01 项目简介 ZXing.Net是ZXing的.Net版本的开源库。支持跨多个平台工作&#xff0c;包括 Windows、Linux 和 macOS&#xff0c;以及在 .NET Core 和 .NET Framework 上运行。 解码…

【数据结构】设有一带头结点的单链表,编程将链表颠倒过来。要求不用另外的数 组或结点完成。

编程题&#xff1a; 设有一带头结点的单链表&#xff0c;编程将链表颠倒过来。要求不用另外的数 组或结点完成。 分析&#xff1a; 该算法通过维护三个指针&#xff08;prev、curr 和 next&#xff09;逐步遍历单链表&#xff0c;实现链表的逆转。在遍历过程中&#xff0c;cur…

IDEA Cody 插件实现原理

近年来&#xff0c;智能编程助手 在开发者日常工作中变得越来越重要。IDEA Cody 插件是 JetBrains 生态中一个重要的插件&#xff0c;它可以帮助开发者 快速生成代码、自动补全、并提供智能提示&#xff0c;从而大大提升开发效率。今天我们将深入探讨 Cody 插件的实现原理&…

技术成神之路:设计模式(十四)享元模式

介绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构性设计模式&#xff0c;旨在通过共享对象来有效地支持大量细粒度的对象。 1.定义 享元模式通过将对象状态分为内部状态&#xff08;可以共享&#xff09;和外部状态&#xff08;不可共享&#xff09;&#xf…

AI免费UI页面生成

https://v0.dev/chat v0 - UI设计 cursor - 编写代码 参考&#xff1a;https://www.youtube.com/watch?vIyIVvAu1KZ4 界面和claude类似&#xff0c;右侧展示效果和代码 https://pagen.so/

【重学 MySQL】三十、数值类型的函数

【重学 MySQL】三十、数值类型的函数 基本函数角度与弧度互换函数三角函数指数与对数进制间的转换示例 基本函数 MySQL提供了一系列基本的数值函数&#xff0c;用于处理数学运算和数值转换。以下是一些常用的基本函数及其用法&#xff1a; 函数用法ABS(x)返回x的绝对值。SIGN…