Playwright之录制脚本转Page Object类

news2024/12/24 8:00:13

Playwright之录制脚本转Page Object类

设计思路 : 我们今天UI自动化设计的时候,通常会遵循一些设计模式,例如Page Object模式。但是自己找元素再去填写有一些麻烦,所以我们可以通过拆解录制的脚本,将其中的元素提取出来,然后放到我们的页面中。

一、文件目录如下

在这里插入图片描述

  • auto_myself(名字瞎起的) : 执行文件,主要功能为获取我们脚本存放的地址,读取信息,然后将其写入py文件,创建object,并添加其属性。
  • page_template : 生成的类的模板,将录制的脚本转为这种格式。
  • scripts_record_file : 录制的脚本存放文件。

二、操作步骤

1.使用playwright脚本录制命令,启动脚本录制功能,进行操作,录制自动化脚本

playwright安装过程就不说了,都是一样的。

playwright codegen
2.将录制的脚本复制到txt文件中

直接用录制器自带的复制,复制粘贴就行啦,很方便。
在这里插入图片描述

3.修改auto_myself文件中的类名称和脚本地址

如果在同一个文件夹下,只修改类名和保存文件的信息就可以。
在这里插入图片描述

4. 执行auto_myself的方法

执行后我们可以得到一个文件名为playwright_element_page,类为class_name的py文件。
在这里插入图片描述

在这里插入图片描述

三、auto_myself文件代码

文件的逻辑如下:

  1. 定义好object的属性
  2. 获取录制的脚本文件
  3. 根据元素特点进行分离,将元素的定位方式保存并重命名
  4. 将获取到的元素进行到我们的模板文件中
  5. 文件替换和去重等处理
 -*- coding: utf-8 -*-
import os.path
from playwright_element_page.page_template import page_base_text
# 获取文件执行目录
root_path = os.path.dirname(os.path.abspath(__file__))
print(root_path)

class AutoMyself(object):
    """
    脚本自动创建类
    """

    _button = 0
    _input = 0
    _select = 0
    _switch = 0
    _frame = 0
    _label = 0
    _link = 0
    _total = 0
    _deduplication = 0

    def __init__(self, record_scripts_base_path: str = '', output_file_path: str = '', output_file_name: str = ''):
        self.base_path = record_scripts_base_path
        self.output_path = root_path + output_file_path + '/' + output_file_name + '.py'
        self.element_dict = {}

    def scripts_to_page(self, page_name: str):
        """
        录制脚本转 page 结构文件
        :param page_name:创建文件名称
        :return:
        """
        if self.__get_element_for_page():
            self.__set_element_to_page(page_name)

    def __get_element_for_page(self):
        """
        获取文件内容
        :return:
        """
        try:
            with open(self.base_path, 'r', encoding='gbk') as f:
                for line in f:
                    line = line.strip().replace("\n", "")
                    tags = ('page.', 'page1.')
                    if any(tag if tag in line else False for tag in tags):
                        self.__create_element_for_page(line)
                        self._total += 1
        except UnicodeDecodeError as ude:
            print(f'*****文件读取失败!文件编码异常:{ude},请检查文件内容!*****')
        except Exception as e:
            print(f'*****执行异常:{e}*****')
        finally:
            print(f'***** 元素数量:{self._total} *****')
            return self.element_dict

    def __set_element_to_page(self, page_name: str):
        """
        保存元素信息到文件
        :return:
        """
        # 元素去重
        self.__element_deduplication()
        try:

            with open(self.output_path, 'w', encoding='utf-8') as f:
                class_name = page_name.title()
                f.write(page_base_text.format(class_name.replace('_', '')))
                for name, locator in self.element_dict.items():
                    f.write(f'\t\tself.{name} = {locator}\n')
        except UnicodeDecodeError as ude:
            print(f"***** __set_element_to_page文件写入异常,字符格式错误:{ude} *****")
        except Exception as e:
            print(f'***** 文件写入异常,{e} *****')
        finally:
            print(f'***** 已去除重复元素数量:{self._deduplication} *****')
            print('***** 文件写入操作完成! *****')

    def __create_element_for_page(self, element):
        """
        创建页面元素
        :return:
        """
        element_types = ('select_option',)
        if 'get_by_role' in element:
            self.__element_filter_by_role(element)
        elif any(element_type if element_type else False for element_type in element_types):
            self.__element_filter_by_type(element)
        else:
            self.__element_filter_by_operate(element)

    def __element_filter_by_role(self, element):
        """
        根据元素角色的定位方式,添加元素信息
        :param element:元素信息
        :return:
        """
        role = element.split('get_by_role("')[1].split('"')[0]
        if role == 'button':
            self.element_dict[f'button_{self._button}'] = element.split('.click')[0]
            self._button += 1
        elif role == 'label':
            self.element_dict[f'label_{self._label}'] = element.split('.click')[0]
            self._label += 1
        elif role == 'link':
            self.element_dict[f'link_{self._link}'] = element.split('.click')[0]
            self._link += 1
        else:
            self.__element_filter_by_operate(element)

    def __element_filter_by_type(self, element):
        """
        根据元素角色的定位方式,添加元素信息
        :param element:元素信息
        :return:
        """
        if 'select_option' in element.split('.')[-1]:
            self.element_dict[f'select_{self._select}'] = element.split('.click')[0]
            self._select += 1
        else:
            self.__element_filter_by_operate(element)

    def __element_filter_by_operate(self, element):
        """
        根据操作方式,判断元素类型
        :param element:
        :return:
        """
        if '.click()' in element:
            self.element_dict[f'button_{self._button}'] = element.split('.click')[0]
            self._button += 1
        elif '.fill(' in element:
            self.element_dict[f'input_{self._input}'] = element.split('.fill')[0]
            self._input += 1
        else:
            print(f'当前元素识别方式未补充:{element}')

    def __element_deduplication(self):
        """
        元素去重
        :return:
        """
        new_dict = {value: key for key, value in self.element_dict.items()}
        self.element_dict = {value: key for key, value in new_dict.items()}
        self._deduplication = self._total - len(self.element_dict)


if __name__ == '__main__':
    am = AutoMyself(record_scripts_base_path='scripts_record_file.txt', output_file_name='playwright_element_page')
    am.scripts_to_page('class_name')

四、page_template文件代码

其实这个文件不用py用txt也可以,只要可以获取到我们想要的类结构,然后按行写入文件就能满足我们的需求。

# -*- coding: utf-8 -*-
# page模板内容
page_base_text = '''# -*- coding: utf-8 -*-
from serve.base_page import BasePage
from playwright.sync_api import Page


class {}(BasePage):
\t"""
\t页面描述
\t"""

\tdef __init__(self, page: Page):
\t\tsuper().__init__(page)
'''

其他

转换的思路其实比较简单,就是将元素提取出来,然后将其写入另一个文件。脚本内容还有很多需要完善的地方,大家可以提出修改意见,我会根据大家的意见进行完善。大家有其他问题也可以提出一起修改~

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

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

相关文章

行业洞察 | 2024应用程序安全领域现状报告

在信息爆炸的时代,我们每天都在使用各种应用,从社交娱乐到工作学习,应用已经成为我们生活中不可或缺的一部分。然而,你是否知道,在这些便捷的背后,隐藏着巨大的安全风险? 近年来,应用…

爬虫-网页基础

HTML 基本语法 HTML&#xff1a;Hyper Text Markup Language, 超文本标记语言&#xff0c;是计算机语言的一种&#xff0c;由元素构成。 p元素 <p>Web 真好玩&#xff01;</p> 由三大部分组成 开始标签&#xff1a;一对尖括号中间包裹这元素名称元素内容&#x…

中霖教育怎么样?注册会计师可以跨省考试吗?

中霖教育怎么样?注册会计师可以跨省考试吗? 1. 考试地点安排&#xff1a; 注册会计师考试是在全国范围内统一举行的&#xff0c;通常设在各省、自治区和直辖市指定的考区。考生须依据准考证上提供的信息&#xff0c;核实自己的具体考试地点。该考试实行的网上统一报名制度&…

mpeg格式怎么转换成mp4?这四种转换方法非常好用!

mpeg格式怎么转换成mp4&#xff1f;在数字视频领域中&#xff0c;MPEG格式算是相对冷门的一种选择&#xff0c;然而&#xff0c;选择这种格式却不是没有代价的&#xff0c;首先&#xff0c;MPEG采用了有损压缩技术&#xff0c;这意味着在视频处理过程中&#xff0c;会丢失一些细…

欧洲杯:高精度定位技术,重塑体育赛事新体验

随着科技的飞速发展&#xff0c;体育赛事的观赏体验与竞技水平正被不断推向新的高度。在即将到来的2024年欧洲杯赛场上&#xff0c;一项革命性的技术——高精度定位&#xff0c;正悄然改变着比赛的每一个细节&#xff0c;为球迷们带来前所未有的观赛享受&#xff0c;同时也为运…

Linux Shell 脚本入门教程:开启你的自动化之旅

目录 一、什么是Shell&#xff1f; 二、 编写第一个Shell脚本 ​编辑 2.2 变量 2.3 功能语句 2.4 数组 一、什么是Shell&#xff1f; Shell是一种计算机程序&#xff0c;它充当了用户与操作系统之间的接口。在Linux系统中&#xff0c;Shell允许用户通过命令行界面&#x…

揭开梵蒂冈秘密档案馆的神秘面纱

关注我们 - 数字罗塞塔计划 - PART 01 深邃的历史 梵蒂冈秘密档案馆起源于公元8世纪&#xff0c;负责保存官方文书和教皇书信。9世纪开始在圣彼得大教堂设立档案库&#xff0c;负责保管外交和法律文件&#xff0c;在帕拉蒂诺山塔内保存经济和行政方面的档案。11至13世纪&…

3.2ui功能讲解之graph页面

本节重点介绍 : graph页面target页面flags页面status页面tsdb-status页面 访问地址 $ip:9090 graph页面 autocomplete 可以补全metrics tag信息或者 内置的关键字 &#xff0c;如sum聚合函数table查询 instante查询&#xff0c; 一个点的查询graph查询调整分辨率 resolutio…

在地图上根据经纬度,画一个矩型围栏,设置每个点的经纬度

在做一个需求时有一个小点就是添加一个配送区域(5公里直径内的)矩形围栏 我做的比较简单 大家看看有没有帮助, 也是精简代码。测试效果上相对是精准的 //谷歌&#xff0c;根据经纬度获取以它为中心半径为5公里内的矩形的四个点经纬度getDefalutPoints (lng: number, lat: num…

【SpringCloud】Ribbon源码解析

ribbon是一个负载均衡组件&#xff0c;它可以将请求分散到多个服务提供者实例中&#xff0c;提高系统的性能和可用性。本章分析ribbon是如何实现负载均衡的 1、LoadBalanced 消费者在引入ribbon组件后&#xff0c;给http客户端添加LoadBalanced注解就可以启用负载均衡功能。Lo…

LangChain 入门上篇:模型 I/O 封装

LangChain 是面向大模型的开发框架&#xff0c;是 AGI 时代软件工程的探索和原型。学习 LangChain 需要关注接口的变更。 LangChain 的核心组件 1.模型 I/O 封装 LLMS 大语言模型Chat Models 一套基于 LLMS&#xff0c;但按对话结构重新封装PromptTemplate 提示词模板Output…

Unity中TimeLine的一些用法

Unity中TimeLine的一些用法 概念其他 概念 无Track模式&#xff08;PlayableAsset、PlayableBehaviour&#xff09; 1. 两者关系 运行在PlayableTrack中作用 PlayableBehaviour 实际执行的脚本字段并不会显示在timeline面板上 PlayableAsset PlayableBehaviour的包装器&#x…

uboot run命令基本使用

run 命令可以用于运行环境变量的中定义的命令,run bootcmd 可以运行bootcmd中启动命令 作用:可以运行我们自定义的环境变量 include/command.h common/cli.c /*** board_run_command() - Fallback function to execute a command** When no command line features are enabled …

性能测试-JMeter学习

1、给不同的访问口分配访问占比&#xff1b;例&#xff1a;登录30%&#xff0c;首页&#xff1a;20%&#xff0c;新增&#xff1a;50% 不同业务放到不同线程组里&#xff0c;实现不同业务的分配 使用吞吐量控制器&#xff0c;设置不同的占比 使用if控制器&#xff0c;设置不同…

mac鼠标键盘共享:ShareMouse for Mac 激活版

hareMouse 是一款 Windows 和 macOS 操作系统上的共享和切换鼠标和键盘的实用工具。这款软件允许用户在多台计算机之间无缝地共享鼠标和键盘&#xff0c;使得在不同设备之间进行工作和操作变得更加便捷。占用资源少&#xff1a; ShareMouse 设计轻量&#xff0c;占用系统资源较…

Logback日志配置两种方式

SpringBoot 默认使用的是Logback 1. 在resource新建文件logback-spring.xml&#xff0c;配置日志相关信息 <configuration><property name"app.name" value"order-service"/><property name"log.path" value"./logs/"…

克隆gitee仓库,在vs2022创建文件夹开发项目操作步骤

git网站 git知识大全 git教程&#xff1a;廖雪峰的官方网站 git菜鸟教程 gitee之创建项目步骤 同步源仓库 2. 克隆命令 3. 右击git Bash Here>粘贴命令行 4. 选中项目文件夹》创建本人文件夹&#xff08;ZYY&#xff09; 5. 打开vs2022》新建项目》选择Framework》下…

C++之boost智能指针

1、boost智能指针 资源获取即初始化&#xff1a;在构造函数中对资源进行初始化&#xff0c;在析构函数中释放。 智能指针的本质思想是&#xff1a;将堆对象的生存期&#xff0c;用栈对象来管理。这个栈对象就是智能指针。 当new 一个堆对象的时候&#xff0c;立刻用智能指针…

VS2022(Visual Studio 2022)最新安装教程

1、下载 1、下载地址 - 官网地址&#xff1a;下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux - 根据自己的电脑的 【操作系统】 灵活选择。 2、安装包 【此处为Windows系统安装包】 2、安装 1、打开软件 - 右击【以管理员身份打开】&#xff0c; 2、准备配置 …

【Unity 角色控制器组件】

【Unity 角色控制器组件】 Character Controller&#xff1a; Unity 内置的一个组件&#xff0c;用于提供高级的物理控制&#xff0c;允许开发者控制角色的移动、跳跃和碰撞。 csharp csharp // 假设你已经有了一个带有Character Controller组件的游戏对象// 获取Character Co…