pytest +uiautomator2+weditor app自动化从零开始

目录结构1.0
在这里插入图片描述
把设备连接单独移出去了
在这里插入图片描述
模块操作代码,有一些流程操作和断言方法

from devices import dv
from time import sleep
import random
from tool.jt import capture_screenshot


def initialization(func):
    def wrapper():
        sleep(1)
        dv.app_stop('com.visteon.txzing.accountcenter')
        dv.app_start('com.visteon.txzing.accountcenter')
        sleep(2)
        func()
    return wrapper


@initialization
def f1():
    '''1、打开账号切换,点击其他的账号,点击确认登录,点击取消'''
    dv(text='账号切换').click()
    dv.xpath(
        '//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/change_account_recycler"]/android.view.ViewGroup[2]').click()
    dv(text='确定').click()
    dv(text='取消').click()


@initialization
def f2():
    '''2、点击设置、点击退出登录、点击取消'''
    dv(text='设置').click()
    dv(text='退出登录').click()
    dv(text='取消').click()


@initialization
def f3():
    '''3、点击设置、点击用户协议,点击返回,点击隐私政策,点击返回,再次点击返回到个人中心主页面'''
    dv(text='设置').click()
    dv(text='用户协议').click()
    sleep(1.5)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/top_bar_back"]').click()
    dv(text='隐私政策').click()
    sleep(1.5)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/top_bar_back"]').click()
    sleep(1.5)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/top_bar_back"]').click()


@initialization
def f4():
    '''4、点击账号关联,点击高德地图绑定,点击确定'''
    dv(text='账号关联').click()
    try:
        dv.xpath('//*[@content-desc="绑定高德地图"]').click()
    except:
        dv.xpath('//*[@content-desc="绑定高德地图"]').click()
    dv(text='确定').click()


def f5():
    '''5、进入问题反馈,点击开始录音,5s内结束录音,重新开始录音,切换问题类别从第一个切到最后一个,然后提交,最后播放语音'''
    dv(text='问题反馈').click()
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    sleep(4)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    sleep(1)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    for i in ['多媒体', '导航', '蓝牙电话', '维保类', '设置', '其他']:
        dv(text=i).click()
        sleep(1)
    # 录音秒数随机
    sleep(random.randint(1, 80))
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    dv(text='提交').click()
    sleep(2)
    dv.xpath(
        '//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/mine_feedback_recyclerview"]/android.view.ViewGroup[1]/android.view.ViewGroup[1]').click()


def run():
    while True:
        try:
            f1()
            f2()
            f3()
            f5()
            f4()
        except Exception as e:
            capture_screenshot(e)
            print(f'报错了重新运行{e}')


# 通过获取文本来断言
b = '//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/mine_feedback_recyclerview"]/android.view.ViewGroup[1]/android.widget.TextView[1]'
a = dv.xpath(b).get_text()
print(a)

# 通过判断元素是否存在来断言
c = dv.xpath('//*[@text="2023/11/30 15:49"]').exists
print(c)

# 通过元素属性是否发生变化来进行断言
d = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]')
# 获取语音条初始状态的info信息
initial_info = d.info
d.click()
clicked_info = d.info
# 比较前后的info信息,找出差异数据
diff = {k: clicked_info[k] for k in clicked_info if clicked_info[k] != initial_info[k]}
print("前后的差异数据:", diff)
if len(diff) == 0:
    print('状态未发生变化')
else:
    print('断言成功')


if __name__ == '__main__':
    while True:
        run()

目录结构1.1
新增test_accountcenter.py编写测试用例
新增run.py执行pytest
新增pytest.ini配置文件
在这里插入图片描述
test_accountcenter.py
删除了3个场景,留下2个场景,每个场景加了2种断言方式f1(ex):f5(ex):,测试用例是test_zhanghao():test_luyin():,f1(ex):f5(ex):内部实现了断言并且返回结果

from devices import dv
from time import sleep
import random
from tool.jt import capture_screenshot
def f1(ex):
    '''1、打开账号切换,点击其他的账号,点击确认登录,点击取消'''
    dv.app_stop('com.visteon.txzing.accountcenter')
    dv.app_start('com.visteon.txzing.accountcenter')
    dv(text='账号切换').click()
    dv.xpath(
        '//*[@resource-id="com.visteon.txzing.accountcenter:id/change_account_recycler"]/android.view.ViewGroup[2]').click()
    dv(text='确定').click()
    text= dv(text='请在互联小程序确认登录').get_text()
    if not dv.xpath('//*[@resource-id="com.visteon.txzing.accountcenter:id/loading_cancel"]').exists:
        return False
    ass =ex==text
    return ass



def f5(ex):
    '''5、进入问题反馈,点击开始录音,5s内结束录音,重新开始录音,切换问题类别从第一个切到最后一个,然后提交,最后播放语音'''
    dv.app_stop('com.visteon.txzing.accountcenter')
    dv.app_start('com.xxxxxxx.xxxxxxx.accountcenter')
    dv(text='问题反馈').click()
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    sleep(4)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    sleep(1)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    lb=['多媒体', '导航', '蓝牙电话', '维保类', '其他', '设置']
    for i in lb:
        dv(text=i).click()
        sleep(1)
    # 录音秒数随机
    sleep(random.randint(5, 10))
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    dv(text='提交').click()
    ass= '设置'==ex
    '''元素信息变化'''
    d = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]')
    # 获取语音条初始状态的info信息
    initial_info = d.info
    d.click()
    clicked_info = d.info
    # 比较前后的info信息,找出差异数据
    diff = {k: clicked_info[k] for k in clicked_info if clicked_info[k] != initial_info[k]}
    print("前后的差异数据:", diff)
    if len(diff) == 0:
        return False

    sleep(2)
    dv.xpath(
        '//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/mine_feedback_recyclerview"]/android.view.ViewGroup[1]/android.view.ViewGroup[1]').click()
    return ass

def test_zhanghao():
    f1('请在互联小程序确认登录')
    assert True

def test_luyin():
    assert f5('设置')


run.py文件
运行文件,暂未配置参数
```python
import pytest
pytest.main([])

pytest.ini文件
配置了下报告的一些参数

[pytest]
addopts = -s --alluredir ./report/data

目录结构1.2
新增断言方法文件
在这里插入图片描述
assertion.py文件
首先dw()判断元素是否存在,不存在不需要进行后续操作,element_existence方法适用于断言元素是否存在,element_info_existence方式适用于判断元素在点击后是否发生了属性变化来断言,element_text_existence适用于判断元素文本和预期结果是否一致

from time import sleep
def dw(dv, element, positioning_method):
    '''
    :param dv: 设备
    :param element: 定位元素
    :param positioning_method: 定位方式
    :return: 判定元素是否存在,存在则返回元素对象用于后续操作
    '''
    if positioning_method == 'xpath':
        if not dv.xpath(element).exists:
            print('断言元素不存在,直接判定断言失败')
            return False
        return dv.xpath(element)
    if positioning_method == 'text':
        if not dv(text=element).exists:
            print('断言元素不存在,直接判定断言失败')
            return False
        return dv(text=element)


def element_existence(dv, element, positioning_method):
    '''
      :param dv: 设备
      :param element: 定位元素
      :param positioning_method: 定位方式
      :return:通过元素是否存在来断言
      '''
    element_ = dw(dv, element, positioning_method)
    if not element_:
        return False
    return True


def element_info_existence(dv, element, positioning_method):
    '''
      :param dv: 设备
      :param element: 定位元素
      :param positioning_method: 定位方式
      :return:通过元素属性是否发生变化来断言
      '''
    if not dw(dv, element, positioning_method):
        return False
    else:
        el = dw(dv, element, positioning_method)
        initial_info = el.info
        el.click()
        sleep(1)
        clicked_info = el.info
        diff = {k: clicked_info[k] for k in clicked_info if clicked_info[k] != initial_info[k]}
        print(f'元素差异字段{diff}')
        if len(diff) == 0:
            print('元素属性未发生变化,断言失败')
            return False
        return True


def element_text_existence(dv, element, positioning_method, text):
    '''

    :param dv: 设备
    :param element: 定位元素
    :param positioning_method: 定位方式
    :param text: 预期结果文本
    :return: 通过文本是否相等来断言
    '''
    if not dw(dv, element, positioning_method):
        return False
    else:
        el = dw(dv, element, positioning_method)
        el_text=el.get_text()
        if not text ==el_text :
            print(f'文本不匹配预期结果{text},实际结果{el_text}')
            return False
        else:
            return True


目录结构1.3
新增case文件夹
case-fun 以每个模块一个文件,里面包含多个场景操作,和场景断言
case-test_case 以每个模块一个文件,和fun文件夹文件一一对应,负责执行模块的每个场景
在这里插入图片描述
accountcenter.py文件

import random
from time import sleep
from tool.assertion import element_existence, element_info_existence, element_text_existence


def f1(dv):
    '''1、打开账号切换,点击其他的账号,点击确认登录'''
    dv.app_stop('com.visteon.txzing.accountcenter')
    dv.app_start('com.visteon.txzing.accountcenter')
    dv(text='账号切换').click()
    dv.xpath(
        '//*[@resource-id="com.visteon.txzing.accountcenter:id/change_account_recycler"]/android.view.ViewGroup[2]').click()
    dv(text='确定').click()

    '''断言'''
    return element_existence(dv, '取消', 'text')


def f2(dv):
    dv.app_stop('com.xxxxxxx.xxxxxxx.accountcenter')
    dv.app_start('com.xxxxxxx.xxxxxxx.accountcenter')
    '''2、点击设置、点击退出登录、点击取消'''
    dv(text='设置').click()
    dv(text='退出登录').click()
    dv(text='取消').click()

    return element_text_existence(dv, '退出登录', 'text', '退出登录')


def f5(dv):
    '''5、进入问题反馈,点击开始录音,5s内结束录音,重新开始录音,切换问题类别从第一个切到最后一个,然后提交,最后播放语音'''
    dv.app_stop('com.xxxxxxx.xxxxxxx.accountcenter')
    dv.app_start('com.xxxxxxx.xxxxxxx.accountcenter')
    dv(text='问题反馈').click()
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    sleep(2)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    sleep(1)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    lb = ['多媒体', '导航', '蓝牙电话', '维保类', '其他', '设置']
    for i in lb:
        dv(text=i).click()
        sleep(1)
    # 录音秒数随机
    sleep(random.randint(5, 10))
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_start_record"]').click()
    dv(text='提交').click()
    sleep(2)
    dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]').click()  # 点击语音条
    '''断言'''
    return element_info_existence(dv,
                                  '//*[@resource-id="com.xxxxxxx.xxxxxxx.accountcenter:id/feedback_record_bar_time"]',
                                  'xpath')

test_accountcenter.py文件

from case.fun.accountcenter import f1, f2, f5
from devices import dv
def test_f1():
    assert f1(dv)
def test_f2():
    assert f2(dv)
def test_f5():
    assert f5(dv)

familytime.py

import random
from time import sleep
from devices import dv
from tool.assertion import element_existence, element_info_existence, element_text_existence

'''这些是通过观察元素属性观察得出的结论,这些是通用值'''


def tu(number):
    '''家人时光每个图片定位'''
    tu = dv.xpath(
        f'//*[@resource-id="com.visteon.txzing.familytime:id/recycler_view"]/android.view.ViewGroup[{number}]/android.widget.ImageView[1]')
    return tu


# 设为按钮
set_as = dv(text='设为')
# 设置壁纸
set_wallpaper = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_wallpaper"]')
# 设置屏保
set_screensaver = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/check_screensaver"]')
# 设为按钮
confirm = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_allow"]')
# 取消按钮
cancel = dv.xpath('//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/btn_normal_cancel"]')


def set_s_w():
    dv.app_stop('com.xxxxxxx.xxxxxxx.familytime')
    dv.app_start('com.xxxxxxx.xxxxxxx.familytime')

    tu(1).click()
    set_as.click()
    set_wallpaper.click()
    set_screensaver.click()
    confirm.click()
    # 多个断言处理
    ass_1 = element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_message"]', 'xpath',
                                   '壁纸、屏保设置成功')
    ass_2 = element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_label"]', 'xpath',
                                   '壁纸 屏保')
    ass_list = [ass_1, ass_2]
    for i in ass_list:
        if not i:
            print(f'断言{i}失败')
            return False
    return True


def cancel_s_w():
    dv.app_stop('com.xxxxxxx.xxxxxxx.familytime')
    dv.app_start('com.xxxxxxx.xxxxxxx.familytime')
    tu(1).click()
    set_as.click()
    set_wallpaper.click()
    set_screensaver.click()
    confirm.click()
    return element_text_existence(dv, '//*[@resource-id="com.xxxxxxx.xxxxxxx.familytime:id/tv_message"]', 'xpath',
                                  '壁纸、屏保取消成功')

test_familytime.py

from case.fun.familytime import set_s_w, cancel_s_w
from devices import dv
from time import sleep
def test_set_s_w():
    set_s_w()
def test_cancel_s_w():
    cancel_s_w()

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

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

相关文章

使用SLS日志服务采集Kong网关的日志

一、阿里云SLS 官方的接入文档已比较丰富了,本文不意重复说明此事。 站在使用的角度,以采集Kong的日志为示例,说明我们应该如何治理日志。 说白了,本文是想给你怎么省钱作一个建议,希望不会让你公司也“降本增笑”。…

MYSQL主从复制配置指引

MYSQL主从复制配置指引 1.前期准备 部署完主备数据库,初始化主备库表结构和数据。 2. 主库配置修改 修改主库配置文件etc/my.cnf,新增以下配置: #服务器 id,需唯一 server-id 1 #二进制文件存放路径 log-bin mysql-bin …

使用 HTML 地标角色提高可访问性

请务必确保所有用户都可以访问您的网站,包括使用屏幕阅读器等辅助技术的用户。 一种方法是使用 ARIA 地标角色来帮助屏幕阅读器用户轻松浏览您的网站。使用地标角色还有其他好处,例如改进 HTML 的语义并更轻松地设置网站样式。在这篇博文中,我…

【C语言】7-32 刮刮彩票 分数 20

7-32 刮刮彩票 分数 20 全屏浏览题目 切换布局 作者 DAI, Longao 单位 杭州百腾教育科技有限公司 “刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示: 每次游戏玩家会拿到一张彩票,上面会有 9 个数字,分别为数字 1 到数字 9&#xf…

Ubuntu18安装(重启黑屏问题)

1. F10 进入bios,选择u盘里的ubuntu镜像 2.进入使用ubuntu,下载 3.重启,esc 4.ubuntu 安e进入 5. nomodeset() F10 保存启动 6. 7.没有网 手机usb提供网络 下载有限网卡驱动

vue使用甘特图dhtmlxgantt + gantt.addTaskLayer

效果图: 甘特图 官网地址 gantt安装与使用 vue版---部分功能收费 安装gantt 或 引入文件 npm install dhtmlx-gantt -save或import gantt from "/public/static/dhtmlxgantt/dhtmlxgantt.js"; import "/public/static/dhtmlxgantt/locale/local…

为“异常”努力是值得的

异常是OO语言处理错误的方式,在C中,鼓励使用异常。侯捷再书中谈起异常,“十年前撰写“未将异常考虑在内的”函数是为一种美好实践,而今我们致力于写出“异常安全码”。”可见异常安全的重要。 说起异常安全,首先就要是异常的出现…

MOS管防护电路解析

功率MOS管自身拥有众多优点,但是MOS管具有较脆弱的承受短时过载能力,特别是在高频的应用场合,所以在应用功率MOS管对必须为其设计合理的保护电路来提高器件的可靠性。 功率MOS管保护电路主要有以下几个方面: 1)防止栅…

苹果 macOS 14.1.2 正式发布 更新了哪些内容?

苹果今日向 Mac 电脑用户推送了 macOS 14.1.2 更新(内部版本号:23B92 | 23B2091),本次更新距离上次发布隔了 28 天。 需要注意的是,因苹果各区域节点服务器配置缓存问题,可能有些地方探测到升级更新的时间略…

销售技巧培训之女装销售技巧

销售技巧培训之女装销售技巧 一、了解目标客户 在销售女装时,了解目标客户是非常重要的。不同年龄段、不同职业、不同收入的女性对女装的需求和偏好都不同。因此,在销售女装时,需要先了解目标客户的特点和需求,以便更好地推荐适…

《opencv实用探索·十四》VideoCapture播放视频和视像头调用

1、VideoCapture播放视频 #include <opencv2/opencv.hpp> #include <iostream>using namespace std; using namespace cv;int main() {// 定义相关VideoCapture对象VideoCapture capture;// 打开视频文件capture.open("1.avi");// 判断视频流读取是否正…

OpenCL学习笔记(一)开发环境搭建(win10+vs2019)

前言 异构编程开发&#xff0c;在高性能编程中有重要的&#xff0c;笔者本次只简单介绍下&#xff0c;如何搭建简单的开发环境&#xff0c;可以供有需要的小伙伴们开发测试使用 一、获取opencl的sdk库 1.使用cuda库 若本机有Nvidia的显卡&#xff0c;在安装cuda库后&#x…

spring boot学习第五篇:spring boot与JPA结合

1、准备表&#xff0c;创建表语句如下 CREATE TABLE girl (id int(11) NOT NULL AUTO_INCREMENT,cup_Size varchar(100) COLLATE utf8mb4_bin DEFAULT NULL,age int(11) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT4 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4…

《ReactJS实践入门》:引领JavaScript前端开发的革新之旅

在当今的软件开发世界中&#xff0c;ReactJS无疑是最为引人注目的JavaScript库之一。对于初学者来说&#xff0c;如何深入理解并掌握这一强大的前端工具&#xff0c;进而应用到实际开发中&#xff0c;一直是他们所面临的问题。而《ReactJS实践入门》一书&#xff0c;正是为了解…

西部再添“芯”增长极 | 海辰储能重庆基地正式投产

12月7日&#xff0c;海辰储能重庆基地一期一阶段项目投产仪式在重庆铜梁举行。此次重庆基地项目的投产&#xff0c;是海辰储能实施三大基地协同发展战略的重要里程碑&#xff0c;将进一步整合内部资源、发挥规模化生产优势、完善产业链布局&#xff0c;成为海辰储能持续迈向高质…

第二十一章

这一章 基本分为三个部分 网络基础概念和TCP,UDP这三个部分主要如下&#xff1a; 计算机网络实现了堕胎计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是再已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#xff0c;相互…

如何切换用户和更改用户密码

https://blog.csdn.net/u012759006/article/details/89681615 https://blog.csdn.net/Z_CAIGOU/article/details/120925716 1、sudo su 切换到root用户 2、passwd 用户名 之后输入你修改后的密码两次&#xff0c;成功。 文章知识点与官方知识档案匹配&#xff0c;可 一般情…

DDD架构思想专栏一《初识领域驱动设计DDD落地》

引言 最近准备给自己之前写的项目做重构&#xff0c;这是一个单体架构的小项目&#xff0c;后端采用的是最常见的三层架构。因为项目比较简单&#xff0c;其实采用三层架构就完全够了。但是呢&#xff0c;小编最近在做DDD架构的项目&#xff0c;于是就先拿之前写的一个老项目试…

【ET8】1.ET8入门-运行指南

主要学习网址 论坛地址为&#xff1a;https://et-framework.cn Git地址为&#xff1a;GitHub - egametang/ET: Unity3D Client And C# Server Framework 官方QQ群 : 474643097 项目检出 检出项目切换到release8.0分支 GitHub地址&#xff1a;GitHub - egametang/ET: Unity…

2023-12-08面试

1、自我介绍 面试官你好&#xff0c;我叫平明博&#xff0c;来自河南郑州&#xff0c;19年毕业&#xff0c;所学专业软件工程&#xff0c;之前任职于南京华苏科技&#xff0c;担任开发工程师一职&#xff0c;在职期间主要对省间现货相关项目进行研发&#xff0c;核心就是从多平…