mirror of
https://gitee.com/mao-peng/MangoTestingPlatform.git
synced 2025-12-06 11:59:15 +08:00
优化了执行器的全局异常捕获;修改了介绍文件;
This commit is contained in:
BIN
API执行演示.gif
Normal file
BIN
API执行演示.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -4,8 +4,8 @@
|
|||||||
# @Time : 2023-07-15 11:57
|
# @Time : 2023-07-15 11:57
|
||||||
# @Author : 毛鹏
|
# @Author : 毛鹏
|
||||||
|
|
||||||
from autotest.ui.base_tools.web import WebDevice
|
|
||||||
from autotest.ui.base_tools.android import AndroidDriver
|
from autotest.ui.base_tools.android import AndroidDriver
|
||||||
|
from autotest.ui.base_tools.web import WebDevice
|
||||||
from enums.tools_enum import StatusEnum
|
from enums.tools_enum import StatusEnum
|
||||||
from enums.ui_enum import ElementOperationEnum, DriveTypeEnum
|
from enums.ui_enum import ElementOperationEnum, DriveTypeEnum
|
||||||
from exceptions.tools_exception import SyntaxErrorError, MysqlQueryIsNullError
|
from exceptions.tools_exception import SyntaxErrorError, MysqlQueryIsNullError
|
||||||
@@ -13,6 +13,7 @@ from exceptions.ui_exception import *
|
|||||||
from models.socket_model.ui_model import ElementResultModel, ElementModel
|
from models.socket_model.ui_model import ElementResultModel, ElementModel
|
||||||
from tools.decorator.async_retry import async_retry
|
from tools.decorator.async_retry import async_retry
|
||||||
from tools.desktop.signal_send import SignalSend
|
from tools.desktop.signal_send import SignalSend
|
||||||
|
from tools.log_collector import log
|
||||||
from tools.message.error_msg import *
|
from tools.message.error_msg import *
|
||||||
|
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ class ElementMain(WebDevice, AndroidDriver):
|
|||||||
elif self.drive_type == DriveTypeEnum.DESKTOP.value:
|
elif self.drive_type == DriveTypeEnum.DESKTOP.value:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
log.error('不存在的设备类型')
|
||||||
raise Exception('不存在的设备类型')
|
raise Exception('不存在的设备类型')
|
||||||
|
|
||||||
async def assertion_element(self):
|
async def assertion_element(self):
|
||||||
@@ -88,6 +90,7 @@ class ElementMain(WebDevice, AndroidDriver):
|
|||||||
elif self.drive_type == DriveTypeEnum.DESKTOP.value:
|
elif self.drive_type == DriveTypeEnum.DESKTOP.value:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
log.error('不存在的设备类型')
|
||||||
raise Exception('不存在的设备类型')
|
raise Exception('不存在的设备类型')
|
||||||
|
|
||||||
async def __ope(self, name, ope_type):
|
async def __ope(self, name, ope_type):
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from exceptions.ui_exception import *
|
|||||||
from models.socket_model.ui_model import ElementModel, ElementResultModel
|
from models.socket_model.ui_model import ElementModel, ElementResultModel
|
||||||
from tools.assertion.sql_assertion import SqlAssertion
|
from tools.assertion.sql_assertion import SqlAssertion
|
||||||
from tools.message.error_msg import *
|
from tools.message.error_msg import *
|
||||||
|
from tools.public_methods import sync_global_exception
|
||||||
|
|
||||||
|
|
||||||
class AndroidDriver(UiautomatorEquipment,
|
class AndroidDriver(UiautomatorEquipment,
|
||||||
@@ -60,7 +61,7 @@ class AndroidDriver(UiautomatorEquipment,
|
|||||||
except UiObjectNotFoundError as error:
|
except UiObjectNotFoundError as error:
|
||||||
raise ElementLocatorError(*ERROR_MSG_0032, value=(self.element_model.name,), error=error, )
|
raise ElementLocatorError(*ERROR_MSG_0032, value=(self.element_model.name,), error=error, )
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print(error)
|
sync_global_exception(error, False)
|
||||||
else:
|
else:
|
||||||
if 'locating' in self.element_model.ope_value:
|
if 'locating' in self.element_model.ope_value:
|
||||||
del self.element_model.ope_value['locating']
|
del self.element_model.ope_value['locating']
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
# @Time : 2023-09-09 23:17
|
# @Time : 2023-09-09 23:17
|
||||||
# @Author : 毛鹏
|
# @Author : 毛鹏
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import uiautomator2
|
import uiautomator2
|
||||||
|
|
||||||
from autotest.ui.base_tools.base_data import BaseData
|
from autotest.ui.base_tools.base_data import BaseData
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class UiautomatorEquipment(BaseData):
|
|||||||
def a_swipe_left(self):
|
def a_swipe_left(self):
|
||||||
"""获取屏幕开关状态"""
|
"""获取屏幕开关状态"""
|
||||||
self.android.info.get('screenOn')
|
self.android.info.get('screenOn')
|
||||||
|
|
||||||
#
|
#
|
||||||
# def a_home(self):
|
# def a_home(self):
|
||||||
# """返回首页"""
|
# """返回首页"""
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ from tools.data_processor.sql_cache import SqlCache
|
|||||||
from tools.desktop.signal_send import SignalSend
|
from tools.desktop.signal_send import SignalSend
|
||||||
from tools.log_collector import log
|
from tools.log_collector import log
|
||||||
from tools.message.error_msg import ERROR_MSG_0008, ERROR_MSG_0009, ERROR_MSG_0042, ERROR_MSG_0045, ERROR_MSG_0047
|
from tools.message.error_msg import ERROR_MSG_0008, ERROR_MSG_0009, ERROR_MSG_0042, ERROR_MSG_0045, ERROR_MSG_0047
|
||||||
|
from tools.public_methods import async_global_exception
|
||||||
"""
|
"""
|
||||||
python -m uiautomator2 init
|
python -m uiautomator2 init
|
||||||
python -m weditor
|
python -m weditor
|
||||||
@@ -180,7 +180,7 @@ class DriverObject:
|
|||||||
await ClientWebSocket.async_send(msg="发送录制接口", func_name=ApiSocketEnum.RECORDING_API.value,
|
await ClientWebSocket.async_send(msg="发送录制接口", func_name=ApiSocketEnum.RECORDING_API.value,
|
||||||
func_args=api_info)
|
func_args=api_info)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
log.error(error)
|
await async_global_exception(error)
|
||||||
|
|
||||||
|
|
||||||
async def test_main():
|
async def test_main():
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import asyncio
|
|||||||
|
|
||||||
from autotest.ui.base_tools.driver_object import DriverObject
|
from autotest.ui.base_tools.driver_object import DriverObject
|
||||||
from autotest.ui.service.cases import CasesMain
|
from autotest.ui.service.cases import CasesMain
|
||||||
from enums.tools_enum import ClientTypeEnum
|
|
||||||
from enums.ui_enum import DriveTypeEnum
|
from enums.ui_enum import DriveTypeEnum
|
||||||
from models.socket_model.ui_model import CaseModel
|
from models.socket_model.ui_model import CaseModel
|
||||||
from service.socket_client import ClientWebSocket
|
|
||||||
from tools.log_collector import log
|
from tools.log_collector import log
|
||||||
|
from tools.public_methods import async_global_exception
|
||||||
|
|
||||||
|
|
||||||
class CaseRun(DriverObject):
|
class CaseRun(DriverObject):
|
||||||
@@ -55,9 +54,7 @@ class CaseRun(DriverObject):
|
|||||||
log.error('自动化类型不存在,请联系管理员检查!')
|
log.error('自动化类型不存在,请联系管理员检查!')
|
||||||
await obj.case_page_step()
|
await obj.case_page_step()
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
log.error(str(error))
|
await async_global_exception(error)
|
||||||
await ClientWebSocket.async_send(code=300,
|
|
||||||
msg="执行元素步骤时发生未知异常,请检查数据或者联系管理员",
|
|
||||||
is_notice=ClientTypeEnum.WEB.value)
|
|
||||||
finally:
|
finally:
|
||||||
self.running_tasks -= 1
|
self.running_tasks -= 1
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from models.socket_model.ui_model import CaseModel, CaseResultModel, PageStepsMo
|
|||||||
from service.socket_client import ClientWebSocket
|
from service.socket_client import ClientWebSocket
|
||||||
from tools.desktop.signal_send import SignalSend
|
from tools.desktop.signal_send import SignalSend
|
||||||
from tools.log_collector import log
|
from tools.log_collector import log
|
||||||
|
from tools.public_methods import async_global_exception
|
||||||
|
|
||||||
class CasesMain(StepsMain):
|
class CasesMain(StepsMain):
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ class CasesMain(StepsMain):
|
|||||||
except MangoActuatorError as error:
|
except MangoActuatorError as error:
|
||||||
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{error.msg}'
|
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{error.msg}'
|
||||||
self.case_result.status = StatusEnum.FAIL.value
|
self.case_result.status = StatusEnum.FAIL.value
|
||||||
log.error(error.msg)
|
log.warning(error.msg)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if page_steps_result_model.status:
|
if page_steps_result_model.status:
|
||||||
@@ -62,17 +62,14 @@ class CasesMain(StepsMain):
|
|||||||
else:
|
else:
|
||||||
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{page_steps_result_model.error_message}'
|
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{page_steps_result_model.error_message}'
|
||||||
self.case_result.status = StatusEnum.FAIL.value
|
self.case_result.status = StatusEnum.FAIL.value
|
||||||
log.error(page_steps_result_model.error_message)
|
log.warning(page_steps_result_model.error_message)
|
||||||
break
|
break
|
||||||
await self.case_posterior(self.case_model.posterior_sql)
|
await self.case_posterior(self.case_model.posterior_sql)
|
||||||
except MangoActuatorError as error:
|
except MangoActuatorError as error:
|
||||||
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{error.msg}'
|
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{error.msg}'
|
||||||
self.case_result.status = StatusEnum.FAIL.value
|
self.case_result.status = StatusEnum.FAIL.value
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
log.error(str(error))
|
await async_global_exception(error)
|
||||||
await ClientWebSocket.async_send(code=300,
|
|
||||||
msg="执行元素步骤时发生未知异常,请检查数据或者联系管理员",
|
|
||||||
is_notice=ClientTypeEnum.WEB.value)
|
|
||||||
else:
|
else:
|
||||||
msg = self.case_result.error_message if self.case_result.error_message else f'用例<{self.case_model.name}>测试完成'
|
msg = self.case_result.error_message if self.case_result.error_message else f'用例<{self.case_model.name}>测试完成'
|
||||||
await ClientWebSocket.async_send(
|
await ClientWebSocket.async_send(
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class StepsMain(ElementMain):
|
|||||||
return self.page_step_result_model
|
return self.page_step_result_model
|
||||||
|
|
||||||
async def __error(self, error: MangoActuatorError):
|
async def __error(self, error: MangoActuatorError):
|
||||||
log.error(
|
log.warning(
|
||||||
f'元素操作失败,element_model:{self.element_model.dict()},element_test_result:{self.element_test_result.dict()},error:{error.msg}')
|
f'元素操作失败,element_model:{self.element_model.dict()},element_test_result:{self.element_test_result.dict()},error:{error.msg}')
|
||||||
path = rf'{InitPath.failure_screenshot_file}\{self.element_model.name}{RandomTimeData.get_deta_hms()}.jpg'
|
path = rf'{InitPath.failure_screenshot_file}\{self.element_model.name}{RandomTimeData.get_deta_hms()}.jpg'
|
||||||
SignalSend.notice_signal_c(f'''元素名称:{self.element_test_result.ele_name}
|
SignalSend.notice_signal_c(f'''元素名称:{self.element_test_result.ele_name}
|
||||||
|
|||||||
95
MangoActuator/dd.md
Normal file
95
MangoActuator/dd.md
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# ✨️ 概述
|
||||||
|
|
||||||
|
DrissionPage 是一个基于 python 的网页自动化工具。
|
||||||
|
|
||||||
|
它既能控制浏览器,也能收发数据包,还能把两者合而为一。
|
||||||
|
|
||||||
|
可兼顾浏览器自动化的便利性和 requests 的高效率。
|
||||||
|
|
||||||
|
它功能强大,内置无数人性化设计和便捷功能。
|
||||||
|
|
||||||
|
它的语法简洁而优雅,代码量少,对新手友好。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
官方网站:[https://drissionpage.cn](https://drissionpage.cn)
|
||||||
|
|
||||||
|
<a href='https://gitee.com/g1879/DrissionPage/stargazers'><img src='https://gitee.com/g1879/DrissionPage/badge/star.svg?theme=dark' alt='star'></img></a> <a href='https://gitee.com/g1879/DrissionPage/members'><img src='https://gitee.com/g1879/DrissionPage/badge/fork.svg?theme=dark' alt='fork'></img></a>
|
||||||
|
|
||||||
|
项目地址:[gitee](https://gitee.com/g1879/DrissionPage) | [github](https://github.com/g1879/DrissionPage)
|
||||||
|
|
||||||
|
您的星星是对我最大的支持💖
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
支持系统:Windows、Linux、Mac
|
||||||
|
|
||||||
|
python 版本:3.6 及以上
|
||||||
|
|
||||||
|
支持浏览器:Chromium 内核浏览器(如 Chrome 和 Edge),electron 应用
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 🛠 如何使用
|
||||||
|
|
||||||
|
**📖 使用文档:** [点击查看](https://g1879.gitee.io/drissionpagedocs)
|
||||||
|
|
||||||
|
**交流 QQ 群:** 636361957
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 💡 理念
|
||||||
|
|
||||||
|
简洁而强大!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# ☀️ 特性和亮点
|
||||||
|
|
||||||
|
作者经过长期实践,踩过无数坑,总结出的经验全写到这个库里了。
|
||||||
|
|
||||||
|
## 🎇 强大的自研内核
|
||||||
|
|
||||||
|
本库采用全自研的内核,内置无数实用功能,对常用功能作了整合和优化,对比 selenium,有以下优点:
|
||||||
|
|
||||||
|
- 不基于 webdriver
|
||||||
|
- 无需为不同版本的浏览器下载不同的驱动
|
||||||
|
- 运行速度更快
|
||||||
|
- 可以跨`<iframe>`查找元素,无需切入切出
|
||||||
|
- 把`<iframe>`看作普通元素,获取后可直接在其中查找元素,逻辑更清晰
|
||||||
|
- 可以同时操作浏览器中的多个标签页,即使标签页为非激活状态,无需切换
|
||||||
|
- 可以直接读取浏览器缓存来保存图片,无需用 GUI 点击另存
|
||||||
|
- 可以对整个网页截图,包括视口外的部分(90以上版本浏览器支持)
|
||||||
|
- 可处理非`open`状态的 shadow-root
|
||||||
|
|
||||||
|
## 🎇 亮点功能
|
||||||
|
|
||||||
|
除了以上优点,本库还内置了无数人性化设计。
|
||||||
|
|
||||||
|
- 极简的语法规则。集成大量常用功能,代码更优雅
|
||||||
|
- 定位元素更加容易,功能更强大稳定
|
||||||
|
- 无处不在的等待和自动重试功能。使不稳定的网络变得易于控制,程序更稳定,编写更省心
|
||||||
|
- 提供强大的下载工具。操作浏览器时也能享受快捷可靠的下载功能
|
||||||
|
- 允许反复使用已经打开的浏览器。无须每次运行从头启动浏览器,调试超方便
|
||||||
|
- 使用 ini 文件保存常用配置,自动调用,提供便捷的设置,远离繁杂的配置项
|
||||||
|
- 内置 lxml 作为解析引擎,解析速度成几个数量级提升
|
||||||
|
- 使用 POM 模式封装,可直接用于测试,便于扩展
|
||||||
|
- 高度集成的便利功能,从每个细节中体现
|
||||||
|
- 还有很多细节,这里不一一列举,欢迎实际使用中体验:)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 🖐🏻 免责声明
|
||||||
|
|
||||||
|
禁止将 DrissionPage 应用到任何可能会违反法律规定和道德约束的项目中。
|
||||||
|
友善使用 DrissionPage,遵守蜘蛛协议,禁止将 DrissionPage 用于任何可能有损他人的项目中。
|
||||||
|
如您选择使用 DrissionPage 即代表您遵守此协议,作者不承担任何由于您违反此协议带来任何的法律风险和损失。
|
||||||
|
同时,作者不对 DrissionPage 可能存在的缺陷导致的损失承担任何责任,一切后果由您承担。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# ☕ 请我喝咖啡
|
||||||
|
|
||||||
|
如果本项目对您有所帮助,不妨请作者我喝杯咖啡 :)
|
||||||
|
|
||||||
|

|
||||||
@@ -1,85 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
from PySide6.QtGui import QAction, QIcon, QKeySequence, QShortcut
|
|
||||||
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QMenu, QSystemTrayIcon
|
|
||||||
|
|
||||||
|
|
||||||
class MyWindow(QMainWindow):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.setWindowTitle("最小化系统托盘")
|
|
||||||
self.resize(400, 300)
|
|
||||||
|
|
||||||
# 创建按钮并连接到最小化到系统托盘的方法
|
|
||||||
self.button = QPushButton("Minimize to Tray")
|
|
||||||
self.button.clicked.connect(self.minimize_to_tray)
|
|
||||||
self.setCentralWidget(self.button)
|
|
||||||
|
|
||||||
# 初始化系统托盘相关的对象和菜单项
|
|
||||||
self._restore_action = QAction()
|
|
||||||
self._quit_action = QAction()
|
|
||||||
self._tray_icon_menu = QMenu()
|
|
||||||
self.tray_icon = QSystemTrayIcon(self)
|
|
||||||
self.tray_icon.setIcon(QIcon("trash.png")) # 替换为你的图标路径
|
|
||||||
self.tray_icon.setToolTip("My Application")
|
|
||||||
|
|
||||||
self.create_actions()
|
|
||||||
self.create_tray_icon()
|
|
||||||
self.tray_icon.show()
|
|
||||||
|
|
||||||
# 连接系统托盘图标的激活事件
|
|
||||||
self.tray_icon.activated.connect(self.tray_icon_activated)
|
|
||||||
|
|
||||||
# 应用程序键盘监听
|
|
||||||
self.listen_keyboard()
|
|
||||||
|
|
||||||
def minimize_to_tray(self):
|
|
||||||
# 最小化窗口到系统托盘
|
|
||||||
self.hide()
|
|
||||||
|
|
||||||
def restore_from_tray(self):
|
|
||||||
# 还原窗口
|
|
||||||
if self.isMinimized():
|
|
||||||
self.showNormal()
|
|
||||||
elif self.isMaximized():
|
|
||||||
self.showMaximized()
|
|
||||||
else:
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def tray_icon_activated(self, reason):
|
|
||||||
# 当系统托盘图标被点击时的处理
|
|
||||||
if reason == QSystemTrayIcon.ActivationReason.Trigger:
|
|
||||||
# 如果点击的是触发事件(比如左键单击),则还原窗口
|
|
||||||
self.restore_from_tray()
|
|
||||||
|
|
||||||
def create_actions(self):
|
|
||||||
# 创建菜单项
|
|
||||||
self._restore_action = QAction("显示", self)
|
|
||||||
self._restore_action.triggered.connect(self.restore_from_tray) # "显示"菜单项触发还原窗口的操作
|
|
||||||
self._quit_action = QAction("退出", self)
|
|
||||||
self._quit_action.triggered.connect(QApplication.quit) # "退出"菜单项触发退出应用程序的操作
|
|
||||||
|
|
||||||
def create_tray_icon(self):
|
|
||||||
# 创建系统托盘图标和上下文菜单
|
|
||||||
self._tray_icon_menu = QMenu(self)
|
|
||||||
self._tray_icon_menu.addAction(self._restore_action)
|
|
||||||
self._tray_icon_menu.addSeparator()
|
|
||||||
self._tray_icon_menu.addAction(self._quit_action)
|
|
||||||
self.tray_icon.setContextMenu(self._tray_icon_menu)
|
|
||||||
self.tray_icon.show()
|
|
||||||
|
|
||||||
def listen_keyboard(self):
|
|
||||||
# 键盘监听
|
|
||||||
shortcut = QShortcut(QKeySequence("Esc"), self)
|
|
||||||
# 当按下 Esc 键时隐藏窗口
|
|
||||||
shortcut.activated.connect(self.hide)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = QApplication()
|
|
||||||
app.setQuitOnLastWindowClosed(False)
|
|
||||||
|
|
||||||
window = MyWindow()
|
|
||||||
window.show()
|
|
||||||
|
|
||||||
app.exec()
|
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ from tools.log_collector import log
|
|||||||
|
|
||||||
class MangoActuatorError(Exception):
|
class MangoActuatorError(Exception):
|
||||||
|
|
||||||
def __init__(self, code: int, msg: str, value: tuple = None, error: any = None, is_log: bool = True):
|
def __init__(self, code: int, msg: str, value: tuple = None, error: any = None, is_log: bool = False):
|
||||||
if value:
|
if value:
|
||||||
msg = msg.format(*value)
|
msg = msg.format(*value)
|
||||||
if error and is_log:
|
if error and is_log:
|
||||||
log.error(f'报错提示:{msg}, 报错内容:{error}')
|
log.error(f'报错提示:{msg}, 报错内容:{error}')
|
||||||
else:
|
elif is_log:
|
||||||
log.error(f'报错提示:{msg}')
|
log.warning(f'报错提示:{msg}')
|
||||||
self.code = code
|
self.code = code
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
|||||||
@@ -9,12 +9,9 @@ from enums.tools_enum import ClientTypeEnum, CacheKeyEnum
|
|||||||
from exceptions import MangoActuatorError
|
from exceptions import MangoActuatorError
|
||||||
from models.socket_model.ui_model import PageStepsModel, WEBConfigModel, CaseModel
|
from models.socket_model.ui_model import PageStepsModel, WEBConfigModel, CaseModel
|
||||||
from service.socket_client import ClientWebSocket
|
from service.socket_client import ClientWebSocket
|
||||||
from settings.settings import GLOBAL_EXCEPTION_CAPTURE
|
|
||||||
from tools.data_processor.sql_cache import SqlCache
|
from tools.data_processor.sql_cache import SqlCache
|
||||||
from tools.decorator.convert_args import convert_args
|
from tools.decorator.convert_args import convert_args
|
||||||
from tools.desktop.signal_send import SignalSend
|
from tools.public_methods import async_global_exception
|
||||||
from tools.log_collector import log
|
|
||||||
|
|
||||||
|
|
||||||
class UIConsumer:
|
class UIConsumer:
|
||||||
page_steps: PageSteps = None
|
page_steps: PageSteps = None
|
||||||
@@ -38,14 +35,7 @@ class UIConsumer:
|
|||||||
msg=error.msg,
|
msg=error.msg,
|
||||||
is_notice=ClientTypeEnum.WEB.value)
|
is_notice=ClientTypeEnum.WEB.value)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
if GLOBAL_EXCEPTION_CAPTURE:
|
await async_global_exception(error)
|
||||||
SignalSend.notice_signal_c(f'发送未知异常,请联系管理员!异常类型:{type(error)}')
|
|
||||||
log.error(f'发送未知异常,请联系管理员!异常类型:{type(error)},错误详情:{str(error)}')
|
|
||||||
await ClientWebSocket.async_send(code=300,
|
|
||||||
msg="执行UI步骤时,发送未知异常!请联系管理员",
|
|
||||||
is_notice=ClientTypeEnum.WEB.value)
|
|
||||||
else:
|
|
||||||
raise error
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@convert_args(WEBConfigModel)
|
@convert_args(WEBConfigModel)
|
||||||
@@ -60,14 +50,7 @@ class UIConsumer:
|
|||||||
cls.page_steps = PageSteps(data.project)
|
cls.page_steps = PageSteps(data.project)
|
||||||
await cls.page_steps.new_web_obj(data)
|
await cls.page_steps.new_web_obj(data)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
if GLOBAL_EXCEPTION_CAPTURE:
|
await async_global_exception(error)
|
||||||
SignalSend.notice_signal_c(f'发送未知异常,请联系管理员!异常类型:{type(error)}')
|
|
||||||
log.error(f'发送未知异常,请联系管理员!异常类型:{type(error)},错误详情:{str(error)}')
|
|
||||||
await ClientWebSocket.async_send(code=300,
|
|
||||||
msg="实例化浏览器对象时,发送未知异常!请联系管理员",
|
|
||||||
is_notice=ClientTypeEnum.WEB.value)
|
|
||||||
else:
|
|
||||||
raise error
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@convert_args(CaseModel)
|
@convert_args(CaseModel)
|
||||||
@@ -86,12 +69,4 @@ class UIConsumer:
|
|||||||
cls.case_run = CaseRun(max_tasks)
|
cls.case_run = CaseRun(max_tasks)
|
||||||
await cls.case_run.queue.put(data)
|
await cls.case_run.queue.put(data)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
if GLOBAL_EXCEPTION_CAPTURE:
|
await async_global_exception(error)
|
||||||
SignalSend.notice_signal_c(f'发送未知异常,请联系管理员!异常类型:{type(error)}')
|
|
||||||
log.error(f'发送未知异常,请联系管理员!异常类型:{type(error)},错误详情:{str(error)}')
|
|
||||||
await ClientWebSocket.async_send(code=300,
|
|
||||||
msg="实例化浏览器对象时,发送未知异常!请联系管理员",
|
|
||||||
is_notice=ClientTypeEnum.WEB.value)
|
|
||||||
else:
|
|
||||||
raise error
|
|
||||||
|
|
||||||
|
|||||||
@@ -134,8 +134,8 @@ class ClientWebSocket:
|
|||||||
try:
|
try:
|
||||||
out = json.loads(recv_json)
|
out = json.loads(recv_json)
|
||||||
log.info(f'接收的消息提示:{out["msg"]}')
|
log.info(f'接收的消息提示:{out["msg"]}')
|
||||||
if out['data']:
|
# if out['data']:
|
||||||
log.debug(f"接收的数据:{json.dumps(out['data'], ensure_ascii=False)}")
|
# log.debug(f"接收的数据:{json.dumps(out['data'], ensure_ascii=False)}")
|
||||||
return SocketDataModel(**out)
|
return SocketDataModel(**out)
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
log.error(f'服务器发送的数据不可被序列化,请检查服务器发送的数据:{recv_json}')
|
log.error(f'服务器发送的数据不可被序列化,请检查服务器发送的数据:{recv_json}')
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Project: auto_test
|
|
||||||
# @Description:
|
|
||||||
# @Time : 2023-08-11 11:08
|
|
||||||
# @Author : 毛鹏
|
|
||||||
# ↓-----------------------------------数据源选择-----------------------------------↓
|
|
||||||
GLOBAL_EXCEPTION_CAPTURE = False
|
|
||||||
# ↑-----------------------------------数据源选择-----------------------------------↑
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print("Global exception capture".upper())
|
|
||||||
@@ -30,7 +30,7 @@ ERROR_MSG_0024 = (324, '上传文件的元素必须要是input标签中的')
|
|||||||
ERROR_MSG_0025 = (325, '用例步骤的数据取不到,请检查用例数据或联系管理员')
|
ERROR_MSG_0025 = (325, '用例步骤的数据取不到,请检查用例数据或联系管理员')
|
||||||
ERROR_MSG_0026 = (326, '文件不存在')
|
ERROR_MSG_0026 = (326, '文件不存在')
|
||||||
ERROR_MSG_0027 = (
|
ERROR_MSG_0027 = (
|
||||||
327, '您元素的操作内容中没有任何的数据,请检查:1.页面步骤详情中字段->元素操作值是否是空,是空可能是你删除了,也可能是执行器的操作选项没有同步需要点击执行器的同步发送缓存数据;2.元素表达式错误导致查询不到元素;')
|
327, '您元素的操作内容中没有任何的数据,请检查:1.页面步骤详情中字段->元素操作值是否是空,是空可能是你删除了,也可能是执行器的操作选项没有同步需要点击执行器的同步发送缓存数据;2.元素表达式错误导致查询不到元素;')
|
||||||
ERROR_MSG_0028 = (328, '一个元素内只能包含一个需要被替换的内容')
|
ERROR_MSG_0028 = (328, '一个元素内只能包含一个需要被替换的内容')
|
||||||
ERROR_MSG_0029 = (329, '页面无元素:{} 表达式:{}')
|
ERROR_MSG_0029 = (329, '页面无元素:{} 表达式:{}')
|
||||||
ERROR_MSG_0030 = (330, '断言时没有找到元素')
|
ERROR_MSG_0030 = (330, '断言时没有找到元素')
|
||||||
|
|||||||
31
MangoActuator/tools/public_methods.py
Normal file
31
MangoActuator/tools/public_methods.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Project: auto_test
|
||||||
|
# @Description:
|
||||||
|
# @Time : 2024-04-29 16:27
|
||||||
|
# @Author : 毛鹏
|
||||||
|
from enums.tools_enum import ClientTypeEnum
|
||||||
|
from service.socket_client import ClientWebSocket
|
||||||
|
from tools.desktop.signal_send import SignalSend
|
||||||
|
from tools.log_collector import log
|
||||||
|
|
||||||
|
|
||||||
|
async def async_global_exception(error, _is=True):
|
||||||
|
if _is:
|
||||||
|
SignalSend.notice_signal_c(f'发送未知异常,请联系管理员!异常类型:{type(error)}')
|
||||||
|
log.error(f'发送未知异常,请联系管理员!异常类型:{type(error)},错误详情:{str(error)}')
|
||||||
|
await ClientWebSocket.async_send(code=300,
|
||||||
|
msg="发生未知异常!请联系管理员",
|
||||||
|
is_notice=ClientTypeEnum.WEB.value)
|
||||||
|
else:
|
||||||
|
raise error
|
||||||
|
|
||||||
|
|
||||||
|
def sync_global_exception(error, _is=True):
|
||||||
|
if _is:
|
||||||
|
SignalSend.notice_signal_c(f'发送未知异常,请联系管理员!异常类型:{type(error)}')
|
||||||
|
log.error(f'发送未知异常,请联系管理员!异常类型:{type(error)},错误详情:{str(error)}')
|
||||||
|
ClientWebSocket.sync_send(code=300,
|
||||||
|
msg="发生未知异常!请联系管理员",
|
||||||
|
is_notice=ClientTypeEnum.WEB.value)
|
||||||
|
else:
|
||||||
|
raise error
|
||||||
@@ -20,8 +20,8 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||||||
|
|
||||||
mysql_db_name = 'mango_server'
|
mysql_db_name = 'mango_server'
|
||||||
mysql_user = 'root'
|
mysql_user = 'root'
|
||||||
# mysql_password = 'root'
|
mysql_password = 'root'
|
||||||
mysql_password = 'mP123456&'
|
# mysql_password = 'mP123456&'
|
||||||
mysql_ip = 'localhost'
|
mysql_ip = 'localhost'
|
||||||
# mysql_ip = '36.213.11.72'
|
# mysql_ip = '36.213.11.72'
|
||||||
mysql_port = 3306
|
mysql_port = 3306
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -47,13 +47,9 @@
|
|||||||
* 所有功能介绍
|
* 所有功能介绍
|
||||||

|

|
||||||
* UI用例执行过程及测试报告
|
* UI用例执行过程及测试报告
|
||||||
|

|
||||||
* API用例执行过程及测试报告
|
* API用例执行过程及测试报告
|
||||||
|

|
||||||
#### 加作者微信,进芒果自动化测试群(记得备注:git芒果测试平台。否则可能会不通过哦)
|
#### 加作者微信,进芒果自动化测试群(记得备注:git芒果测试平台。否则可能会不通过哦)
|
||||||
如果觉得项目对你有帮助,那就请我喝咖啡!
|
如果觉得项目对你有帮助,那就请我喝咖啡!
|
||||||
<div style="display:flex;">
|

|
||||||
<img src="img_8.png" style="width:45%;">
|
|
||||||
<div style="width:10%"></div>
|
|
||||||
<img src="微信.jpg" style="width:45%;">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|||||||
BIN
UI执行演示.gif
Normal file
BIN
UI执行演示.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.7 MiB |
Reference in New Issue
Block a user