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
|
||||
# @Author : 毛鹏
|
||||
|
||||
from autotest.ui.base_tools.web import WebDevice
|
||||
from autotest.ui.base_tools.android import AndroidDriver
|
||||
from autotest.ui.base_tools.web import WebDevice
|
||||
from enums.tools_enum import StatusEnum
|
||||
from enums.ui_enum import ElementOperationEnum, DriveTypeEnum
|
||||
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 tools.decorator.async_retry import async_retry
|
||||
from tools.desktop.signal_send import SignalSend
|
||||
from tools.log_collector import log
|
||||
from tools.message.error_msg import *
|
||||
|
||||
|
||||
@@ -76,6 +77,7 @@ class ElementMain(WebDevice, AndroidDriver):
|
||||
elif self.drive_type == DriveTypeEnum.DESKTOP.value:
|
||||
pass
|
||||
else:
|
||||
log.error('不存在的设备类型')
|
||||
raise Exception('不存在的设备类型')
|
||||
|
||||
async def assertion_element(self):
|
||||
@@ -88,6 +90,7 @@ class ElementMain(WebDevice, AndroidDriver):
|
||||
elif self.drive_type == DriveTypeEnum.DESKTOP.value:
|
||||
pass
|
||||
else:
|
||||
log.error('不存在的设备类型')
|
||||
raise Exception('不存在的设备类型')
|
||||
|
||||
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 tools.assertion.sql_assertion import SqlAssertion
|
||||
from tools.message.error_msg import *
|
||||
from tools.public_methods import sync_global_exception
|
||||
|
||||
|
||||
class AndroidDriver(UiautomatorEquipment,
|
||||
@@ -60,7 +61,7 @@ class AndroidDriver(UiautomatorEquipment,
|
||||
except UiObjectNotFoundError as error:
|
||||
raise ElementLocatorError(*ERROR_MSG_0032, value=(self.element_model.name,), error=error, )
|
||||
except Exception as error:
|
||||
print(error)
|
||||
sync_global_exception(error, False)
|
||||
else:
|
||||
if 'locating' in self.element_model.ope_value:
|
||||
del self.element_model.ope_value['locating']
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
# @Time : 2023-09-09 23:17
|
||||
# @Author : 毛鹏
|
||||
import time
|
||||
|
||||
import uiautomator2
|
||||
|
||||
from autotest.ui.base_tools.base_data import BaseData
|
||||
|
||||
@@ -29,6 +29,7 @@ class UiautomatorEquipment(BaseData):
|
||||
def a_swipe_left(self):
|
||||
"""获取屏幕开关状态"""
|
||||
self.android.info.get('screenOn')
|
||||
|
||||
#
|
||||
# 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.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.public_methods import async_global_exception
|
||||
"""
|
||||
python -m uiautomator2 init
|
||||
python -m weditor
|
||||
@@ -180,7 +180,7 @@ class DriverObject:
|
||||
await ClientWebSocket.async_send(msg="发送录制接口", func_name=ApiSocketEnum.RECORDING_API.value,
|
||||
func_args=api_info)
|
||||
except Exception as error:
|
||||
log.error(error)
|
||||
await async_global_exception(error)
|
||||
|
||||
|
||||
async def test_main():
|
||||
|
||||
@@ -8,11 +8,10 @@ import asyncio
|
||||
|
||||
from autotest.ui.base_tools.driver_object import DriverObject
|
||||
from autotest.ui.service.cases import CasesMain
|
||||
from enums.tools_enum import ClientTypeEnum
|
||||
from enums.ui_enum import DriveTypeEnum
|
||||
from models.socket_model.ui_model import CaseModel
|
||||
from service.socket_client import ClientWebSocket
|
||||
from tools.log_collector import log
|
||||
from tools.public_methods import async_global_exception
|
||||
|
||||
|
||||
class CaseRun(DriverObject):
|
||||
@@ -55,9 +54,7 @@ class CaseRun(DriverObject):
|
||||
log.error('自动化类型不存在,请联系管理员检查!')
|
||||
await obj.case_page_step()
|
||||
except Exception as error:
|
||||
log.error(str(error))
|
||||
await ClientWebSocket.async_send(code=300,
|
||||
msg="执行元素步骤时发生未知异常,请检查数据或者联系管理员",
|
||||
is_notice=ClientTypeEnum.WEB.value)
|
||||
await async_global_exception(error)
|
||||
|
||||
finally:
|
||||
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 tools.desktop.signal_send import SignalSend
|
||||
from tools.log_collector import log
|
||||
|
||||
from tools.public_methods import async_global_exception
|
||||
|
||||
class CasesMain(StepsMain):
|
||||
|
||||
@@ -54,7 +54,7 @@ class CasesMain(StepsMain):
|
||||
except MangoActuatorError as error:
|
||||
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{error.msg}'
|
||||
self.case_result.status = StatusEnum.FAIL.value
|
||||
log.error(error.msg)
|
||||
log.warning(error.msg)
|
||||
break
|
||||
else:
|
||||
if page_steps_result_model.status:
|
||||
@@ -62,17 +62,14 @@ class CasesMain(StepsMain):
|
||||
else:
|
||||
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{page_steps_result_model.error_message}'
|
||||
self.case_result.status = StatusEnum.FAIL.value
|
||||
log.error(page_steps_result_model.error_message)
|
||||
log.warning(page_steps_result_model.error_message)
|
||||
break
|
||||
await self.case_posterior(self.case_model.posterior_sql)
|
||||
except MangoActuatorError as error:
|
||||
self.case_result.error_message = f'用例<{self.case_model.name}> 失败原因:{error.msg}'
|
||||
self.case_result.status = StatusEnum.FAIL.value
|
||||
except Exception as error:
|
||||
log.error(str(error))
|
||||
await ClientWebSocket.async_send(code=300,
|
||||
msg="执行元素步骤时发生未知异常,请检查数据或者联系管理员",
|
||||
is_notice=ClientTypeEnum.WEB.value)
|
||||
await async_global_exception(error)
|
||||
else:
|
||||
msg = self.case_result.error_message if self.case_result.error_message else f'用例<{self.case_model.name}>测试完成'
|
||||
await ClientWebSocket.async_send(
|
||||
|
||||
@@ -73,7 +73,7 @@ class StepsMain(ElementMain):
|
||||
return self.page_step_result_model
|
||||
|
||||
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}')
|
||||
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}
|
||||
|
||||
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):
|
||||
|
||||
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:
|
||||
msg = msg.format(*value)
|
||||
if error and is_log:
|
||||
log.error(f'报错提示:{msg}, 报错内容:{error}')
|
||||
else:
|
||||
log.error(f'报错提示:{msg}')
|
||||
elif is_log:
|
||||
log.warning(f'报错提示:{msg}')
|
||||
self.code = code
|
||||
self.msg = msg
|
||||
|
||||
@@ -9,12 +9,9 @@ from enums.tools_enum import ClientTypeEnum, CacheKeyEnum
|
||||
from exceptions import MangoActuatorError
|
||||
from models.socket_model.ui_model import PageStepsModel, WEBConfigModel, CaseModel
|
||||
from service.socket_client import ClientWebSocket
|
||||
from settings.settings import GLOBAL_EXCEPTION_CAPTURE
|
||||
from tools.data_processor.sql_cache import SqlCache
|
||||
from tools.decorator.convert_args import convert_args
|
||||
from tools.desktop.signal_send import SignalSend
|
||||
from tools.log_collector import log
|
||||
|
||||
from tools.public_methods import async_global_exception
|
||||
|
||||
class UIConsumer:
|
||||
page_steps: PageSteps = None
|
||||
@@ -38,14 +35,7 @@ class UIConsumer:
|
||||
msg=error.msg,
|
||||
is_notice=ClientTypeEnum.WEB.value)
|
||||
except Exception as error:
|
||||
if GLOBAL_EXCEPTION_CAPTURE:
|
||||
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
|
||||
await async_global_exception(error)
|
||||
|
||||
@classmethod
|
||||
@convert_args(WEBConfigModel)
|
||||
@@ -60,14 +50,7 @@ class UIConsumer:
|
||||
cls.page_steps = PageSteps(data.project)
|
||||
await cls.page_steps.new_web_obj(data)
|
||||
except Exception as error:
|
||||
if GLOBAL_EXCEPTION_CAPTURE:
|
||||
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
|
||||
await async_global_exception(error)
|
||||
|
||||
@classmethod
|
||||
@convert_args(CaseModel)
|
||||
@@ -86,12 +69,4 @@ class UIConsumer:
|
||||
cls.case_run = CaseRun(max_tasks)
|
||||
await cls.case_run.queue.put(data)
|
||||
except Exception as error:
|
||||
if GLOBAL_EXCEPTION_CAPTURE:
|
||||
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
|
||||
|
||||
await async_global_exception(error)
|
||||
|
||||
@@ -134,8 +134,8 @@ class ClientWebSocket:
|
||||
try:
|
||||
out = json.loads(recv_json)
|
||||
log.info(f'接收的消息提示:{out["msg"]}')
|
||||
if out['data']:
|
||||
log.debug(f"接收的数据:{json.dumps(out['data'], ensure_ascii=False)}")
|
||||
# if out['data']:
|
||||
# log.debug(f"接收的数据:{json.dumps(out['data'], ensure_ascii=False)}")
|
||||
return SocketDataModel(**out)
|
||||
except json.decoder.JSONDecodeError:
|
||||
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())
|
||||
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_user = 'root'
|
||||
# mysql_password = 'root'
|
||||
mysql_password = 'mP123456&'
|
||||
mysql_password = 'root'
|
||||
# mysql_password = 'mP123456&'
|
||||
mysql_ip = 'localhost'
|
||||
# mysql_ip = '36.213.11.72'
|
||||
mysql_port = 3306
|
||||
|
||||
10
README.md
10
README.md
@@ -47,13 +47,9 @@
|
||||
* 所有功能介绍
|
||||

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

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

|
||||
#### 加作者微信,进芒果自动化测试群(记得备注: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