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文件代碼
文件的邏輯如下:
- 定義好object的屬性
- 獲取錄制的腳本文件
- 根據元素特點進行分離,將元素的定位方式保存并重命名
- 將獲取到的元素進行到我們的模板文件中
- 文件替換和去重等處理
-*- 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 = 0def __init__(self, record_scripts_base_path: str = '', output_file_path: str = '', output_file_name: str = ''):self.base_path = record_scripts_base_pathself.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 += 1except UnicodeDecodeError as ude:print(f'*****文件讀取失敗!文件編碼異常:{ude},請檢查文件內容!*****')except Exception as e:print(f'*****執行異常:{e}*****')finally:print(f'***** 元素數量:{self._total} *****')return self.element_dictdef __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 += 1elif role == 'label':self.element_dict[f'label_{self._label}'] = element.split('.click')[0]self._label += 1elif role == 'link':self.element_dict[f'link_{self._link}'] = element.split('.click')[0]self._link += 1else: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 += 1else: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 += 1elif '.fill(' in element:self.element_dict[f'input_{self._input}'] = element.split('.fill')[0]self._input += 1else: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 Pageclass {}(BasePage):
\t"""
\t頁面描述
\t"""\tdef __init__(self, page: Page):
\t\tsuper().__init__(page)
'''
其他
轉換的思路其實比較簡單,就是將元素提取出來,然后將其寫入另一個文件。腳本內容還有很多需要完善的地方,大家可以提出修改意見,我會根據大家的意見進行完善。大家有其他問題也可以提出一起修改~