前言
前篇:【PC桌面自动化测试工具开发笔记】(四)用QTextEdit实现仿AirtestIDE的代码编辑界面
上篇文章留了copy_signal和paste_signal两个信号,待实现需求点:不同测试脚本间代码内容拷贝时自动拷贝图片资源。实现方法其实和前篇一样,对字符串一顿操作就可以实现了,这里重新把相关函数贴上:
字符串处理
def string_to_html_filter(text: str) -> str:
"""
特殊字符转换
:param text: 原始文本
:return: 转换后的文本
"""
text = text.replace("&", "&")
text = text.replace(">", ">")
text = text.replace("<", "<")
text = text.replace("\"", """)
text = text.replace("\'", "'")
text = text.replace(" ", " ")
text = text.replace("\n", "<br>")
text = text.replace("\r", "<br>")
return text
def get_img_from_text(plain_line, air_case_path, img_name):
"""
纯文本转换为富文本图片显示
:param plain_line: 纯文本
:param air_case_path: 用例路径
:param img_name: 图片名称
:return: 富文本内容
"""
plain_line = string_to_html_filter(plain_line)
html_line = plain_line.replace(img_name, "<img src='" + os.path.join(air_case_path, img_name) + "'/>")
return html_line
def get_img_list_from_text(text_list: list[str], air_case_path: str, pic_list: list[str]) -> list[tuple]:
"""
根据文本列表获取图片列表
:param text_list: 文本列表
:param air_case_path: 用例地址
:param pic_list: 图片列表
:return: (图片路径,匹配文本行,行号)...列表
"""
image_list = []
for row in range(len(text_list)):
line = text_list[row].strip("\n")
for pic in pic_list:
img_path = os.path.join(air_case_path, pic)
if pic in line:
image_list.append((img_path, line, row))
return image_list
def search_img_in_html(html_text):
"""
从html内容中查找img
:param html_text: html富文本
:return: row_list
"""
content = html_text.split("\n")[4:] # 跳过前四行
row_list = [i for i in range(len(content)) if "<img src=" in content[i]] # 返回图片所在行号
return row_list
def get_img_from_html(html_text, row):
"""
从html中提取图片路径,图片名
:param html_text: html文本
:param row: 需要处理的行号
:return: 图片路径,图片名
"""
html_content = html_text.split("\n")[4:] # 跳过前四行
html_line = html_content[row] # 图片所在行
img_path = html_line[
html_line.find("<img src=") + len("<img src=") + 1:html_line.rfind('.png') + len(
'.png')] # 从html行内容提取图片信息
img_name = img_path[img_path.rfind('\\') + 1:]
return img_path, img_name
def get_text_from_img(plain_line, html_text, row):
"""
将图片转换为文本
:param plain_line: 获取无法解析图片的纯文本信息
:param html_text: html富文本
:param row: 需要处理的行号
:return: 处理结果
"""
img_name = get_img_from_html(html_text, row)[1]
value = plain_line.replace('', img_name) # 替换图片文本内容
return value
拷贝、粘贴槽函数
类变量show_image去控制富文本显示/纯代码显示,用类实例变量self.air_case_file_path去存储当前编辑的脚本路径。
这里的self.textEdit_air_case是前篇文章CodeTextEdit类的实例,绑定对应信号就可以实现代码内容拷贝时自动拷贝图片资源了。
def copy_image_resource(self):
"""拷贝图片资源"""
if self.show_image:
copy_content = self.textEdit_air_case.textCursor().selection().toHtml()
row_list = search_img_in_html(copy_content)
self.copy_image_list = [get_img_from_html(copy_content, row)[0] for row in row_list]
else:
copy_content = self.textEdit_air_case.textCursor().selection().toPlainText()
air_case_file_path = self.air_case_file_path
target_path = air_case_file_path[:air_case_file_path.rfind("\\")]
string_list1 = [result.strip('"') for result in re.split(r'("[^"]*")', copy_content) if
result and result[0] == '"']
string_list2 = [result.strip("'") for result in re.split(r"('[^']*')", copy_content) if
result and result[0] == "'"]
string_list = string_list1 + string_list2
self.copy_image_list = [os.path.join(target_path, word) for word in string_list if word.endswith(".png")]
def paste_image_resource(self):
"""图片资源粘贴"""
air_case_file_path = self.air_case_file_path
target_path = air_case_file_path[:air_case_file_path.rfind("\\")]
for image in self.copy_image_list:
if os.path.isfile(image):
try:
shutil.copy(image, target_path)
except shutil.SameFileError:
pass
无用图片资源清理
采用airtest的处理方式,各个测试脚本的测试图片资源存储在对应的.air文件夹路径下,在拷贝代码的时候自动粘贴图片资源,难免会有无用的图片资源生成,这里把清理资源的函数一并放上。
def clear_extra_image(self):
"""清理多余图片"""
air_case_file_path = self.air_case_file_path
if os.path.isfile(air_case_file_path):
if not self.show_image: # 纯文本
text_list = self.textEdit_air_case.toPlainText().split("\n")
air_case_path = air_case_file_path[:air_case_file_path.rfind("\\")]
pic_list = [file for file in os.listdir(air_case_path) if file.endswith(".png")]
image_list = get_img_list_from_text(text_list, air_case_path, pic_list)
else: # 富文本
row_list = search_img_in_html(self.textEdit_air_case.toHtml())
image_list = []
for row in row_list:
img_path = get_img_from_html(self.textEdit_air_case.toHtml(), row)[0]
plain_line = self.textEdit_air_case.document().findBlockByLineNumber(row).text()
text_line = get_text_from_img(plain_line, self.textEdit_air_case.toHtml(), row)
image_list.append((img_path, text_line, row))
air_case_path = air_case_file_path[:air_case_file_path.rfind('\\')]
pic_list = [os.path.join(air_case_path, file) for file in os.listdir(air_case_path) if
file.endswith(".png")]
extra_pic_list = [pic for pic in pic_list if pic not in [img[0] for img in image_list]]
if extra_pic_list:
print("当前用例路径下多余图片:")
for pic in extra_pic_list:
#self.textBrowser.append("<img src='" + pic + "'/>" + "<br>")#这里是我自己的日志输出textBrowser
os.remove(pic)
print("已删除")
小结
本文通过字符串处理的方式实现代码图片名的提取,通过shutil库方法拷贝图片资源,实现了代码内容拷贝时自动拷贝图片资源,省去了手动复制图片资源的步骤。
后续可以考虑弃用airtest的处理方式,将图片资源统一存到一个文件夹形成测试素材资源库,方便图片资源的复用与管理。