使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 43--添加allure测试报告显示信息和其他封装方法
测试学习记录仅供参考添加allure测试报告显示信息增加测试报告首页环境信息和修改 allure 测试报告显示图标一、增加测试报告首页环境信息1、在项目根目录下创建一个名称为 environment.xml 的配置文件输入相关的环境配置信息在生成测试报告时会读取此配置文件用于在allure 测试报告首页展示environment parameter keysystem/key valueWindows 10/value /parameter parameter keyPython version/key valuepython 3.8.10/value /parameter parameter keyallure version/key valueallure-pytest 2.13.8/value /parameter parameter key测试项目/key value开源电商商城系统/value /parameter parameter key团队/key valueXXXXXX/value /parameter parameter key时间/key valueXXXXXXXX/value /parameter /environment2、优化 run.py 文件内容import pytest import os import shutil if __name__ __main__: pytest.main() shutil.copy(./environment.xml, ./report/temp) os.system(allure serve ./report/temp)二、修改 Allure 显示图标3、找到 allure.yml 文件python 安装文件路径下 allure 资源包文件夹目录中--烦请根据自身实际情况例 C:\Users\Administrator\AppData\Local\Programs\Python\Python38\Lib\site-packages\allure-2.13.8\config4、选中 allure.yml 文件以记事本格式打开增加“- custom-logo-plugin ”后保存自行修改5、将要显示的图片放到相关的对应文件夹下烦请自行设置C:\Users\Administrator\AppData\Local\Programs\Python\Python38\Lib\site-packages\allure-2.13.8\plugins\custom-logo-plugin\static6、打开 styles.css 文件打开方式自行选择例如记事本格式、写字板、Notepad等等7、修改 styles.css 文件内容并保存烦请根据实际图片大小和显示的内容自行设置testicon.png图标的名字测试报告图标旁要显示的内容.side-nav__brand { background: url(testicon.png) no-repeat left center !important; margin-left: 10px; height: 40px; background-size: contain !important; } .side-nav__brand span { display: none; } .side-nav__brand:after { content: 测试报告; margin-left: 20px; }8、运行主函数 run.py 文件查看测试报告显示结果封装模拟鼠标键盘的操作已定位到元素但无法进行输入操作的最终解决方法ElementNotInteractableException 是一个常见的异常元素无法进行交互的异常通常发生在尝试与网页上的某个元素进行交互时但是此元素不可交互说明前端开发人员把元素设置成了隐藏、禁用、不可操作等一系列防自动化参数、防爬虫手段机制等此时调用 webdriver 里面的 send_keys 输入操作是无法输入的封装一个通过模拟鼠标、键盘的输入操作进行输入内容来解决无法进行输入的问题封装方法封装模拟鼠标、键盘的输入方法1、 优化项目根目录 util_tools 软件包下 basePage.py 文件封装 模拟鼠标键盘的输入 方法可参照webdriver 中的输入方法进行封装1、定义函数方法 def send_keys_actions(self):2、跟 send_keys 方法一样需要传两个参数def send_keys_actions(self, locator: tuple, data):3、先找到元素通过调用已经封装好的方法 element self.location_element(*locator)4、调用模拟鼠标键盘的类ActionChains()5、传入浏览器对象ActionChains(self.__driver)6、调用 move_to_element() 方法把找到的 element 元素传进来 move_to_element(element)7、点 click()ActionChains(self.__driver).move_to_element(element).click()8、再点 send_keys()ActionChains(self.__driver).move_to_element(element).click().send_keys()9、输入 data 内容ActionChains(self.__driver).move_to_element(element).click().send_keys(data)10、提交动作链ActionChains(self.__driver).move_to_element(element).click().send_keys(data).perform()11、参照 webdriver 的 send_keys 输入方法添加异常和日志信息def send_keys_actions(self, locator: tuple, data): 模拟鼠标键盘的输入操作 :param locator: tuple定位元素信息元组类型 :param data: 输入的内容 :return: try: element self.location_element(*locator) ActionChains(self.__driver).move_to_element(element).click().send_keys(data).perform() logs.info(f元素被输入内容{locator}输入的内容为{data}) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e模拟鼠标、键盘的操作把页面滑动到最下面打开页面之后把页面滑动到最下面2、使用window.scrollTo方法通过调用window.scrollTo方法将页面滚动到指定位置。第一个参数表示水平滚动位置第二个参数表示垂直滚动位置。这种方法适用于需要精确控制滚动位置的情况。需要注意的是这种方法在使用时应确保页面内容已经加载完毕否则可能无法正确获取到页面高度或元素位置。document.body.scrollHeight返回整个文档的高度包括不可见的部分然后scrollTo(x, y)方法将页面滚动到指定的x和y坐标其中x通常为0表示水平滚动位置而y为目标位置。def scroll_to_button(self): 使用JavaScript滚动页面到最底部 # self.__driver.execute_script(window.scrollTo(0, document.documentElement.scrollHeight);) self.__driver.execute_script(window.scrollTo(0, document.body.scrollHeight);)3、逐步优化完善 basePage.py 文件# 导包 from pyxnat.core.uriutil import file_path from selenium import webdriver from selenium.common import NoSuchElementException, TimeoutException from selenium.webdriver.common.by import By from time import sleep from selenium.webdriver.support import expected_conditions as ec from selenium.webdriver.support.wait import WebDriverWait from config import setting from util_tools.logs_util.recordlog import logs from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from datetime import datetime import pytesseract from PIL import Image from selenium.webdriver.support.ui import Select from util_tools.handle_data.configParse import ConfigParse class BasePage(object): def __init__(self, driver): self.__driver driver self.__wait WebDriverWait(self.__driver, setting.WAIT_TIME) self.conf ConfigParse() def window_max(self): self.__driver.maximize_window() def window_full(self): self.__driver.fullscreen_window() def screenshot(self): self.__driver.get_screenshot_as_png() def open_url(self, url): if url.startswith(http) or url.startswith(https): self.__driver.get(url) logs.info(f打开页面{url}) else: new_url self.conf.get_host(host) url self.__driver.get(new_url) logs.info(f打开页面{new_url}) def get_tag_text(self, locator: tuple): try: element self.location_element(*locator) element_text element.text logs.info(f获取标签文本内容{element_text}) return element_text except Exception as e: logs.error(f获取标签文本内容出现异常原因为{str(e)}) property def current_url(self): return self.__driver.current_url property def title(self): return self.__driver.title def refresh(self): self.__driver.refresh() def scroll_to_button(self): self.__driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) property def switch_to(self): return self.__driver.switch_to def iframe(self, frame): try: self.switch_to.frame(frame) logs.info(f切换到{frame}--iframe内部框架中) except: logs.error(切换到iframe框架失败) def switch_to_new_tab(self): try: original_window self.__driver.window_handles[0] all_window self.__driver.window_handles new_window None for window in all_window: if window ! original_window: new_window window break if new_window: self.switch_to.window(new_window) logs.info(成功切换到新标签页) except TimeoutException: logs.error(等待新标签页打开超时。) except NoSuchElementException: logs.error(未找到新标签页句柄。) except Exception as e: logs.error(f切换窗口时发生异常{str(e)}) def exit_iframe(self): self.switch_to.default_content() property def alert(self): return self.__wait.until(ec.alert_is_present()) def alert_confirm(self): self.alert.accept() def alert_cancel(self): self.alert.dismiss() def location_element(self, by, value): try: element self.__wait.until(ec.presence_of_element_located((by, value))) logs.info(f找到元素{by}{value}) return element except Exception as e: logs.error(f未找到元素{by}{value}) raise e def location_elements(self, by, value): try: self.__wait.until(ec.presence_of_all_elements_located((by, value))) elements self.__driver.find_elements(by, value) logs.info(f找到元素列表{by}{value}) return elements except Exception as e: logs.error(f未找到元素列表{by}{value}) raise e def click(self, locator: tuple, forceFalse): try: element self.location_element(*locator) if not force: self.__driver.execute_script(arguments[0].click(), element) else: self.__driver.execute_script(arguments[0].click({force:true}), element) logs.info(f元素被点击{locator}) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def send_keys(self, locator: tuple, data): try: element self.location_element(*locator) element.send_keys(data) logs.info(f元素被输入内容{locator}输入的内容为{data}) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def send_keys_actions(self, locator: tuple, data): try: element self.location_element(*locator) ActionChains(self.__driver).move_to_element(element).click().send_keys(data).perform() logs.info(f元素被输入内容{locator}输入的内容为{data}) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def selects(self, locator: tuple, index): try: select Select(self.location_element(*locator)) select.select_by_index(index) logs.info(f选择第{index}个数据) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def enter(self): try: ActionChains(self.__driver).send_keys(Keys.ENTER).perform() logs.info(按下回车键) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def right_click(self, locator: tuple): try: element self.location_element(*locator) ActionChains(driver).context_click(element).perform() logs.info(执行鼠标右键点击操作) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def double_click(self, locator: tuple): try: element self.location_element(*locator) ActionChains(driver).double_click(element).perform() logs.info(执行鼠标双击操作) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def screenshots(self, image_name): import os current_time datetime.now().strftime(%Y%m%d%H%M%S) file_name f{image_name}-{current_time}.png file_path os.path.join(setting.FILE_PATH.get(screenshot), file_name) self.__driver.get_screenshot_as_file(file_path) def screenshots_png(self): return self.__driver.get_screenshot_as_png() def clear(self, locator: tuple): try: element self.location_element(*locator) element.clear() logs.info(清空文本) except NoSuchElementException as e: logs.error(f元素无法定位{e}) raise e def ocr_captcha(self, locator: tuple): captcha_element self.location_element(*locator) captcha_path setting.FILE_PATH[screenshot] /captcha.png captcha_element.screenshot(captcha_path) captcha_image Image.open(captcha_path) try: captcha_text pytesseract.image_to_string(captcha_image) logs.info(f识别到的验证码为{captcha_text}) return captcha_text except pytesseract.pytesseract.TesseractNotFoundError: logs.error(找不到tesseract这是因为pytesseract模块依赖于TesseractOCR引擎来进行图像识别) def is_element_present(self, locator: tuple): try: self.__wait.until(ec.presence_of_element_located(*locator)) return True except: return False def assert_is_element_present(self, locator: tuple): try: element self.__driver.find_element(*locator) assert element.is_displayed(), 元素不存在 except NoSuchElementException as e: logs.error(f元素未找到{e}) raise AssertionError(元素不存在) def assert_element_not_visible(self, locator: tuple): try: self.__wait.until(ec.invisibility_of_element_located(locator)) except TimeoutException: logs.error(元素可见) def assert_title(self, expect_title): assert expect_title in self.title if __name__ __main__: driver webdriver.Edge()未完待续。。。

相关新闻

使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 44--Pytest框架钩子函数

使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 44--Pytest框架钩子函数

2026/7/7 22:24:40 阅读更多 →
语义分割实战——基于EGEUNet神经网络印章分割系统1:数据集说明(含下载链接)

语义分割实战——基于EGEUNet神经网络印章分割系统1:数据集说明(含下载链接)

2026/7/3 21:00:40 阅读更多 →
语义分割实战——基于EGEUNet神经网络印章分割系统2:含训练测试代码和数据集

语义分割实战——基于EGEUNet神经网络印章分割系统2:含训练测试代码和数据集

2026/7/3 21:00:42 阅读更多 →

最新新闻

OpenCV 4.8 图像压缩实战:3种无损编码算法对比与Python实现

OpenCV 4.8 图像压缩实战:3种无损编码算法对比与Python实现

OpenCV 4.8 图像压缩实战:3种无损编码算法对比与Python实现图像压缩技术是计算机视觉领域的基础能力之一,尤其在嵌入式设备和实时视频传输场景中,高效的压缩算法直接影响系统性能。本文将深入解析游程编码、哈夫曼编码和LZW三种经典无损压缩算…

2026/7/8 22:48:29 阅读更多 →
LabVIEW弹性VI标签消失问题

LabVIEW弹性VI标签消失问题

问题背景 LabVIEW 2020引入的Malleable VI(弹性VI)功能是一项革命性特性,允许创建泛型化的子VI,使其能够根据输入数据类型自动适配不同的实现路径。然而,许多在实际使用中报告了一个令人困扰的现象:Mallea…

2026/7/8 22:48:29 阅读更多 →
拉普拉斯算子图像边缘检测实战:Python+OpenCV 4.x 实现3种卷积核对比

拉普拉斯算子图像边缘检测实战:Python+OpenCV 4.x 实现3种卷积核对比

拉普拉斯算子图像边缘检测实战:PythonOpenCV 4.x 实现3种卷积核对比在计算机视觉领域,边缘检测是一项基础而关键的任务。它能够从图像中提取出物体的轮廓和结构信息,为后续的图像分析、目标识别等高级任务奠定基础。拉普拉斯算子作为一种经典…

2026/7/8 22:48:29 阅读更多 →
TrollInstallerX:解锁iOS设备安装自由的一键式解决方案

TrollInstallerX:解锁iOS设备安装自由的一键式解决方案

TrollInstallerX:解锁iOS设备安装自由的一键式解决方案 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 还在为iOS设备无法自由安装应用而烦恼吗?…

2026/7/8 22:48:29 阅读更多 →
Python Scikit-learn 1.4 对比 MATLAB:3 类数学建模任务效率实测

Python Scikit-learn 1.4 对比 MATLAB:3 类数学建模任务效率实测

Python Scikit-learn 1.4 对比 MATLAB:3 类数学建模任务效率实测当数据科学家面对数学建模任务时,工具选择往往成为第一个关键决策。我曾在一个气象预测项目中同时使用过MATLAB和Python的Scikit-learn,当处理10GB的全球气象站数据时&#xff…

2026/7/8 22:46:28 阅读更多 →
随机森林回归 sklearn 1.4.2 实战:3步调参优化 MSE 降低 30% 的完整流程

随机森林回归 sklearn 1.4.2 实战:3步调参优化 MSE 降低 30% 的完整流程

随机森林回归 sklearn 1.4.2 实战:3步调参优化 MSE 降低 30% 的完整流程在数据科学项目中,随机森林因其出色的表现和鲁棒性成为回归任务的首选算法之一。但许多从业者止步于基础实现,未能充分发挥其潜力。本文将揭示如何通过系统性调参&#…

2026/7/8 22:44:27 阅读更多 →

日新闻

3大核心能力重塑《明日方舟》游戏体验:MAA自动化助手的革命性突破

3大核心能力重塑《明日方舟》游戏体验:MAA自动化助手的革命性突破

3大核心能力重塑《明日方舟》游戏体验:MAA自动化助手的革命性突破 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: …

2026/7/8 0:00:48 阅读更多 →
MyBatis 批量操作深度优化——从 N+1 到批处理的全路径

MyBatis 批量操作深度优化——从 N+1 到批处理的全路径

MyBatis 批量操作深度优化——从 N1 到批处理的全路径 一、从"功能正确"到"性能可接受"——MyBatis 批量操作的三段式进化 MyBatis 在日常增删改查场景中几乎是无感的——实体映射直观、SQL 控制灵活。但当数据量从千级上升到十万级、百万级,许…

2026/7/8 0:00:48 阅读更多 →
工业负载控制方案:TPD2015FN与PIC18F45K22应用解析

工业负载控制方案:TPD2015FN与PIC18F45K22应用解析

1. 工业负载控制方案概述在工业自动化、电机驱动和照明控制等高需求场景中,可靠地控制电感和电阻负载是核心挑战之一。TPD2015FN作为东芝的8通道高端智能功率开关IC,配合PIC18F45K22微控制器,能够构建一套稳定、高效的负载控制系统。这套组合…

2026/7/8 0:02:48 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/8 16:14:06 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/7 12:34:47 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/8 16:59:55 阅读更多 →

月新闻