首页 > 其他分享 >如何用覆盖函数的方式,实现你自己的touch?

如何用覆盖函数的方式,实现你自己的touch?

时间:2024-04-11 10:57:48浏览次数:27  
标签:函数 覆盖 time airtest touch import

此文章来源于项目官方公众号:“AirtestProject”
版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途

1、前言

在使用Airtest进行日常测试工作中,我们有时候想针对某个接口进行功能增强,或者增加一些错误处理和重试机制,但是又不想直接修改Airtest源码,因为担心更新Airtest库就会覆盖掉源码的修改。

这个时候,我们更推荐大家使用python覆盖函数的方式处理,通过覆盖函数的方式改变函数的行为是一种常见的编程技巧,既能让我们的代码保持灵活性,又避免了直接修改源码库。

下文我们将一起来看下覆盖函数在Airtest框架下的应用小案例.。

2、示例

我们以覆盖Airtest里的touch接口为例,来一起体验下覆盖函数的魅力:

2.1 新建一个new_touch脚本文件并导入需要覆盖的函数

新建一个new_touch脚本文件,并将我们需要增强的函数或某个语句先导入并取一个与原函数不冲突的别名。

from airtest.core.api import touch as old_touch

这一行代码表示从 airtest.core.api 模块中导入了touch函数,并将其重命名为old_touch 。这样做的目的是保留原有的touch函数,以便在新函数中调用。

2.2 开始定义覆盖函数

在新建的**new_touch**文件下,可以正常调用旧函数并结合实际场景去增加所需要增强的功能,去实现想要达到的效果。

from airtest.core.api import *
from airtest.core.api import touch as old_touch

def touch(pic):

    try:
	#若打开App后是进入的学习积分界面,即可直接点击

        old_touch(pic)
        print("进入的是学习积分界面")

    except TargetNotFoundError:
	#若打开App后是进入的App首页界面,需要先点击积分

        print("进入的是首页界面")
        old_touch(Template(r"tpl1712044513750.png", record_pos=(0.267, -1.05), resolution=(1080, 2520)))
        
        print("现在进入了学习积分界面")
        
	#跳转到对应的学习积分界面后再进行点击
        old_touch(pic)

2.3 在脚本中导入新函数以覆盖旧函数

创建一个新的跑测脚本,并将new_touch文件放到与跑测脚本同一文件夹下,使用import导入new_touch文件的touch用法,就可以直接使用我们修改后的touch用法。

# -*- encoding=utf8 -*-
__author__ = "Airtest"

from airtest.core.api import *

from new_touch import touch

#打开进入学习强国App
start_app("cn.xuexi.android")


#尝试点击选读文章任务跳转
touch(Template(r"tpl1712044077691.png", target_pos=6, record_pos=(-0.006, 0.261), resolution=(1080, 2520)))

在需要使用新的touch函数的脚本中,首先从airtest.core.api导入所有内容,然后从定义了新touch函数的模块(这里该模块名为new_touch)导入新的touch函数。由于Python的名称解析是从左到右的,后导入的同名函数会覆盖先前导入的函数,因此这样做可以确保新的touch函数覆盖了原始的 touch 函数。

2.4 最终效果

2.5 覆盖函数的功能增强

在了解完一个简单的覆盖函数示例之后,我们可以再来看一个稍微复杂点的小案例,就是利用覆盖函数,给旧函数增加一些错误处理操作或者错误log记录等。依然以Airtest的 touch 接口为例:

参考代码如下:

在新的touch函数里,我们增加了一些错误记录,并截图错误场景,将报错抛出,在日常点击的时候可以更精准的去判断报错出现的场景以及原因。

from airtest.core.api import *
from airtest.core.api import touch as old_touch
import logging

# 初始化日志记录器
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
"""
param target: 点击目标,可以是图片(Template)或坐标。
param timeout: 超时时间,单位为秒。
param retry_interval: 重试间隔时间,单位为秒。
"""

def touch(target, timeout, retry_interval):

    start_time = time.time()  # 记录开始时间
    while True:
        try:
            # 尝试点击目标
            old_touch(target)
            logger.info(f"成功点击图片")
            break  # 点击成功则退出循环
            
        except TargetNotFoundError:
			#计算超时时间
            current_time = time.time()
            elapsed_time = current_time - start_time

            if elapsed_time > timeout:

                # 如果超时,则捕获异常并记录错误信息
                logger.error(f"在指定的超时时间 {timeout} 秒内未找到目标图片")

                # 捕获屏幕截图以供后续分析
                snapshot(filename=f"error_{current_time}.png")
                raise  # 重新抛出异常,或者可以选择其他的错误处理方式

            else:
                 # 没有超时,则等待一段时间后重试
                logger.info(f"未找到目标图片,{retry_interval} 秒后重试...")
                time.sleep(retry_interval)
                continue

        except Exception as e:
            # 捕获其他可能的异常,并记录
            current_time = time.time()
            logger.error(f"点击图片时发生未知错误: {e}")

            # 捕获屏幕截图以供后续分析
            snapshot(filename=f"error_{current_time}.png")
            raise  # 重新抛出异常,或者可以选择其他的错误处理方式

调用方式跟刚才简单的案例一样,从 enhanced_touch 文件中 import 新的touch进来,需要注意 importtouch 的语句一定放在 from airtest.core.api import * 之后,确保覆盖。

# -*- encoding=utf8 -*-
__author__ = "Airtest"

from airtest.core.api import *
from enhanced_touch import touch

auto_setup(__file__)

start_app("cn.xuexi.android")

#调用修改后的touch,并传入需要识别的图片、超时时间、重试间隔时间
touch(Template(r"tpl1712113066466.png", record_pos=(0.298, 0.285), resolution=(1080, 2520)), timeout=10, retry_interval=5)

3、小结

函数覆盖是一种强大的技术,可以在不改变原始代码的情况下调整、增强或替换现有功能。不过,这种技术也需要谨慎使用,因为它可能会导致代码的可读性和可维护性降低,尤其是在覆盖的函数逻辑变得复杂时。正确的文档记录和清晰的代码结构对于维护这种类型的代码至关重要。

我们的样例仅供参考,不一定适用于所有场合,同时也欢迎大家给我们投稿自己写的覆盖函数或封装函数,我们也会多多分享更多的相关的使用技巧。让我们一起努力,共同进步~


AirtestIDE下载:airtest.netease.com/
Airtest 教程官网:airtest.doc.io.netease.com/
搭建企业私有云服务:airlab.163.com/b2b

官方答疑 Q 群:526033840

标签:函数,覆盖,time,airtest,touch,import
From: https://www.cnblogs.com/AirtestProject/p/18128353

相关文章

  • 嵌入式之指针、数组、函数篇(三)
    三、指针、数组、函数1.什么是指针?指针其实也是个变量,只不过这个变量里面存储的是内存地址。2.什么是指针的类型?举个例子:int*a;指针类型为int*char*c;指针类型为char*3.什么是指针所指向类型举个例子:int*a;指针指向类型为intchar*c;指针指向类型为char注......
  • C++ 虚函数与纯虚函数
    C++中的虚函数(virtual)是可以被子类重写的成员函数而纯虚函数(purevirtual)是必须被抽象/基类中的定义的虚函数,必须被派生类实现virtualtypefunction(){}//虚函数virtualvoidfuntion1()=0//纯虚函数主要区别:实现虚函数有实现,而纯虚函数没有实现子类中虚函数可......
  • VUE - 使用h函数创建虚拟节点
    VUE-使用h函数创建虚拟节点 1. 如在 antd 的 notification 组件中使用 参考文档:https://1x.antdv.com/components/notification-cn/leth=this.$createElement;that.$notification.error({message:'上传提示',descrip......
  • 带有 self 和不带 self 定义的函数有着不同的用途和作用范围
    1.带有self的方法: -带有self的方法通常定义在类中,用于操作类的实例对象(即对象的实例属性和方法)。   -当定义类的方法时,第一个参数通常是self,它代表当前类的实例对象,用于访问类的属性和调用其他方法。   -在调用这类方法时,Python会自动将调用对象作为第一个参......
  • 【测试开发学习历程】python高阶函数
    目录1map()函数2reduce()函数3filter()函数4sorted()函数1map()函数map()函数语法:map(function,iterable)参数:function:函数iterable:一个或多个序列返回值:迭代器对象作用:map()是Python内置的高阶函数,它接收一个函数function和一个iterable,并通过把......
  • 使用 `omit` 函数移除敏感信息
    exportdefaultfunctionomit<Textendsobject,KextendskeyofT>(obj:T,fields:K[]|readonlyK[],):Omit<T,K>{constclone={...obj};if(Array.isArray(fields)){fields.forEach(key=>{deleteclone[key];......
  • 【异常】写了很多单元测试用例,但是Sonar上显示的单元测试覆盖率依旧为 0.0%
    一、异常内容写了很多单元测试用例,但是Sonar上显示的单元测试覆盖率依旧为0.0%二、异常说明在SonarQube中显示单元测试覆盖率为0%,通常意味着SonarQube没有正确地接收到测试覆盖率报告。三、异常解决要解决这个问题,您可以按照以下步骤操作:3.1确保测试覆盖率报告已......
  • Sort函数的使用
    std::sort函数是<algorithm>头文件中的一个模板函数,用于对容器中的元素进行排序。通常,std::sort函数需要三个参数:指向要排序序列的起始位置的迭代器。指向要排序序列的结束位置之后一个位置的迭代器。一个可选的比较函数或可调用对象,用于确定排序顺序。当你只传递两个参数给s......
  • 《C++程序设计》阅读笔记【7-堆和拷贝构造函数】
    ......
  • C语言: 字符串函数(下)
    片头在上一篇中,我们介绍了字符串函数。在这一篇章中,我们将继续学习字符串函数,准备好了吗?开始咯!1.strncpy函数1.1strncpy函数的用法strncpy是C语言中的一个字符串处理函数,它用于将一个字符串的一部分内容复制到另一个字符串中。其函数原型为:char*strncpy(char*dest......