自动化测试:web+app端在工作中的具体实现

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

自动化测试:web端修改客户端配置,客户端查看配置是否生效

一、测试环境

1、代码编辑器使用Pycharm,编程语言选择Python,web自动化测试工具选择python第三方库playwright,客户端测试工具选择appium
2、项目架构:web端+app端
3、测试用例管理方法:Pytest
4、python及第三方库版本:python:3.11 playwright:1.57.0 pytest:8.3.3 selenium:4.33 appium-python-client:5.1.1
5、appium server:v2.18.0

二、使用步骤

1.Pycharm中文件脚本目录

1、新建python软件包:tests用来存放测试文件
用pytest整合测试用例所以测试文件以test_开头,比如test_patientscreen.py
2、setting软件包:用来存放测试中用到的配置信息,比如web端登录的用户名密码、要上传的文件、延时时间
都放在setting下面方便自定义配置后期维护,而且python在导入这些setting时很方便能够自动查找。
3、pages软件包:使用PO模式进行web端测试时会用到。PO模式我的理解是将在本次测试中经常用到的界面操作根据当前页面来封装。
比如:一个数据查询页面。
有输入关键词、点击搜索、翻页、拉动进度条…
这些操作都是这个页面下的,就可以把这个界面封装成一个类,这些操作都是这个类下的操作函数
因为对web端操作不可避免要经常在各个界面间来回切换。
当下一次切换到这个数据查询界面时就可以直接调用类中的操作函数。比较方便。
4、log文件夹
放日志的,当有多个测试用例时用日志记录操作步骤和捕获错误是个好办法。
工具是python的logging库

2.关键的对象

1、Browser
scope规划了生成器的生命范围

@pytest.fixture(scope="session")defbrowser()->Browser: playwright = sync_playwright().start() browser = playwright.chromium.launch(headless=False,slow_mo=30000)yield browser browser.close() playwright.stop()

2、page

@pytest.fixture(scope="class")defpage(browser:Browser)-> Page: context = browser.new_context() page = context.new_page()yield page page.close() context.close()

这里装饰器说明了page生成器的生命范围是class,所以在第一次调用此生成器的测试类中page是可以延续的,即第一个测试用例可能需要先进行登录操作,但是后续的测试函数直接从上一个测试结束时界面状态开始就可以
3、控制app的driver
scope=“class”,appium控制设备在第一次调用driver的class中是连续的,执行完第一个测试用例后在执行第二个之前不会重启app。

@pytest.fixture(scope='class')defcreate_driver(): desired_cap ={"platformName":"Android","platformVersion":"6",# 建议移除,除非必要,Appium会自动检测"deviceName":"设备名称",# 可改为通用名称"udid":"udid",# 关键:使用udid指定你的设备"appPackage":"app名","appActivity":"初始化界面app活动名","automationName":"UiAutomator2","noReset":True,"newCommandTimeout":900,"autoGrantPermissions":True,"unicodeKeyboard":True,"resetKeyboard":True} options = AppiumOptions() options.load_capabilities(desired_cap) driver =Nonetry: driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", options=options) driver.implicitly_wait(30)print("驱动初始化成功,设备已连接")yield driver # 将driver提供给外部使用finally:if driver: driver.quit()print("驱动已关闭")

4、日志生成器
调用logging模块后声明日志工具

@pytest.fixture(scope="session")deflogger(): logger = logging.getLogger("日志")# 设置日志记录器级别 logger.setLevel("DEBUG")# 日志文件夹位置 log_dir ="./log"# 判断日志文件夹是否存在,不存在生成一个ifnot os.path.exists(log_dir): os.makedirs(log_dir)# 日志记录位置 log_file = os.path.join(log_dir,'log.txt')# log.txt文件名要存在不然写不进去# 添加日志处理器 log_handler = logging.handlers.RotatingFileHandler(log_file, mode='w', encoding='utf-8')# 日志固定输出格式 log_format ="%(asctime)s-%(levelname)s-%(process)d-%(message)s"# 创建格式化器 fmt = logging.Formatter(fmt=log_format) log_handler.setFormatter(fmt)# 将日志处理器添加到日志记录器中 logger.addHandler(log_handler)yield logger print("销毁日志记录器")

有了这个日志工具后,在测试用例文件中要打印什么直接logger.info(“”)或者logger.error(“”)


3、PO模式具体使用

在pages软件包中添加py文件login.py

from playwright.sync_api import Page classPatientScreen:def__init__(self,page:Page): self.page = page defnavigate(self): self.page.get_by_text() self.page.get_by_role()...

类PatientScreen是封装的一个页面,__init__方法中声明此类的属性page

def__init____(self,page:Page):#page:Page是表明page参数是Page类型,Page从playwright.sync_api中导入了

关于这个页面下的操作如何写,推荐使用playwright自带的codegen录制工具,能自动生成操作相应的代码,很方便(大拇指)

playwright codegen "http://..."

在测试文件py中如何调用呢?

classTestPatientScreen:deftest_templatecolor(self,page,create_driver,logger): logger.info("case1:测试一览表背景颜色切换") login_page = WebLogin(page) patientscreen_page = PatientScreen(page)``` 

声明测试类后,在测试函数中可以直接调用在common中声明的生成器page
然后声明一个PO模式中类的对象作为我们要操作的对象
比如:
login_page是登录界面的可以执行类中动作的对象

4、总结一下本次写appium定位元素时遇到的新的方法

1、遇到一个在web端上传图片后验证app端是否正确上传了的测试点
问了一下ds,方法还是不错的,还是要感谢python丰富的第三方库
先获取设备上的图片:

logo = create_driver.find_element(By.XPATH,'/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.FrameLayout[1]/android.widget.LinearLayout/android.widget.ImageView') screenshot_bytes = logo.screenshot_as_png withopen(device_logo_path,"wb")as f:#device_logo_path是图片保存路径 f.write(screenshot_bytes)

然后再把原图保存在这个工程的一个位置,建议保存在setting下面,因为是测试文件,这样比较规范,比如路径是web_logo_path

比较图片是否是同一张的方法:计算汉明距离

from PIL import Image import imagehash defhash_compare(img1_path,img2_path,threshold=16): hash1 = imagehash.phash(Image.open(img1_path)) hash2 = imagehash.phash(Image.open(img2_path))#计算汉明距离 hamming_distance = hash1-hash2 is_similar = hamming_distance <= threshold if is_similar:print("同一张图片")else:print("不是同一张")

threshold是比较的严格程度,越小越严格,最大64
这个我是根据社会获取到的图片和原图进行比较,因为从设备上获取的照片比较模糊,先试了threshold=5被判断为不通过。
然后两张完全不同的图片选择64,竟然会被判断为一样。
取16可以分辨不同的图片,所以最终选了16。
2、web端开启手动滑动功能,远程工具连接设备,鼠标确实能拖动小窗口上下滑动
但是通过appium定位不到这个可滑动的元素
于是采用坐标滑动的方法

defswipe_up(driver,start_x_percent=0.2,start_y_percent=0.8,end_y_percent=0.2): width = driver.get_window_size()['width'] height = driver.get_window_size()['height'] actions = ActionChains(driver) actions.w3c_actions = ActionBuilder(driver,mouse=PointerInput(interaction.POINTER_TOUCH,"TOUCH")) actions.w3c_actions.pointer_action.move_to_location(start_x_percent*width,start_y_percent*height) actions.w3c_actions.pointer_action.pointer_down() actions.w3c_actions.pointer_action.move_to_location(start_x_percent*width,end_y_percent*height) actions.w3c_actions.pointer_action.pointer_up() actions.perform()

ps:觉得之前的swipe方法简单又快捷,但是现在好像只支持ActionChains这种方法。

Read more

AI魔术师:基于视觉的增强现实特效

AI魔术师:基于视觉的增强现实特效

AI魔术师:基于视觉的增强现实特效 * 一、前言 * 二、AR 与视觉 AI 的技术基石 * 2.1 增强现实的核心概念 * 2.2 计算机视觉与 AI 的技术融合 * 2.3 技术栈选型与环境搭建 * 三、视觉 AR 的核心技术解析 * 3.1 相机标定与坐标系统 * 3.1.1 相机标定原理 * 3.1.2 标定代码实现 * 3.2 实时特征跟踪技术 * 3.2.1 ORB 特征跟踪原理 * 3.2.2 单目视觉里程计实现 * 3.3 语义分割与虚实融合

基于FPGA的高速serial通信模块设计与验证

FPGA高速串行通信设计实战:从原理到验证的完整路径 在现代高性能电子系统中,数据洪流正以前所未有的速度涌动。无论是雷达前端每秒采集的TB级回波信号,还是数据中心内部节点间低延迟互联需求,传统并行总线早已力不从心——引脚爆炸、布线复杂、信号完整性恶化……这些问题迫使工程师转向一种更优雅的解决方案: 基于FPGA的高速串行通信(High-Speed Serial Link) 。 今天,我们就来深入拆解这个“吞吐利器”的设计全貌。不讲空话,只聚焦真实工程场景下的关键挑战与应对策略,带你走通从协议理解、模块构建到实测验证的完整闭环。 为什么是FPGA?它凭什么扛起高速通信大旗? 当你的系统需要稳定跑在5 Gbps以上,且对延迟敏感时,MCU或通用处理器往往束手无策。它们受限于软件调度开销、外设带宽瓶颈和中断响应抖动。而FPGA不同——它是硬件逻辑的自由画布。 以Xilinx Kintex Ultrascale+为例,其片上集成了多达96个GTH收发器通道,单通道支持高达13.1 Gbps线速率;Intel Stratix 10 SX系列更是可达28.3 Gbps。这些专用硬核不仅

ROS2:无人机从 “能飞” 到 “会思考” 的全栈技术引擎 —— 深度拆解与落地指南(上)

前言 在无人机技术飞速迭代的今天,“飞得稳” 已不再是终极目标,工业巡检、农业植保、仓储物流、应急搜救等复杂场景,对无人机提出了 “自主定位、智能感知、协同作业” 的高阶要求。而 ROS2(Robot Operating System 2)作为新一代机器人操作系统,正成为无人机突破 “手动控制” 瓶颈、迈向 “自主智能” 的核心引擎。 很多开发者会困惑:飞控系统(如 PX4、ArduPilot)已能实现起飞、悬停、巡航,为何还要集成 ROS2?两者如何分工协作?不同场景下的硬件配置最低要求是什么?本文将从核心定位、飞控配合、协调底座能力、硬件 OS 最小要求、集成实战、典型场景六大维度,用通俗语言 + 海量表格,全方位拆解 ROS2

OpenClaw 新手指南:从零开始的 AI 机器人搭建完全攻略

OpenClaw 新手指南:从零开始的 AI 机器人搭建完全攻略 想随时随地通过微信、飞书、Telegram 等平台与 AI 助手对话?OpenClaw 帮你实现。 为什么选择 OpenClaw? OpenClaw 是一个开源的自托管 AI 网关,让你可以在自己服务器上运行一个 central hub,连接所有聊天平台到强大的 AI 模型(如 Claude、GPT、Pi、Kimi 等)。 核心优势: * ✅ 数据完全掌控(自托管,隐私安全) * ✅ 多平台统一管理(一个网关服务所有渠道) * ✅ 无代码扩展(通过技能系统) * ✅ 24/7 可用(开机自启动) * ✅ 日志和记忆(支持长期对话) 10个核心技巧详解 技巧 1:快速安装与配置 适用场景: