使用 Pytest 运行 yaml 文件来驱动 Appium 自动化测试

目录

前言:

获取 yaml 文件

YamlTest 测试类

Appium 初始化

Pytest 测试类

自定义 runtest demo:

自定义错误输出

Yaml 使用方式规则


前言:

使用Pytest来运行yaml文件来驱动Appium自动化测试是一种方便且灵活的方法。通过将测试数据和测试逻辑分离,您可以更轻松地管理和扩展测试用例。

本文主要介绍一下 pytest hook 方法是怎么运行 yaml 文件做测试的 (喜欢其他方式也可以用 xlsx,sql 等),怎么与 Appium 结合,来驱动 Appium 做自动化测试。

该运行方式参照 pytest --doctest 参数运行的方法, 想深入了解的同学可以查看 _pytest/doctest.py 源码

获取 yaml 文件

使用 pytest_collect_file 钩子函数,在脚本运行之前过滤 .yml 文件

def pytest_collect_file(parent, path):# 获取文件.yml 文件if path.ext == ".yml" and path.basename.startswith("test"):return YamlFile(path, parent)

读取 yml 转成 json 移交至 YamlTest 类

class YamlFile(pytest.File):# 读取文件内容def collect(self):import yamlraw = yaml.safe_load(self.fspath.open(encoding='utf-8'))for name, values in raw.items():yield YamlTest(name, self, values)

YamlTest 测试类

下面就是测试类了,这里我们 Appium 还是使用单例初始化,方便所有测试用例继承一个 session

Appium 初始化

class Singleton(object):"""单例 ElementActions 为自己封装操作类"""Action = Nonedef __new__(cls, *args, **kw):if not hasattr(cls, '_instance'):desired_caps={}host = "http://localhost:4723/wd/hub"driver = webdriver.Remote(host, desired_caps)Action = ElementActions(driver, desired_caps)orig = super(Singleton, cls)cls._instance = orig.__new__(cls, *args, **kw)cls._instance.Action = Actionreturn cls._instanceclass DriverClient(Singleton):pass

Pytest 测试类

测试类初始化,这里要说一下,测试类一定要继承 pytest.Item 方法

class YamlTest(pytest.Item):def __init__(self, name, parent, values):super(YamlTest, self).__init__(name, parent)self.values = valuesself.Action = DriverClient().Action # 初始化 Appiumself.locator = None

为了减少代码的逻辑,取出来的 yaml json 字符串怎么可以直接转化成可运行方法呢?

这里就要说到 class 的 _getattribute_ 内建属性的用法,下面举个简单例子

class TestExample:def test1(self):print('test1')>>> TestExample().__getattribute__('test1')()
test1

现在我们就能直接读取 yaml 文件中的 method 字符串直接转化成 Appium api 运行了(method 对应自己封装或 Appium api 的方法)

自定义 runtest demo:

class YamlTest(pytest.Item):def __init__(self, name, parent, values):super(YamlTest, self).__init__(name, parent)self.values = valuesself.Action = DriverClient().Actionself.locator = Nonedef runtest(self):# 运行用例for self.locator in self.values:self.locator['time'] = 5if self.locator.get('element'):# 需要接收参数response = self.Action.__getattribute__(self.locator.get('method'))(self.locator)else:# 不需要参数response = self.Action.__getattribute__(self.locator.get('method'))()self.assert_response(response, self.locator)

这里将 Appium api 基本操作封装成了两类:

  • 需要接收元素的参数,例如:点击,查找,输入等
  • 不需要接收元素参数,例如:重启,滑动等

自定义错误输出

def repr_failure(self, excinfo):"""自定义报错信息,如果没有定义则会默认打印错误堆栈信息,因为比较乱,所以这里自定义一下 """if isinstance(excinfo.value, Exception):return '测试用例名称:{} \n' \'步骤输入参数:{} \n' \'数据:{}'.format(self.name, self.locator, excinfo.value.args)def reportinfo(self):return self.fspath, 0, "CaseName: %s" % self.name

下面就是完整的测试类了

class YamlTest(pytest.Item):def __init__(self, name, parent, values):super(YamlTest, self).__init__(name, parent)self.values = valuesself.Action = DriverClient().Actionself.locator = Nonedef runtest(self):# 运行用例for self.locator in self.values:self.locator['time'] = 5is_displayed = Trueif not self.locator.get('is_displayed'):is_displayed = False if str(self.locator.get('is_displayed')).lower() == 'false' else Truetry:if self.locator.get('element'):response = self.Action.__getattribute__(self.locator.get('method'))(yamldict(self.locator))else:response = self.Action.__getattribute__(self.locator.get('method'))()self.assert_response(response, self.locator)except Exception as E:if is_displayed:raise Epassdef repr_failure(self, excinfo):"""自定义报错信息,如果没有定义则会打印堆栈错误信息,调试时可以注释该函数,便于问题查找 """if isinstance(excinfo.value, Exception):return '测试类名称:{} \n' \'输入参数:{} \n' \'错误信息:{}'.format(self.name, self.locator, excinfo.value.args)def assert_response(self, response, locator):if locator.get('assert_text'):assert locator['assert_text'] in responseelif locator.get('assert_element'):assert responsedef reportinfo(self):return self.fspath, 0, "CaseName: %s" % self.name

这里我们主体 Pytest+yaml 测试框架就构建完成了,当然还有各种异常的捕获等钩子函数,自己封装的 Appium api 方法等,上篇文章讲过了,这里就不赘述了,自行选择添加更多功能

Yaml 使用方式规则

因为我们上面将接收方法分成了需要 element 参数和不需要 element 参数两类所以 yaml 格式如下

test_index:-method: launchApp # 启动 APP-method: 方法名称 例如:click (必填)element: 查找元素id,class等 (选填,配合 method 如需要点击元素,查找元素等必填)type: 元素类型 id,xpath,class  name,accessibility id (选填,会自动识别,如识别错误则自行填写)name: 测试步骤的名称 例如:点击搜索按钮 (选填)text: 需要输入或者查找的文本 (选填,配合部分 method 使用)time: 查找该元素需要的时间,默认 5s (选填)index: 页面有多个id,class时,不为空则查找元素数组下标 (选填)is_displayed: 默认 True ,当为 False 时元素未找到也不会抛异常(选填)

咱们用微博做个 demo 测试一下

test_index:-method: launchApp # 重启 APP-method: clickelement: click_ad_skipname: 广告跳过按钮is_displayed: False-method: clickelement: 发现name: 导航发现按钮-method: sleepelement: 3-method: set_textelement: com.sina.weibo:id/tv_search_keywordtext: testerhomename: 搜索输入框-method: set_keycode_enter-method: screenshot_elementelement: //*[@resource-id="com.sina.weibo:id/lv_content"]/android.widget.RelativeLayout[1]name: 搜索内容截图

运行用例

pytest -v ./test_case/test_ranking.yml --alluredir /report/test

或者直接运行文件目录

使用方法和基本 pytest 用法没有太大区别

pytest -v ./test_case --alluredir /report/test

来查看下运行结果:

 

  作为一位过来人也是希望大家少走一些弯路

在这里我给大家分享一些自动化测试前进之路的必须品,希望能对你带来帮助。

(WEB自动化测试、app自动化测试、接口自动化测试、持续集成、自动化测试开发、大厂面试真题、简历模板等等)

相信能使你更好的进步!

点击下方小卡片

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp:针对与富文本解析的几种方法

第一章、富文本的解析方法 1.1 uniapp自带组件&#xff1a;rich-text <rich-text :nodes"nodes"></rich-text> 1.2 v-html <view v-html"item.content"></view> 1.3 uview组件&#xff1a;u-parse <u-parse :content&quo…

Linux·从 URL 输入到页面展现到底发生什么?

打开浏览器从输入网址到网页呈现在大家面前&#xff0c;背后到底发生了什么&#xff1f;经历怎么样的一个过程&#xff1f;先给大家来张总体流程图&#xff0c;具体步骤请看下文分解&#xff01; 总体来说分为以下几个过程: DNS 解析:将域名解析成 IP 地址TCP 连接&#xff1a…

Zoho Projects:Jira的理想替代品,让项目管理更高效

在软件开发生命周期中&#xff0c;项目管理一直是一个非常重要的环节。为了更好地协作、追踪项目的进程和管理任务&#xff0c;许多公司选择了Jira这款著名的项目管理工具&#xff0c;它是个非常强大的工具&#xff0c;但同时也有非常明显的缺点。今天&#xff0c;我们将向大家…

ChatGLM-6B+LangChain实战

目标&#xff1a;原始使用ChatGLM-6B可接受的文字长度有限&#xff0c;打算结合LangChain实现长文本生成摘要. 方法&#xff1a; step1&#xff1a;自定义一个GLM继承LangChain中的langchain.llms.base.LLM&#xff0c;load自己的模型. step2&#xff1a;使用LangChain的mapred…

帆软 FineReport/FineBI channel反序列化漏洞分析

事件背景 热点漏洞 漏洞说明 1. 漏洞原理&#xff1a;FineReport/FineBI channel接口能接受序列化数据并对其进行反序列化。配合帆软内置CB链会导致任意代码执行。 2. 组件描述&#xff1a;FineReport是一款企业级报表设计和数据分析工具&#xff0c;它提供了丰富多样的组件…

Vue+axios 使用CancelToken多次发送请求取消前面所有正在pendding的请求

需求&#xff1a; 项目中 折线图数据是循环调用的&#xff0c;此时勾选一个设备&#xff0c; 会出现多条线。 原因 折线图数据一进来接口循环在调用&#xff0c;勾选设备时&#xff0c;循环调用的接口有的处于pedding状态 &#xff0c;有的还在加载中&#xff0c;这就导致勾…

Maven 继承、聚合、属性

文章目录 一、继承1.1. 概念1.2. 语法1.3. 示例1.4. 其他常见使用 二、聚合2.1. 概念2.2. 示例 三、属性3.1. Java 系统属性3.2.系统环境变量属性3.3.Maven 内置属性 一、继承 1.1. 概念 当项目较大&#xff0c;为了便于开发和管理&#xff0c;经常需要将工程划分成多个 Maven…

奇迹MU架设教程:SQL Server 2008数据库的安装教程

不管是搭建什么游戏&#xff0c;都是有数据库的&#xff0c;奇迹MU用的是SQL 数据库&#xff0c;根据服务器系统选择SQL server版本&#xff0c;我比较喜欢用Windows server 2008R2系统&#xff0c;所以我安装的是SQL server 2008。作为架设奇迹很重要的数据库程序&#xff0c;…

Day13 02-Linux常用命令汇总

文章目录 第三章 Linux的常用命令【重要】3.1 命令格式的说明3.2 帮助命令3.2.1 man3.2.2 help 3.3 文件处理命令3.3.1 cd3.3.2 ls3.3.3 pwd3.3.4 mkdir3.3.5 touch3.3.6 echo3.3.7 cp3.3.8 mv3.3.9 rm3.3.10 vi编辑器3.3.11 ln 3.4 查看命令3.4.1 cat3.4.2 more3.4.3 head3.4.…

【Linux】进程概念

【Linux】进程概念 文章目录 【Linux】进程概念1、冯诺依曼体系结构2、操作系统2.1 概念2.2 设计OS的目的2.3 定位2.4 管理2.5 系统调用和库函数概念 3、进程3.1 基本概念3.2 描述进程—PCB3.3 组织进程3.4 查看进程3.5 获取进程标示符3.6 创建进程-fork初识3.7 进程状态3.7.1 …

ADC 的初识

ADC介绍 Q: ADC是什么&#xff1f; A: 全称&#xff1a;Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 ADC的性能指标 量程&#xff1a;能测量的电压范围分辨率&#xff1a;ADC能辨别的最小模拟量&#xff0c;通常以输出二进制数的位数表示&#xff0c;比如&am…

分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测,含混淆矩阵图、分类图)

分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测&#xff0c;含混淆矩阵图、分类图) 目录 分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测&#xff0c;含混淆矩阵图、分类图…