提交 35b07be9 authored 作者: PGY's avatar PGY

refactor(统一平台): 重构代码并添加定时执行功能

- 优化了浏览器初始化过程
- 添加了定时执行功能测试的脚本,实现了自动化定时任务
- 调整了截图保存路径,统一到 reports/imgs目录下
- 移除了未使用的导入和冗余代码,精简了代码结构
- 添加了对钉钉机器人发送测试结果的支持
上级 acd876b6
...@@ -106,7 +106,7 @@ def SELENIUM_LOG_SCREEN(driver, width: str = None, module_name: str = None, func ...@@ -106,7 +106,7 @@ def SELENIUM_LOG_SCREEN(driver, width: str = None, module_name: str = None, func
# 使用当前时间作为文件名,确保唯一性 # 使用当前时间作为文件名,确保唯一性
filename = datetime.now().strftime('%Y%m%d%H%M%S%f') filename = datetime.now().strftime('%Y%m%d%H%M%S%f')
# 定义文件路径和相对于log的路径 # 定义文件路径和相对于log的路径
filepath = f'log/imgs/{filename}.png' filepath = f'reports/imgs/{filename}.png'
filepath_relative_to_log = f'imgs/{filename}.png' filepath_relative_to_log = f'imgs/{filename}.png'
# 获取并保存截图 # 获取并保存截图
driver.get_screenshot_as_file(filepath) driver.get_screenshot_as_file(filepath)
......
此差异已折叠。
# 浏览器初始化函数
def browser_init(login_type):
"""
初始化浏览器设置和实例。
此函数旨在创建并配置一个Chrome浏览器实例,包括设置Chrome选项以排除不必要的日志,
并尝试打开特定的登录页面。任何初始化过程中出现的错误都会被捕获并记录。
参数:
login_type (str): 指定登录类型,根据不同的登录类型选择不同的URL。
返回:
"""
# 标记初始化过程的开始
INFO("'----------' 正在初始化浏览器 '----------'")
# 创建Chrome选项实例,用于配置浏览器行为
options = webdriver.ChromeOptions()
# 添加实验性选项,排除某些命令行开关以减少输出日志
options.add_experimental_option('excludeSwitches', ['enable-Logging'])
# 忽略证书错误,允许在本地主机上运行时不安全
options.add_argument('--ignore-certificate-errors')
# 禁用自动化控制特征检测,避免被网站识别为自动化流量
options.add_argument('--disable-blink-features=AutomationControlled')
# 允许不安全的本地主机运行,通常用于开发和测试环境
options.add_argument('--allow-insecure-localhost')
# 使用webdriver_manager自动下载并管理chromedriver
# service = ChromeService(ChromeDriverManager().install())
# 使用备用的ChromeDriver下载源
# service = Service(ChromeDriverManager().install())
# 手动指定ChromeDriver的路径
# 自动化运行服务器的chromedriver路径:
service = Service(r'C:\Users\29194\AppData\Local\Programs\Python\Python310\Scripts\chromedriver.exe')
# service = Service(r'C:\Program Files\Python310\Scripts\chromedriver.exe')
# 尝试创建WebDriver实例并执行初始化操作
try:
# 创建WebDriver实例
wd = webdriver.Chrome(service=service, options=options)
# 设置隐式等待时间为10秒,以允许元素加载
wd.implicitly_wait(60)
# 获取登录URL
login_url = get_login_url_from_config(login_type)
# 打开对应类型的登录页面
wd.get(login_url)
# 最大化浏览器窗口
wd.maximize_window()
# 将WebDriver实例存储在全局存储器中,以便后续使用
GSTORE['wd'] = wd
# 标记初始化过程完成
INFO("'----------' 浏览器初始化完成 '----------'")
except Exception as e:
# 捕获并记录初始化过程中的任何异常
logging.error(f"浏览器初始化失败:{e}")
import sys import sys
import os import os
# 获取当前脚本的绝对路径 # 获取当前脚本的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
# 构建统一平台的绝对路径 # 构建统一平台的绝对路径
platform_path = os.path.abspath(os.path.join(current_dir, '..','..','..')) platform_path = os.path.abspath(os.path.join(current_dir, '..','..','..'))
# 添加路径 # 添加路径到系统路径中
sys.path.append(platform_path) sys.path.append(platform_path)
# 导入模块 # 导入模块
from 统一平台.base.bases import * from 统一平台.base.bases import *
# 获取当前脚本所在的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# 构建XLSX文件的绝对路径 # 构建XLSX文件的绝对路径
xlsx_file_path = os.path.join(current_dir, '..', '..', 'data', '统一平台PC端测试用例.xlsx') xlsx_file_path = os.path.join(current_dir, '..', '..', 'data', '统一平台PC端测试用例.xlsx')
...@@ -20,7 +15,7 @@ class Unified_Platform_0001: ...@@ -20,7 +15,7 @@ class Unified_Platform_0001:
#执行指令: #执行指令:
# cd ./统一平台/ # cd ./统一平台/
# hytest --tag 统一平台 # hytest --tag 统一平台
tags = ['创建会议','重庆长安'] tags = ['创建会议','重庆长安','统一平台']
ddt_cases = read_xlsx_data(xlsx_file_path, sheet_name="新建会议&") ddt_cases = read_xlsx_data(xlsx_file_path, sheet_name="新建会议&")
def teststeps(self): def teststeps(self):
wd = GSTORE['wd'] wd = GSTORE['wd']
...@@ -36,7 +31,7 @@ class Unified_Platform_0001: ...@@ -36,7 +31,7 @@ class Unified_Platform_0001:
element_type = step.get('element_type') element_type = step.get('element_type')
element_value = step.get('element_value') element_value = step.get('element_value')
expented_result = step.get('expented_result') expented_result = step.get('expented_result')
print(f"执行JSON:{step}") print(f"正在执行JSON:{step}")
if step.get("page") == "CreateMeeting": if step.get("page") == "CreateMeeting":
if element_type == "input": if element_type == "input":
safe_send_keys((locator_type, locator_value), element_value, wd) safe_send_keys((locator_type, locator_value), element_value, wd)
......
...@@ -11,7 +11,7 @@ sys.path.append(platform_path) ...@@ -11,7 +11,7 @@ sys.path.append(platform_path)
from 统一平台.base.bases import * from 统一平台.base.bases import *
class Unified_Platform_0001: class Unified_Platform_0001:
tags = ['统一平台','会议控制','重庆长安'] tags = ['统一平台','会议控制','重庆长安','统一标准版']
def teststeps(self): def teststeps(self):
wd = GSTORE['wd'] wd = GSTORE['wd']
# 进入会控界面 # 进入会控界面
......
...@@ -23,11 +23,15 @@ def suite_setup(): ...@@ -23,11 +23,15 @@ def suite_setup():
wd = GSTORE['wd'] wd = GSTORE['wd']
STEP(2, "登录系统") STEP(2, "登录系统")
safe_send_keys((By.XPATH, "//input[@placeholder='手机号/用户名/邮箱']"),"admin@pgy",wd) safe_send_keys((By.XPATH, "//input[@placeholder='手机号/用户名/邮箱']"),"admin@pgy",wd)
safe_send_keys((By.XPATH, "//input[@placeholder='密码']"),"Ubains@13579",wd) safe_send_keys((By.XPATH, "//input[@placeholder='密码']"),"Ubains@1357",wd)
safe_send_keys((By.XPATH, "//input[@placeholder='图形验证']"),"csba",wd) safe_send_keys((By.XPATH, "//input[@placeholder='图形验证']"),"csba",wd)
safe_click((By.XPATH, "//span[@class='el-checkbox__inner']"),wd) sleep(2)
print("对协议进行勾选")
safe_click((By.XPATH, "//div[@aria-label='提示']//span[contains(text(),'确定')]"),wd)
print("已经勾选协议了")
sleep(2) sleep(2)
safe_click((By.XPATH, "//div[@id='pane-1']//div//span[contains(text(),'登录')]"),wd) safe_click((By.XPATH, "//div[@id='pane-1']//div//span[contains(text(),'登录')]"),wd)
print("已经点击登录了")
sleep(2) sleep(2)
def suite_teardown(): def suite_teardown():
......
import sys import sys
import os import os
from win32trace import flush #from win32trace import flush
# 获取当前脚本的绝对路径 # 获取当前脚本的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
...@@ -50,4 +50,4 @@ class Unified_Platform_0001: ...@@ -50,4 +50,4 @@ class Unified_Platform_0001:
notify_text = elment_get_text((locator_type,locator_value), wd) notify_text = elment_get_text((locator_type,locator_value), wd)
INFO(f"获取弹窗提示内容为:{notify_text}") INFO(f"获取弹窗提示内容为:{notify_text}")
CHECK_POINT("判断是否跟预期一致", expented_result == notify_text) CHECK_POINT("判断是否跟预期一致", expented_result == notify_text)
SELENIUM_LOG_SCREEN(wd, "50%") SELENIUM_LOG_SCREEN(wd, "50%",1,1,1 )
\ No newline at end of file \ No newline at end of file
...@@ -25,9 +25,13 @@ def suite_setup(): ...@@ -25,9 +25,13 @@ def suite_setup():
safe_send_keys((By.XPATH, "//input[@placeholder='手机号/用户名/邮箱']"),"admin@pgy",wd) safe_send_keys((By.XPATH, "//input[@placeholder='手机号/用户名/邮箱']"),"admin@pgy",wd)
safe_send_keys((By.XPATH, "//input[@placeholder='密码']"),"Ubains@1357",wd) safe_send_keys((By.XPATH, "//input[@placeholder='密码']"),"Ubains@1357",wd)
safe_send_keys((By.XPATH, "//input[@placeholder='图形验证']"),"csba",wd) safe_send_keys((By.XPATH, "//input[@placeholder='图形验证']"),"csba",wd)
safe_click((By.XPATH, "//span[@class='el-checkbox__inner']"),wd) sleep(2)
print("对协议进行勾选")
safe_click((By.XPATH, "//div[@aria-label='提示']//span[contains(text(),'确定')]"),wd)
print("已经勾选协议了")
sleep(2) sleep(2)
safe_click((By.XPATH, "//div[@id='pane-1']//div//span[contains(text(),'登录')]"),wd) safe_click((By.XPATH, "//div[@id='pane-1']//div//span[contains(text(),'登录')]"),wd)
print("已经点击登录了")
sleep(2) sleep(2)
def suite_teardown(): def suite_teardown():
......
{ {
"_comment_exhibit_unified_platform": "统一平台系统URL", "_comment_exhibit_unified_platform": "统一平台系统URL",
"统一平台": "http://192.168.9.78:443/#/login", "统一平台": "http://192.168.9.78:443/#/login",
"成都太行": "http://192.168.9.78:2443/#/login" "成都太行": "http://192.168.9.78:2443/#/login",
"初始化网页": "https://www.baidu.com/"
} }
\ No newline at end of file
server_addr: "ngrok.ubsyun.com:9083"
trust_host_root_certs: false
tunnels:
nat1:
remote_port: 32136
proto:
tcp: "192.168.1.66:80"
nat2:
remote_port: 32135
proto:
tcp: "192.168.1.66:8081"
\ No newline at end of file
ngrok -config=ngrok.cfg start nat1 nat2
\ No newline at end of file
import schedule
import queue
from base.bases import *
import time
import logging
import threading
"""
执行指令:
1.打开一个终端输入:
- cd .\统一平台\
- python -m http.server 8081 --directory reports
2.打开新终端输入:
- cd .\统一平台\ngrok\ngrok-调试主机\
- .\start.bat
3.再打开一个终端输入:
- cd .\统一平台\
- python .\定时执行功能测试.py
"""
# 创建一个任务队列,用于存储待处理的任务
task_queue = queue.Queue()
def run_task(task, *args, **kwargs):
# 将任务及其参数放入任务队列
task_queue.put((task, args, kwargs))
logging.debug(f"任务已加入队列: {task.__name__} with args: {args} and kwargs: {kwargs}")
def worker():
# 工作线程的主循环
while True:
# 从任务队列中获取任务及其参数
task, args, kwargs = task_queue.get()
try:
# 记录任务开始执行的时间
logging.debug(f"开始执行任务: {task.__name__} with args: {args} and kwargs: {kwargs}")
# 执行任务并获取结果
result = task(*args, **kwargs)
# 如果任务有返回结果,记录日志
if result:
logging.info(result)
except Exception as e:
# 捕获任务执行过程中发生的任何异常并记录错误日志
logging.error(f"执行任务时发生错误: {e}", exc_info=True)
finally:
# 无论任务是否成功执行,都标记任务已完成
task_queue.task_done()
# 记录任务完成的时间
logging.debug(f"任务完成: {task.__name__}")
def start_workers(num_workers):
# 启动指定数量的工作线程
for _ in range(num_workers):
# 创建一个新的工作线程,目标函数为 worker,设置为守护线程
threading.Thread(target=worker, daemon=True).start()
# 启动3个工作线程
start_workers(3)
# 定时执行成都太行项目
schedule.every().day.at("08:00").do(run_task, run_automation_test, report_title="成都太行项目测试报告", report_url_prefix="http://nat.ubainsyun.com:32135", test_case="成都太行", ding_type="项目功能验证")
# 定时执行重庆长安项目
#schedule.every().day.at("08:15").do(run_task, run_automation_test, report_title="重庆长安项目测试报告", report_url_prefix="http://nat.ubainsyun.com:32135", test_case="重庆长安", ding_type="项目功能验证")
# 定时执行统一平台标准版
schedule.every().day.at("08:20").do(run_task, run_automation_test, report_title="统一平台标准版测试报告", report_url_prefix="http://nat.ubainsyun.com:32135", test_case="统一平台", ding_type="标准版巡检")
try:
# 无限循环,持续检查并执行计划任务
while True:
schedule.run_pending() # 检查并执行所有待处理的任务
time.sleep(1) # 每秒检查一次
except KeyboardInterrupt:
# 捕获用户中断信号 (Ctrl+C)
logging.info("Scheduler interrupted by user.")
except Exception as e:
# 捕获其他未预期的异常
logging.error(f"Unexpected error: {e}", exc_info=True)
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论