news 2026/2/4 15:55:30

Appium+Python+pytest自动化测试框架的实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Appium+Python+pytest自动化测试框架的实战

本文主要介绍了Appium+Python+pytest自动化测试框架的实战,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

先简单介绍一下目录,再贴一些代码,代码里有注释

Basic目录下写的是一些公共的方法,Data目录下写的是测试数据,image存的是测试失败截图,Log日志文件,Page测试的定位元素,report测试报告,Test测试用例,pytest.ini是pytest启动配置文件,requirements.txt需要安装的py模块,run.py运行文件


Basic/base.py

里面封装了 一些方法,元素的点击,输入,查找,还有一些自己需要的公共方法也封装在里面,如果你们有别的需要可以自己封装调用

Basic/deiver.py
APP启动的前置条件,一个是普通的app,一个是微信公众号,配置微信公众号自动化测试和一般的APP是有点区别的,微信需要切换webview才能定位到公众号

from appium import webdriver def init_driver(): desired_caps = {} # 手机 系统信息 desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '9' # 设备号 desired_caps['deviceName'] = 'emulator-5554' # 包名 desired_caps['appPackage'] = '' # 启动名 desired_caps['appActivity'] = '' desired_caps['automationName'] = 'Uiautomator2' # 允许输入中文 desired_caps['unicodeKeyboard'] = True desired_caps['resetKeyboard'] = True desired_caps['autoGrantPermissions'] = True desired_caps['noReset'] = False # 手机驱动对象 driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps) return driver def driver_weixin(): desired_caps = {} # 手机 系统信息 desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '9' # 设备号 desired_caps['deviceName'] = '' # 包名 desired_caps['appPackage'] = 'com.tencent.mm' # 启动名 desired_caps['appActivity'] = '.ui.LauncherUI' # desired_caps['automationName'] = 'Uiautomator2' # 允许输入中文 desired_caps['unicodeKeyboard'] = True desired_caps['resetKeyboard'] = True desired_caps['noReset'] = True # desired_caps["newCommandTimeout"] = 30 # desired_caps['fullReset'] = 'false' # desired_caps['newCommandTimeout'] = 10 # desired_caps['recreateChromeDriverSessions'] = True desired_caps['chromeOptions'] = {'androidProcess': 'com.tencent.mm:tools'} # 手机驱动对象 driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps) return driver

Basic/get_data.py

这是获取测试数据的方法

import os import yaml def getData(funcname, file): PATH = os.getcwd() + os.sep with open(PATH + 'Data/' + file + '.yaml', 'r', encoding="utf8") as f: data = yaml.load(f, Loader=yaml.FullLoader) # 1 先将我们获取到的所有数据都存放在一个变量当中 tmpdata = data[funcname] # 2 所以此时我们需要使用循环走进它的内心。 res_arr = list() for value in tmpdata.values(): tmp_arr = list() for j in value.values(): tmp_arr.append(j) res_arr.append(tmp_arr) return res_arr

Basic/Log.py

日志文件,不多介绍

# -*- coding: utf-8 -*- """ 封装log方法 """ import logging import os import time LEVELS = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR, 'critical': logging.CRITICAL } logger = logging.getLogger() level = 'default' def create_file(filename): path = filename[0:filename.rfind('/')] if not os.path.isdir(path): os.makedirs(path) if not os.path.isfile(filename): fd = open(filename, mode='w', encoding='utf-8') fd.close() else: pass def set_handler(levels): if levels == 'error': logger.addHandler(MyLog.err_handler) logger.addHandler(MyLog.handler) def remove_handler(levels): if levels == 'error': logger.removeHandler(MyLog.err_handler) logger.removeHandler(MyLog.handler) def get_current_time(): return time.strftime(MyLog.date, time.localtime(time.time())) class MyLog: path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) log_file = path+'/Log/log.log' err_file = path+'/Log/err.log' logger.setLevel(LEVELS.get(level, logging.NOTSET)) create_file(log_file) create_file(err_file) date = '%Y-%m-%d %H:%M:%S' handler = logging.FileHandler(log_file, encoding='utf-8') err_handler = logging.FileHandler(err_file, encoding='utf-8') @staticmethod def debug(log_meg): set_handler('debug') logger.debug("[DEBUG " + get_current_time() + "]" + log_meg) remove_handler('debug') @staticmethod def info(log_meg): set_handler('info') logger.info("[INFO " + get_current_time() + "]" + log_meg) remove_handler('info') @staticmethod def warning(log_meg): set_handler('warning') logger.warning("[WARNING " + get_current_time() + "]" + log_meg) remove_handler('warning') @staticmethod def error(log_meg): set_handler('error') logger.error("[ERROR " + get_current_time() + "]" + log_meg) remove_handler('error') @staticmethod def critical(log_meg): set_handler('critical') logger.error("[CRITICAL " + get_current_time() + "]" + log_meg) remove_handler('critical') if __name__ == "__main__": MyLog.debug("This is debug message") MyLog.info("This is info message") MyLog.warning("This is warning message") MyLog.error("This is error") MyLog.critical("This is critical message")

AI写代码bash

Basic/Shell.py

执行shell语句方法

# -*- coding: utf-8 -*- # @Time : 2018/8/1 下午2:54 # @Author : WangJuan # @File : Shell.py """ 封装执行shell语句方法 """ import subprocess class Shell: @staticmethod def invoke(cmd): output, errors = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() o = output.decode("utf-8") return o

Page/page.py

class Page: def __init__(self, driver): self.driver = driver @property def initloginpage(self): return Login_Page(self.driver)

Test/test_login.py

登陆的测试用,我贴一条使用数据文件的用例

class Test_login: @pytest.mark.parametrize("args", getData("test_login_error", 'data_error_login')) def test_error_login(self, args): """错误登陆""" self.page.initloginpage.input_user(args[0]) self.page.initloginpage.input_pwd(args[1]) self.page.initloginpage.click_login() toast_status = self.page.initloginpage.is_toast_exist(args[2]) if toast_status == False: self.page.initpatientpage.take_screenShot() assert False

pytest.ini

pytest配置文件,注释的是启动失败重试3次,因为appium会因为一些不可控的原因失败,所有正式运行脚本的时候需要加上这个

[pytest] ;addopts = -s --html=report/report.html --reruns 3 addopts = -s --html=report/report.html testpaths = ./Test python_files = test_*.py python_classes = Test* python_functions = test_add_prescription_list requirements.txt 框架中需要的患教,直接pip install -r requirements.txt 安装就可以了,可能会失败,多试几次 ```python adbutils==0.3.4 allure-pytest==2.7.0 allure-python-commons==2.7.0 Appium-Python-Client==0.46 atomicwrites==1.3.0 attrs==19.1.0 certifi==2019.6.16 chardet==3.0.4 colorama==0.4.1 coverage==4.5.3 decorator==4.4.0 deprecation==2.0.6 docopt==0.6.2 enum34==1.1.6 facebook-wda==0.3.4 fire==0.1.3 humanize==0.5.1 idna==2.8 importlib-metadata==0.18 logzero==1.5.0 lxml==4.3.4 more-itertools==7.1.0 namedlist==1.7 packaging==19.0 Pillow==6.1.0 pluggy==0.12.0 progress==1.5 py==1.8.0 PyMySQL==0.9.3 pyparsing==2.4.0 pytest==5.0.0 pytest-cov==2.7.1 pytest-html==1.21.1 pytest-metadata==1.8.0 pytest-repeat==0.8.0 pytest-rerunfailures==7.0 PyYAML==5.1.1 requests==2.22.0 retry==0.9.2 selenium==3.141.0 six==1.12.0 tornado==6.0.3 uiautomator2==0.3.3 urllib3==1.25.3 wcwidth==0.1.7 weditor==0.2.3 whichcraft==0.6.0 zipp==0.5.1

​​​​​​​

到此这篇关于Appium+Python+pytest自动化测试框架的实战的文章就介绍到这了

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/4 10:41:28

降AI率+降重工具合集,学生必备

随着AI写作工具的普及,越来越多的大学生开始使用AI来辅助论文写作。根据最新数据显示,超过73%的大学生承认自己曾借助AI工具完成论文。然而,学术查重平台也在同步升级,对“AI率”检测愈发严格。许多高校已明确规定:AI率…

作者头像 李华
网站建设 2026/2/4 13:47:07

Qwen3-0.6B:6亿参数引爆轻量AI革命,重塑企业智能化格局

Qwen3-0.6B:6亿参数引爆轻量AI革命,重塑企业智能化格局 【免费下载链接】Qwen3-0.6B Qwen3 是 Qwen 系列中最新一代大型语言模型,提供全面的密集模型和混合专家 (MoE) 模型。Qwen3 基于丰富的训练经验,在推理、指令遵循、代理能力…

作者头像 李华
网站建设 2026/1/29 12:08:13

深入理解Android Handler机制:从原理到进阶实战

目录 引言 一、Handler四组件架构全景 1.1 核心组件关系图 1.2 各组件核心职责 1.3 工作原理源码解析 二、Handler基础实战案例 2.1 跨线程UI更新 2.2 延迟任务与定时任务 三、IdleHandler深度解析与实战 3.1 IdleHandler核心原理 3.2 IdleHandler源码分析 3.3 IdleHandler实战…

作者头像 李华
网站建设 2026/1/29 11:10:05

Groove音乐播放器完全指南:解锁专业级音乐体验

开启你的音乐之旅 🎵 【免费下载链接】Groove 项目地址: https://gitcode.com/gh_mirrors/gr/Groove Groove音乐播放器是一款功能全面的开源音乐软件,专为追求高品质音乐体验的用户设计。它巧妙地将本地音乐管理、在线音乐探索和个性化播放功能融…

作者头像 李华
网站建设 2026/2/3 20:53:54

Omega-AI:Java开发者的终极深度学习框架,快速构建智能应用

Omega-AI:Java开发者的终极深度学习框架,快速构建智能应用 【免费下载链接】omega-ai Omega-AI:基于java打造的深度学习框架,帮助你快速搭建神经网络,实现模型推理与训练,引擎支持自动求导,多线…

作者头像 李华