自动化测试用例之元素自愈:Playwright与pytest的结合使用

前言

在自动化测试领域,元素定位的准确性对于测试的成功至关重要。当使用Playwright结合pytest进行测试时,我们可以通过一些策略来增强测试的鲁棒性,特别是在元素定位失败时能够自动进行修复。本文将详细介绍如何实现这一过程。

环境准备

首先,确保你的环境中安装了playwrightpytest。可以通过以下命令安装:

pip install pytest
pip install playwright

自动化修复策略

在测试过程中捕获失败并尝试自动修复问题。我们将使用 Playwright 的 Locator 来定位元素,并在失败时重新定位更新元素。

BasePage类设计

BasePage类封装了页面操作和自动修复的逻辑。

base.py

# -*- coding: utf-8 -*-
# @Author  : blues_C
# @File    : base.py
# @Desc:import re
from utils.logger import log
from playwright.sync_api import Page, expect, Locatorclass BasePage:def __init__(self, page: Page):self.page = pagedef locator(self, selector: str) -> Locator:"""查找并返回元素"""element = self.page.locator(selector)if not element.is_visible():self.auto_repair()return elementdef click(self, selector: str):self.locator(selector).click()def fill(self, selector: str, input_value: str):self.locator(selector).fill(input_value)def auto_repair(self, scope_selector: str = "body",selector: str = "input, button, a, select, textarea, div, span, img, iframe, label, svg",filename="login_element.py"):### 自动修复逻辑:尝试重新定位页面上的所有相关元素,并更新我们的元素定位文件。### page_title = self.page.title()scope = self.page.locator(scope_selector)elements = scope.locator(selector).all()log.info(f"自愈元素: {selector} (共 {len(elements)} 个)")# 检查文件是否存在if os.path.exists(filename):# 读取现有文件内容,以便检查变量名with open(filename, "r") as file:lines = file.readlines()existing_variables = set()# 获取现有的变量名for line in lines:if "=" in line:variable_name = line.split("=")[0].strip()existing_variables.add(variable_name)# 打开文件,准备写入新内容with open(filename, "w") as file:file.write(f"# Existing variables from {page_title}\n\n")for element in elements:element_info = f"element='{element}', "start_index = element_info.find("selector=")if start_index != -1:selector_str = element_info[start_index + len("selector='"):]end_index = selector_str.find("'")if end_index != -1:selector_content = selector_str[:end_index]# 获取各个属性text = element.inner_text()value = element.get_attribute('value')element_id = element.get_attribute('id')element_class = element.get_attribute('class')element_name = element.get_attribute('name')element_type = element.get_attribute('type')element_placeholder = element.get_attribute('placeholder')# 检查属性是否为 None,并记录非 None 的属性log_info = f"element='{selector_content}', "if text != '':log_info += f"text='{text}'  "if value != '' and value is not None:log_info += f"[value='{value}']  "if element_id is not None:log_info += f"#{element_id}  "if element_class is not None:log_info += f"[class='{element_class}']  "if element_name is not None:log_info += f"[name='{element_name}']  "if element_type is not None:log_info += f"[type='{element_type}']  "if element_placeholder is not None:log_info += f"[placeholder='{element_placeholder}']"# 打印日志信息log.info(log_info)# 如果变量名已存在,替换现有的定义行if variable_name in existing_variables:file.write(f"# {log_info} (replaced)\n")if element.get_attribute('name') is not None:variable_name = element.get_attribute('name')variable_type = selector_contentfile.write(f"{variable_name} = '{variable_type}'\n\n")existing_variables.add(variable_name)elif element.get_attribute('type') is not None:variable_name = element.get_attribute('type')variable_type = selector_contentfile.write(f"{variable_name} = '{variable_type}'\n\n")existing_variables.add(variable_name)else:variable_type = selector_contentfile.write(f"'{variable_type}'\n\n")existing_variables.add(variable_name)else:# 如果文件不存在,则创建新文件并写入内容with open(filename, "w") as file:file.write(f"# {page_title}\n")for element in elements:element_info = f"element='{element}', "start_index = element_info.find("selector=")if start_index != -1:selector_str = element_info[start_index + len("selector='"):]end_index = selector_str.find("'")if end_index != -1:selector_content = selector_str[:end_index]text = element.inner_text()value = element.get_attribute('value')element_id = element.get_attribute('id')element_class = element.get_attribute('class')element_name = element.get_attribute('name')element_type = element.get_attribute('type')element_placeholder = element.get_attribute('placeholder')info = f"element='{selector_content}', "if text != '':info += f"text='{text}'  "if value != '' and value is not None:info += f"[value='{value}']  "if element_id is not None:info += f"#{element_id}  "if element_class is not None:info += f"[class='{element_class}']  "if element_name is not None:info += f"[name='{element_name}']  "if element_type is not None:info += f"[type='{element_type}']  "if element_placeholder is not None:info += f"[placeholder='{element_placeholder}']"log.info(info)file.write(f"# {info}\n")if element.get_attribute('name') is not None:variable_name = element.get_attribute('name')variable_type = selector_contentfile.write(f"{variable_name} = '{variable_type}'\n\n")elif element.get_attribute('type') is not None:variable_name = element.get_attribute('type')variable_type = selector_contentfile.write(f"{variable_name} = '{variable_type}'\n\n")else:variable_type = selector_contentfile.write(f"'{variable_type}'\n\n")

pytest fixture的使用

conftest.py

import pytest
from playwright.sync_api import sync_playwright@pytest.fixture(scope='session')
def browser():with sync_playwright() as p:browser = p.chromium.launch()yield browserbrowser.close()

测试用例编写

test_cases.py

import pytest
from common.base import BasePage
from playwright.sync_api import sync_playwrightdef test_auto_repair(browser):page = browser.new_page()page.goto('https://example.com')try:# 运行测试步骤BasePage(page).fill(login_element.username, 'username')BasePage(page).fill(login_element.password, 'password')BasePage(page).click(login_element.login)except Exception as e:pytest.fail(f'Test failed: {e}')BasePage(page).fill(login_element.username, 'username')BasePage(page).fill(login_element.password, 'password')BasePage(page).click(login_element.login)

元素定位文件

login_element.py 示例:

# 登录到 standard
# element='form >> input,button >> nth=0', #username  [class='form-control']  [name='username']  [type='text']  
username = 'form >> input,button >> nth=0'# element='form >> input,button >> nth=1', #password  [class='form-control']  [name='password']  [type='password']  
password = 'form >> input,button >> nth=1'# element='form >> input,button >> nth=2', #id-hidden-input  [name='credentialId']  [type='hidden']  
credentialId = 'form >> input,button >> nth=2'# element='form >> input,button >> nth=3', [value='登录']  #kc-login  [class='btn btn-primary btn-block btn-lg']  [name='login']  [type='submit']  
login = 'form >> input,button >> nth=3'

总结

本文展示了如何使用Playwright的Locator结合pytest的自动化测试框架来实现元素的自动定位和修复。通过封装页面操作和自动修复逻辑到BasePage类中,我们可以提高测试的稳定性和可维护性。同时,使用pytest的fixture来管理浏览器的生命周期,使得测试更加简洁。

通过上述方法,我们能够确保即使在面对复杂的页面元素变化时,我们的自动化测试也能够适应并成功执行,从而提高测试的覆盖率和准确性。

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

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

相关文章

ZooKeeper 搭建详细步骤之一(单机模式)

ZooKeeper 搭建详细步骤之三(真集群) ZooKeeper 搭建详细步骤之二(伪集群模式) ZooKeeper 搭建详细步骤之一(单机模式) ZooKeeper 及相关概念简介 搭建模式简述 ZooKeeper 的搭建模式包括单机模式、集群模…

YOLOv8核心原理深度解析

YOLOv8源码地址: https://github.com/ultralytics/ultralytics 一、简介: 根据官方描述,Yolov8是一个SOTA模型,它建立在Yolo系列历史版本的基础上,并引入了新的功能和改进点,以进一步提升性能和灵活性,使其成为实现目标检测、图像分割、姿态估计等任务的最佳选择。其具体…

AI图书推荐:将 ChatGPT和Excel融合倍增工作效率

《将 ChatGPT和Excel融合倍增工作效率》( Hands-on ChatGPT in Excel. Enhance Your Excel Workbooks)由Mitja Martini撰写,旨在教授读者如何将ChatGPT与Excel结合使用,以提升工作效率和创造AI增强的Excel工具。它还提供了Excel中…

AnomalyGPT——使用大型视觉语言模型进行工业异常检测的算法解析与应用

1.概述 工业缺陷检测是工业自动化和质量控制中的一个重要环节,其目的是在生产过程中识别和分类产品或组件中的缺陷,以确保最终产品的质量满足既定标准。这项技术的应用可以显著提高生产效率,降低成本,并减少由于缺陷产品导致的潜…

sgg_ssm学习--前端搭建遇到的问题

目录 问题1:由于我是解压缩软件nodejs,没有添加系统路径 解决:添加nodejs的路径 到系统 path中 问题2:vscode 终端输入npm命令 报错 解决(如图所示在vscode打开前端工程,终端修改如下配置): 问题1&…

如何在iPhone上恢复出厂设置后恢复数据

你不想让这种情况发生,但它确实发生了。您必须将iPhone恢复出厂设置。当您的 iPhone 上出现软件问题且无法修复时,可能会发生这种情况。相反,在更新期间,或者您的iPhone遇到问题时,iPhone上的数据不再存在。 不过不用…

Spark SQL编程初级实践

参考链接 Spark编程: Spark SQL基本操作 2020.11.01_df.agg("age"->"avg")-CSDN博客 RDD编程初级实践-CSDN博客 Spark和Hadoop的安装-CSDN博客 1. Spark SQL基本操作 { "id":1 , "name":" Ella" , "age":…

使用多网络和Kubernetes转变您的通讯应用程序

传统的 Kubernetes 网络在基本的 Pod 到 Pod 连接方面表现出色,但在满足通讯工作负载的安全性、性能和合规性要求时可能存在不足。这限制了通讯提供商充分利用 Kubernetes 的可扩展性和敏捷性优势的能力。 Google Cloud 的多网络方法使通讯提供商能够克服这些限制&a…

笔记-PPT绘图导出高清无失真图片

问题描述:PPT绘图已经用了高清图(jpg、tif格式),但论文图片还是不清晰,打印出来还是有点糊 以下是PPT导出高清不失真图片(emf格式)的具体描述。 目录 一、绘图工具二、操作步骤 一、绘图工具 …

数据挖掘之基于Lightgbm等多模型消融实验的信用欺诈检测实现

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在当前的金融环境中,信用欺诈行为日益增多,给金融机构和消费者带来了巨大的损…

【已解决】pandas读excel中长数字变成科学计数法的问题

pandas 读excel中的长数字时,即使excel中已经设置为文本,读进df后也会自动变成科学计数法。 在日常的数据分析和处理工作中,Excel和pandas是数据分析师们不可或缺的得力助手。然而,在使用pandas读取Excel文件时,我们有…

Spring Boot的热部署工具“AND”Swagger测试工具

Spring Boot的热部署&Swagger测试页面的使用 热部署指的是在项目无需重启的情况下,只需要刷新页面,即可获得已经修改的样式或功能。要注意该工具一般用于开发环境,在生产环境中最好不要添加这个工具。 对于无需重启便可刷新这么方便的工…

【linux-1-Ubuntu常用命令-vim编辑器-Vscode链接ubuntu远程开发】

目录 1. 安装虚拟机Vmare和在虚拟机上安装Ubuntu系统:2. 常用的Ubuntu常识和常用命令2.1 文件系统结构2.2 常用命令2.3 vim编辑器 3. Ubuntu能联网但是ping不通电脑:4. Windows上安装VScode链接ubuntu系统,进行远程开发: 1. 安装虚…

理解sourcemap:调试和部署的利器

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

根据顶层的id递归查询出全部子节点

效果图 根据输入的id为2查询出所有的红色框起来的节点 mapper接口 TSystemOrg getOrgByorgId(String orgId); List<TSystemOrg> getOrgListByParentId(String parentId);mapper.xml <!--根据id查询org--> <select id"getOrgByorgId" resultType&…

【JVM】简述类加载器及双亲委派机制

双亲委派模型&#xff0c;是加载class文件的一种机制。在介绍双亲委派模型之前&#xff0c;我需要先介绍几种类加载器&#xff08;Class Loader&#xff09;。 1&#xff0c;类加载器 Bootstrap&#xff0c;加载lib/rt.jar&#xff0c;charset.jar等中的核心类&#xff0c;由…

【算法】【贪心算法】【leetcode】870. 优势洗牌

题目地址&#xff1a;https://leetcode.cn/problems/advantage-shuffle/description/ 题目描述&#xff1a; 给定两个长度相等的数组 nums1 和 nums2&#xff0c;nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。 返回 nums1 的任意排列&…

界面组件DevExpress中文教程 - 如何在Node.js应用中创建报表?

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 获取DevExpress Reporting最新正式版下载(Q技术…

【SQL Server】入门教程-基础篇(三)

目录 前言 SQL 常用函数学习 AVG – 平均值 COUNT – 汇总函数 ​编辑MAX – 最大值 ​编辑MIN – 最小值 ​编辑SUM – 求和 UCASE/UPPER – 大写 LCASE/LOWER – 小写 ROUND – 数值取舍 NOW/SYSDATE – 当前时间 前言 这一篇博客&#xff0c;是Sql Server函数学…

本地构建编译Apache-Seatunnel2.3.5适配Web1.0.0运行实现Mysql-CDC示例

本地构建编译Apache-Seatunnel2.3.5适配Web1.0.0运行实现Mysql-CDC示例 文章目录 1.前言2.编译2.1版本说明2.2 seatunnel2.3.4-release分支配置2.3maven调优配置 3.web1.0.0适配3.1配置文件修改和新增文件3.2手动拷贝jar修改依赖3.3修改web不兼容的代码3.4 web编译打包 4.运行m…