提交 77ec55c5 authored 作者: 陈泽健's avatar 陈泽健

将原有pytest框架代码改为hytest框架使用,优化了脚本执行效率,并对应增加异常处理。MQTT相关模块还未调整完。

上级 d8d160aa
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.10 (pythonProject1)" />
<option name="sdkName" value="Python 3.10 (预定系统标准版)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pythonProject1)" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (预定系统标准版)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
......@@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/预定系统标准版.iml" filepath="$PROJECT_DIR$/.idea/预定系统标准版.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/预定系统.iml" filepath="$PROJECT_DIR$/.idea/预定系统.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
\ No newline at end of file
此差异已折叠。
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
......@@ -129,10 +129,7 @@ class Mqtt:
:param current_time: 当前时间
:return: 消息字典
"""
<<<<<<< HEAD:预定系统/base/Mqtt_Send.py
#安卓信息设备上报
=======
>>>>>>> 949209b52f0b2ea4a02345aefb25f4daee4ec4bd:预定系统/base/Mqtt_Android.py
if topic == "rebootResponseTopic":
return {
"method": "/system/readSystemInfo",
......@@ -189,17 +186,13 @@ class Mqtt:
}
})
}
<<<<<<< HEAD:预定系统/base/Mqtt_Send.py
#安卓信息心跳上报
=======
>>>>>>> 949209b52f0b2ea4a02345aefb25f4daee4ec4bd:预定系统/base/Mqtt_Android.py
elif topic == "/uams/android/broadcast":
return json.dumps({
"type":"heartbeat",
"clientId" : config['clientId'],
"appId":"com.ubains.uniplatform",
"deviceId": config['deviceId']
<<<<<<< HEAD:预定系统/base/Mqtt_Send.py
})
#毫米波雷达数据上报
......@@ -222,10 +215,6 @@ class Mqtt:
"ip" : config['ip']
}
})
=======
})
>>>>>>> 949209b52f0b2ea4a02345aefb25f4daee4ec4bd:预定系统/base/Mqtt_Android.py
def send_and_receive_messages(self, topic, message, num_times=1, timeout=5, interval=0.2):
"""
......
import logging
from hytest import *
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def browser_init():
INFO("'----------' 正在初始化浏览器 '----------'")
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
wd = webdriver.Chrome(options=options)
wd.implicitly_wait(10)
wd.get('https://nat.ubainsyun.com:11046')
wd.maximize_window()
GSTORE['wd'] = wd
def handle_ssl_warning():
wd = GSTORE['wd']
try:
# 记录处理 SSL 证书警告的开始信息
INFO("'----------' 正在处理SSL证书警告 '----------'")
# 等待并点击“详细信息”按钮
WebDriverWait(wd, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="details-button"]'))
).click()
# 等待并点击“继续”链接,以忽略 SSL 警告
WebDriverWait(wd, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="proceed-link"]'))
).click()
# 等待页面加载完成
WebDriverWait(wd, 10).until(
EC.presence_of_element_located((By.TAG_NAME, 'body'))
)
# 记录处理 SSL 证书警告完成的信息
INFO("'----------' SSL证书警告处理完成 '----------'")
except Exception as e:
# 记录处理 SSL 证书警告过程中遇到的错误,并抛出异常
logging.error(f"处理 SSL 证书警告遇到错误: {e}")
raise
def admin_login():
wd = GSTORE['wd']
INFO("输入用户名:admin@czj")
# 等待元素刷新
WebDriverWait(wd, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[1]/div/input')
)).send_keys("admin@czj")
INFO("输入密码:Ubains@4321")
WebDriverWait(wd, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[2]/div/input')
)).send_keys("Ubains@4321")
INFO("输入验证码:csba")
WebDriverWait(wd, 10).until(
EC.element_to_be_clickable(
(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[3]/div[1]/div/input')
)).send_keys("csba")
wd.implicitly_wait(5)
INFO("点击登录按钮")
WebDriverWait(wd, 10).until(
EC.element_to_be_clickable(
(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[4]/input')
)).click()
def browser_quit():
INFO("清除浏览器")
wd = GSTORE['wd']
wd.quit()
\ No newline at end of file
......@@ -13,9 +13,12 @@
- 了解清楚安卓信息的状态判断,后续将调试redis连接以及将键值对存入redis。
4. 2024-10-24
- 优化MQTT底层方法,通过判断topic的值来发送不同的消息体。
<<<<<<< HEAD
- 优化安卓信息上报.py脚本通过读配置文件中的topic,调用build_message时传入topic进行主题判断。后续方便进行MQTT主题与消息体的管理。
- 补充毫米波雷达数据上报数据,毫米波设备的device_id需要与实际设备匹配才行。
=======
- 优化安卓信息上报.py脚本通过读配置文件中的topic,调用build_message时传入topic进行主题判断。后续方便进行MQTT主题与消息体的管理。
>>>>>>> 949209b52f0b2ea4a02345aefb25f4daee4ec4bd
- 修改提交git时代码中出现了很多非法字符的问题。
5. 2024-10-28
- 优化了Mqtt_Send中封装的函数,补充异常处理以及日志优化。
6. 2024-11-02
- 将原有pytest框架代码改为hytest框架使用,优化了脚本执行效率,并对应增加异常处理。
- MQTT相关模块还未调整完。
\ No newline at end of file
import logging
import pytest
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common import StaleElementReferenceException
class Base:
def __init__(self, driver):
self.driver = driver
self.logger = logging.getLogger(__name__)
def find_element(self, by, value):
"""
查找元素,并处理可能的异常
"""
try:
return WebDriverWait(self.driver, 30).until(
EC.presence_of_element_located((by, value))
)
except StaleElementReferenceException:
return WebDriverWait(self.driver, 30).until(
EC.presence_of_element_located((by, value))
)
def perform_login(self, username, password, verification_code):
"""
执行登录操作
"""
self.driver.implicitly_wait(5)
self.driver.refresh()
try:
# 清除并输入用户名
username_input = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[1]/div/input')
username_input.clear()
username_input.send_keys(username)
# 清除并输入密码
password_input = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[2]/div/input')
password_input.clear()
password_input.send_keys(password)
# 清除并输入验证码
verification_input = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[3]/div[1]/div/input')
verification_input.clear()
verification_input.send_keys(verification_code)
# 点击登录按钮
login_button = self.find_element(By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[4]/input')
login_button.click()
# 检查登录是否成功
if self.check_login_null():
self.logger.info("登录失败,必填项不能为空!断言成功!")
elif self.check_login_success():
self.logger.info("登录成功,断言成功!")
self.return_to_login_page()
elif self.check_login_failure():
self.logger.info("登录失败, 必填项错误!断言成功!")
else:
self.logger.error("登录状态未知,断言失败!")
pytest.fail("登录状态未知,断言失败!")
except StaleElementReferenceException as e:
self.logger.error(f"元素已失效,重新查找... {e}")
pytest.fail(f"元素已失效,重新查找... {e}")
except Exception as e:
self.logger.error(f"登录操作失败: {e}")
pytest.fail(f"登录操作失败: {e}")
def return_to_login_page(self):
"""
返回登录页面
"""
try:
# 定位到退出按钮并点击
logout_button = self.find_element(By.XPATH, '//*[@id="app"]/div/div[1]/div/img[3]')
logout_button.click()
# 记录日志,表明已成功尝试返回登录页面
self.logger.info("已成功返回登录页面")
# 刷新页面,并等待一段时间以确保页面加载完成
self.driver.refresh()
self.driver.implicitly_wait(5)
except Exception as e:
# 如果发生异常,记录错误日志并使测试用例失败
self.logger.error(f"返回登录页面失败: {e}")
pytest.fail(f"返回登录页面失败: {e}")
def check_login_null(self):
"""
检查登录失败,必填项为空的情况
"""
try:
login_element_text = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '/html/body/div[2]/p'))
).text
# 断言登录失败后,提示信息中包含'请输入'关键词
assert "请输入" in login_element_text, "登录失败后未找到'请输入'提示语"
return True
except Exception as e:
self.logger.error(f"登录失败检查失败: {e}")
return False
def check_login_success(self):
"""
检查登录成功的情况
"""
try:
message_element_text = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.XPATH, "//*[contains(text(), '欢迎')]"))
).text
# 断言欢迎信息是否符合预期
assert "欢迎 预定标准版测试" == message_element_text, "登录成功后找到'欢迎 预定标准版测试'提示语"
return True
except Exception as e:
self.logger.error(f"登录成功检查失败: {e}")
return False
def check_login_failure(self):
"""
检查登录失败的情况
"""
try:
login_element_text = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[1]/div[1]'))
).text
# 断言登录元素的文本是否为"账号登录",如果符合,则说明登录失败检查成功
assert "账号登录" == login_element_text, "登录失败后未找到'账号登录'提示语"
return True
except Exception as e:
self.logger.error(f"登录失败检查失败: {e}")
return False
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
import logging
class Browser_driver(object):
def browser_init(self):
# logging.info('初始化开始!')
try:
# 自动下载并使用 ChromeDriver
self.driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))
# 设置隐式等待时间
self.driver.implicitly_wait(5) # 延长至5秒
# logging.info('初始化成功,驱动正常!')
except Exception as e:
logging.error(f'初始化失败: {e}')
raise
return self.driver
from hytest import *
import sys
import os
# 获取当前脚本的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 构建预定系统的绝对路径
预定系统_path = os.path.abspath(os.path.join(current_dir, '..','..'))
# 添加路径
sys.path.append(预定系统_path)
# 导入模块
try:
from 预定系统.Base.base import *
except ModuleNotFoundError as e:
print(f"ModuleNotFoundError: {e}")
print("尝试使用绝对路径导入")
from 预定系统.Base.base import *
def suite_setup():
browser_init()
handle_ssl_warning()
def suite_teardown():
browser_quit()
\ No newline at end of file
from time import sleep
from hytest import *
import sys
import os
# 获取当前脚本的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 构建预定系统的绝对路径
预定系统_path = os.path.abspath(os.path.join(current_dir, '..','..','..'))
# 添加路径
sys.path.append(预定系统_path)
# 导入模块
try:
from 预定系统.Base.base import *
except ModuleNotFoundError as e:
print(f"ModuleNotFoundError: {e}")
print("尝试使用绝对路径导入")
from 预定系统.Base.base import *
# 提取常量
XPATH_USERNAME_INPUT = '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[1]/div/input'
# 用户名输入框的 XPath 路径
XPATH_PASSWORD_INPUT = '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[2]/div/input'
# 密码输入框的 XPath 路径
XPATH_CODE_INPUT = '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[3]/div[1]/div/input'
# 验证码输入框的 XPath 路径
XPATH_LOGIN_BUTTON = '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[4]/input'
# 登录按钮的 XPath 路径
XPATH_WELCOME_TEXT = '//*[@id="app"]/div/div[1]/div/span[1]'
# 欢迎文本的 XPath 路径
CLASS_MESSAGE_CONTENT = 'el-message__content'
# 消息内容的 CSS 类名
DEFAULT_WAIT_TIME = 10
# 默认等待时间(秒),用于元素加载或操作之间的等待
def clear_and_send_keys(wd, locator, value):
"""
清空输入框并发送指定值
该函数首先等待指定的元素变得可点击,然后清空该元素的内容,
最后向该元素发送指定的值。这个过程常用于表单填写自动化。
参数:
- wd: WebDriver实例,用于与浏览器交互。
- locator: 定位器,用于定位页面上的元素。
- value: 需要发送到元素的值,通常为字符串。
返回值:
"""
# 等待元素变得可点击,这是为了确保元素已经加载完成并且可以接收输入
element = WebDriverWait(wd, DEFAULT_WAIT_TIME).until(EC.element_to_be_clickable(locator))
# 清空元素的内容,通常用于输入框,以确保之前的内容不会影响新的输入
element.clear()
# 向元素发送指定的值,这是自动化表单填写的关键步骤
element.send_keys(value)
class UI_000x:
ddt_cases = [
{
'name': '登录 UI_0001',
'para': [None,'Ubains@4321','csba','请输入账号!']
},
{
'name': '登录 UI_0002',
'para': ['admin@czj',None,'csba','请输入密码!']
},
{
'name': '登录 UI_0003',
'para': ['admin@czj','Ubains@4321',None,'请输入验证码!']
},
{
'name': '登录 UI_0004',
'para': ['admin@czj112','Ubains@4321','csba','账号或密码错误']
},
{
'name': '登录 UI_0005',
'para': ['adM 12in@czj','Ubains@4321','csba','账号或密码错误']
},
{
'name': '登录 UI_0006',
'para': ['admin@czj', '12345', 'csba', '账号或密码错误']
},
{
'name': '登录 UI_0007',
'para': ['admin@czj', 'U bains1s@432', 'csba', '账号或密码错误']
},
{
'name': '登录 UI_0008',
'para': ['admin@czj', 'Ubains@4321', '123', '验证码错误']
},
{
'name': '登录 UI_0009',
'para': ['admin@czj', 'Ubains@4321', 'cs 12', '验证码错误']
},
{
'name': '登录 UI_0010',
'para': ['admin@czj', 'Ubains@4321', 'csba', '欢迎 预定标准版测试']
}
]
def teststeps(self):
"""
执行测试步骤以验证登录功能。
本函数根据参数输入账号、密码和验证码,并检查登录后的提示信息是否与预期相符。
"""
# 初始化通知文本为空字符串
notify_text = ""
# 从全局存储中获取webdriver实例
wd = GSTORE['wd']
# 从self.para中解构出用户名、密码、验证码和检查文本
username, password, code, check_text = self.para
# 步骤1:输入账号、密码和验证码
STEP(1, f"输入账号: {username}, 密码: {password}, 验证码: {code}")
# 如果用户名不为空,则清空用户名输入框并输入用户名
if username is not None:
clear_and_send_keys(wd, (By.XPATH, XPATH_USERNAME_INPUT), username)
# 如果密码不为空,则清空密码输入框并输入密码
if password is not None:
clear_and_send_keys(wd, (By.XPATH, XPATH_PASSWORD_INPUT), password)
# 如果验证码不为空,则清空验证码输入框并输入验证码
if code is not None:
clear_and_send_keys(wd, (By.XPATH, XPATH_CODE_INPUT), code)
# 步骤2:点击登录按钮
STEP(2, "点击登录按钮")
# 等待登录按钮可点击,并点击它
login_button = WebDriverWait(wd, DEFAULT_WAIT_TIME).until(
EC.element_to_be_clickable((By.XPATH, XPATH_LOGIN_BUTTON)))
login_button.click()
# 等待1秒以允许页面响应
sleep(2)
# 根据预期的检查文本类型,获取并记录提示信息
if check_text == "欢迎":
notify_text = WebDriverWait(wd, DEFAULT_WAIT_TIME).until(
EC.presence_of_element_located((By.XPATH, XPATH_WELCOME_TEXT))
).text
INFO(f"Alert text: {notify_text}")
else:
try:
notify_text = WebDriverWait(wd, DEFAULT_WAIT_TIME).until(
EC.presence_of_element_located((By.CLASS_NAME, CLASS_MESSAGE_CONTENT))
).text
INFO(f"Alert text: {notify_text}")
except Exception as e:
INFO(f"Exception occurred: {e}")
# 步骤3:校验提示信息
STEP(3, f"校验提示信息: {check_text}")
# 设置隐式等待时间
wd.implicitly_wait(DEFAULT_WAIT_TIME)
# 检查点:验证提示信息是否与预期相符
CHECK_POINT('弹出提示', notify_text == check_text)
def teardown(self):
"""
测试 teardown 方法,用于测试结束后清理环境。
该方法从全局存储 GSTORE 中获取 WebDriver 实例,并在测试结束前刷新当前页面。
这是为了确保每个测试都是在干净的状态下执行,避免不同测试之间相互影响。
"""
# 从全局存储中获取 WebDriver 实例
wd = GSTORE['wd']
# 执行步骤 4:刷新页面,以确保下一个测试从一个干净的状态开始
STEP(4, "刷新页面")
wd.refresh()
\ No newline at end of file
# from datetime import datetime
# import time
# from hytest import *
# import sys
# import os
# # 获取当前脚本的绝对路径
# current_dir = os.path.dirname(os.path.abspath(__file__))
# # 构建预定系统的绝对路径
# 预定系统_path = os.path.abspath(os.path.join(current_dir, '..','..','..'))
# # 添加路径
# sys.path.append(预定系统_path)
# # 导入模块
# try:
# from 预定系统.Base.Mqtt_Send import *
# except ModuleNotFoundError as e:
# print(f"ModuleNotFoundError: {e}")
# print("尝试使用绝对路径导入")
# from 预定系统.Base.Mqtt_Send import *
#
# if __name__ == "__main__":
# # 读取配置文件
# configs = Mqtt.read_config_from_csv('../测试数据/MQTT安卓上报数据.csv')
#
# broker_address = "192.168.5.218"
# port = 1883
# # topic = "rebootResponseTopic"
# num_repeats = 100 # 重复执行的次数
# interval_between_repeats = 0.2 # 每次重复之间的间隔时间(秒)
#
# # 创建 MQTT 客户端实例
# mqtt_client = Mqtt(broker_address, port)
#
# try:
# # 连接到 MQTT 服务器
# mqtt_client.connect()
#
# for repeat in range(num_repeats):
# logging.info(f"开始第 {repeat + 1} 次上报")
#
# # 遍历配置文件中的每一行数据
# for config in configs:
# # 构建消息内容-
# # 构建消息内容
# topic = config["topic"]
# current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# message = Mqtt.build_message(config, current_time, topic)
#
# # 发送消息
# mqtt_client.publish(topic, message)
#
# # 每次发送之间可以设置一个间隔时间
# time.sleep(interval_between_repeats)
#
# # 每次重复之间设置一个间隔时间
# time.sleep(interval_between_repeats)
#
# except Exception as e:
# logging.error(f"发送消息时发生错误: {e}")
#
# finally:
# # 断开与 MQTT 服务器的连接
# mqtt_client.disconnect()
# from datetime import datetime
# import logging
# import time
# import sys
# import os
# # 获取当前脚本的绝对路径
# current_dir = os.path.dirname(os.path.abspath(__file__))
# # 构建预定系统的绝对路径
# 预定系统_path = os.path.abspath(os.path.join(current_dir, '..','..','..'))
# # 添加路径
# sys.path.append(预定系统_path)
# # 导入模块
# try:
# from 预定系统.Base.Mqtt_Send import *
# except ModuleNotFoundError as e:
# print(f"ModuleNotFoundError: {e}")
# print("尝试使用绝对路径导入")
# from 预定系统.Base.Mqtt_Send import *
#
# if __name__ == "__main__":
# # 读取配置文件
# configs = Mqtt.read_config_from_csv('../测试数据/MQTT毫米波上报数据.csv')
#
# broker_address = "192.168.5.218"
# port = 1883
# num_repeats = 100 # 重复执行的次数
# interval_between_repeats = 0.2 # 每次重复之间的间隔时间(秒)
#
# # 创建 MQTT 客户端实例-
# mqtt_client = Mqtt(broker_address, port)
#
# try:
# # 连接到 MQTT 服务器
# mqtt_client.connect()
#
# for repeat in range(num_repeats):
# logging.info(f"开始第 {repeat + 1} 次上报")
#
# # 遍历配置文件中的每一行数据
# for config in configs:
# # 构建消息内容
# topic = config["topic"]
# current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# message = Mqtt.build_message(config, current_time, topic)
#
# # 发送消息
# mqtt_client.publish(topic, message)
#
# # 每次发送之间可以设置一个间隔时间
# time.sleep(interval_between_repeats)
#
# # 每次重复之间设置一个间隔时间
# time.sleep(interval_between_repeats)
#
# except Exception as e:
# logging.error(f"发送消息时发生错误: {e}")
#
# finally:
# # 断开与 MQTT 服务器的连接
# mqtt_client.disconnect()
from hytest import *
import sys
import os
# 获取当前脚本的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 构建预定系统的绝对路径
预定系统_path = os.path.abspath(os.path.join(current_dir, '..','..','..'))
# 添加路径
sys.path.append(预定系统_path)
# 导入模块
try:
from 预定系统.Base.base import *
except ModuleNotFoundError as e:
print(f"ModuleNotFoundError: {e}")
print("尝试使用绝对路径导入")
from 预定系统.Base.base import *
def suite_setup():
admin_login()
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
=== [ 收集测试用例 ] ===
== cases\__st__.py
== cases\__init__.py
** no cases in this file, skip it.
== cases\会议室管理\__init__.py
** no cases in this file, skip it.
== cases\授权码管理\__init__.py
** no cases in this file, skip it.
== cases\登录模块\__init__.py
** no cases in this file, skip it.
== cases\登录模块\账号密码登录测试.py
== cases\设备管理\__init__.py
** no cases in this file, skip it.
== cases\设备管理\安卓信息上报.py
** no cases in this file, skip it.
== cases\设备管理\毫米波雷达上报.py
** no cases in this file, skip it.
== cases\账号管理\__st__.py
== cases\账号管理\__init__.py
** no cases in this file, skip it.
== cases\账号管理\部门管理.py
** no cases in this file, skip it.
=== [ 执行测试用例 ] ===
预备执行用例数量 : 10
========= 测试开始 : 20241102_135632 =========
>>> cases\
[ suite setup ] cases\
'----------' 正在初始化浏览器 '----------'
'----------' 正在处理SSL证书警告 '----------'
'----------' SSL证书警告处理完成 '----------'
>>> cases\登录模块\账号密码登录测试.py
* 登录 UI_0001 - 2024-11-02 13:56:39
[ case execution steps ]
-- 第 1 步 -- 输入账号: None, 密码: Ubains@4321, 验证码: csba
-- 第 2 步 -- 点击登录按钮
Alert text: 请输入账号!
-- 第 3 步 -- 校验提示信息: 请输入账号!
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0001
-- 第 4 步 -- 刷新页面
* 登录 UI_0002 - 2024-11-02 13:56:40
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj, 密码: None, 验证码: csba
-- 第 2 步 -- 点击登录按钮
Alert text: 请输入密码!
-- 第 3 步 -- 校验提示信息: 请输入密码!
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0002
-- 第 4 步 -- 刷新页面
* 登录 UI_0003 - 2024-11-02 13:56:41
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj, 密码: Ubains@4321, 验证码: None
-- 第 2 步 -- 点击登录按钮
Alert text: 请输入验证码!
-- 第 3 步 -- 校验提示信息: 请输入验证码!
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0003
-- 第 4 步 -- 刷新页面
* 登录 UI_0004 - 2024-11-02 13:56:43
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj112, 密码: Ubains@4321, 验证码: csba
-- 第 2 步 -- 点击登录按钮
Alert text: 账号或密码错误
-- 第 3 步 -- 校验提示信息: 账号或密码错误
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0004
-- 第 4 步 -- 刷新页面
* 登录 UI_0005 - 2024-11-02 13:56:44
[ case execution steps ]
-- 第 1 步 -- 输入账号: adM 12in@czj, 密码: Ubains@4321, 验证码: csba
-- 第 2 步 -- 点击登录按钮
Alert text: 账号或密码错误
-- 第 3 步 -- 校验提示信息: 账号或密码错误
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0005
-- 第 4 步 -- 刷新页面
* 登录 UI_0006 - 2024-11-02 13:56:45
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj, 密码: 12345, 验证码: csba
-- 第 2 步 -- 点击登录按钮
Alert text: 账号或密码错误
-- 第 3 步 -- 校验提示信息: 账号或密码错误
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0006
-- 第 4 步 -- 刷新页面
* 登录 UI_0007 - 2024-11-02 13:56:47
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj, 密码: U bains1s@432, 验证码: csba
-- 第 2 步 -- 点击登录按钮
Alert text: 账号或密码错误
-- 第 3 步 -- 校验提示信息: 账号或密码错误
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0007
-- 第 4 步 -- 刷新页面
* 登录 UI_0008 - 2024-11-02 13:56:48
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj, 密码: Ubains@4321, 验证码: 123
-- 第 2 步 -- 点击登录按钮
Alert text: 验证码错误
-- 第 3 步 -- 校验提示信息: 验证码错误
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0008
-- 第 4 步 -- 刷新页面
* 登录 UI_0009 - 2024-11-02 13:56:50
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj, 密码: Ubains@4321, 验证码: cs 12
-- 第 2 步 -- 点击登录按钮
Alert text: 验证码错误
-- 第 3 步 -- 校验提示信息: 验证码错误
** 检查点 ** 弹出提示 ----> 通过
PASS
[ case teardown ] 登录 UI_0009
-- 第 4 步 -- 刷新页面
* 登录 UI_0010 - 2024-11-02 13:56:51
[ case execution steps ]
-- 第 1 步 -- 输入账号: admin@czj, 密码: Ubains@4321, 验证码: csba
-- 第 2 步 -- 点击登录按钮
Exception occurred: Message:
Stacktrace:
GetHandleVerifier [0x00007FF63C4DFD55+29557]
(No symbol) [0x00007FF63C4521F0]
(No symbol) [0x00007FF63C30B6EA]
(No symbol) [0x00007FF63C35FA15]
(No symbol) [0x00007FF63C35FC6C]
(No symbol) [0x00007FF63C3ABB07]
(No symbol) [0x00007FF63C38753F]
(No symbol) [0x00007FF63C3A88A3]
(No symbol) [0x00007FF63C3872A3]
(No symbol) [0x00007FF63C3512DF]
(No symbol) [0x00007FF63C352451]
GetHandleVerifier [0x00007FF63C80DC4D+3363437]
GetHandleVerifier [0x00007FF63C859AD7+3674359]
GetHandleVerifier [0x00007FF63C84EA7B+3629211]
GetHandleVerifier [0x00007FF63C59FC16+815670]
(No symbol) [0x00007FF63C45D69F]
(No symbol) [0x00007FF63C459264]
(No symbol) [0x00007FF63C459400]
(No symbol) [0x00007FF63C4481AF]
BaseThreadInitThunk [0x00007FFD832E257D+29]
RtlUserThreadStart [0x00007FFD83FCAF08+40]
-- 第 3 步 -- 校验提示信息: 欢迎 预定标准版测试
** 检查点 ** 弹出提示 ----> !! 不通过!!
FAIL
Traceback:
File "D:\GithubData\自动化脚本-3\ubains-module-test\预定系统\cases\登录模块\账号密码登录测试.py", line 167, in teststeps
CHECK_POINT('弹出提示', notify_text == check_text)
File "D:\GithubData\ubains-module-test\ubains-module-test\.venv\lib\site-packages\hytest\common.py", line 76, in CHECK_POINT
raise AssertionError()
AssertionError
[ case teardown ] 登录 UI_0010
-- 第 4 步 -- 刷新页面
[ suite teardown ] cases\
清除浏览器
========= 测试结束 : 20241102_135705 =========
耗时 : 33.340 秒
预备执行用例数量 : 10
实际执行用例数量 : 10
通过 : 9
失败 : 1
异常 : 0
套件初始化失败 : 0
套件清除 失败 : 0
用例初始化失败 : 0
用例清除 失败 : 0
=== [ 收集测试用例 ] ===
== cases\__st__.py
== cases\__init__.py
** no cases in this file, skip it.
== cases\会议室管理\__init__.py
** no cases in this file, skip it.
== cases\授权码管理\__init__.py
** no cases in this file, skip it.
== cases\登录模块\__init__.py
** no cases in this file, skip it.
== cases\登录模块\账号密码登录测试.py
== cases\设备管理\__init__.py
** no cases in this file, skip it.
== cases\设备管理\安卓信息上报.py
=== [ 收集测试用例 ] ===
== cases\__st__.py
== cases\__init__.py
** no cases in this file, skip it.
== cases\会议室管理\__init__.py
** no cases in this file, skip it.
== cases\授权码管理\__init__.py
** no cases in this file, skip it.
== cases\登录模块\__init__.py
** no cases in this file, skip it.
== cases\登录模块\账号密码登录测试.py
== cases\设备管理\__init__.py
** no cases in this file, skip it.
== cases\设备管理\安卓信息上报.py
<<<<<<< HEAD
from 预定系统.base.Mqtt_Send import Mqtt
=======
from 预定系统.base.Mqtt_Android import Mqtt
>>>>>>> 949209b52f0b2ea4a02345aefb25f4daee4ec4bd
from datetime import datetime
import logging
import time
if __name__ == "__main__":
# 读取配置文件
<<<<<<< HEAD
configs = Mqtt.read_config_from_csv('../测试数据/MQTT安卓上报数据.csv')
=======
configs = Mqtt.read_config_from_csv('../测试数据/MQTT心跳上报.csv')
>>>>>>> 949209b52f0b2ea4a02345aefb25f4daee4ec4bd
broker_address = "192.168.5.218"
port = 1883
# topic = "rebootResponseTopic"
num_repeats = 100 # 重复执行的次数
interval_between_repeats = 0.2 # 每次重复之间的间隔时间(秒)
# 创建 MQTT 客户端实例
mqtt_client = Mqtt(broker_address, port)
try:
# 连接到 MQTT 服务器
mqtt_client.connect()
for repeat in range(num_repeats):
logging.info(f"开始第 {repeat + 1} 次上报")
# 遍历配置文件中的每一行数据
for config in configs:
<<<<<<< HEAD
# 构建消息内容-
=======
# 构建消息内容
>>>>>>> 949209b52f0b2ea4a02345aefb25f4daee4ec4bd
topic = config["topic"]
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
message = Mqtt.build_message(config, current_time, topic)
# 发送消息
mqtt_client.publish(topic, message)
# 每次发送之间可以设置一个间隔时间
time.sleep(interval_between_repeats)
# 每次重复之间设置一个间隔时间
time.sleep(interval_between_repeats)
except Exception as e:
logging.error(f"发送消息时发生错误: {e}")
finally:
# 断开与 MQTT 服务器的连接
mqtt_client.disconnect()
from 预定系统.base.Mqtt_Send import Mqtt
from datetime import datetime
import logging
import time
if __name__ == "__main__":
# 读取配置文件
configs = Mqtt.read_config_from_csv('../测试数据/MQTT毫米波上报数据.csv')
broker_address = "192.168.5.218"
port = 1883
num_repeats = 100 # 重复执行的次数
interval_between_repeats = 0.2 # 每次重复之间的间隔时间(秒)
# 创建 MQTT 客户端实例-
mqtt_client = Mqtt(broker_address, port)
try:
# 连接到 MQTT 服务器
mqtt_client.connect()
for repeat in range(num_repeats):
logging.info(f"开始第 {repeat + 1} 次上报")
# 遍历配置文件中的每一行数据
for config in configs:
# 构建消息内容
topic = config["topic"]
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
message = Mqtt.build_message(config, current_time, topic)
# 发送消息
mqtt_client.publish(topic, message)
# 每次发送之间可以设置一个间隔时间
time.sleep(interval_between_repeats)
# 每次重复之间设置一个间隔时间
time.sleep(interval_between_repeats)
except Exception as e:
logging.error(f"发送消息时发生错误: {e}")
finally:
# 断开与 MQTT 服务器的连接
mqtt_client.disconnect()
username,password,verification_code
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
admin@,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj,Ubains@4321,
,Ubains@4321,csba
admin@czj2,Ubains@4321,csba
admin@czj,Ubains@4321,csba
\ No newline at end of file
topic,clientId,appToken,companyNumber,cnum,conferenceId,macAddress,authCode
rebootResponseTopic,48134e6047a19aaf,AND-8AJ-0021,CN-8AJ-UBAINS,22tcji1m49t45ro0r3zyaj0zqd1863yh,219,20:59:20:00:28:81,AND-8AJ-0021
rebootResponseTopic,48134e6047a19aac,AND-8AJ-0022,CN-8AJ-UBAINS,9arvn9am36cjzlimxm4ojd9xzdzusaup,219,20:59:20:00:28:82,AND-8AJ-0022
rebootResponseTopic,48134e6047a19aab,AND-8AJ-0023,CN-8AJ-UBAINS,v3ydnq9u34ocunzanac6l3q8atkvvic3,219,20:59:20:00:28:83,AND-8AJ-0023
rebootResponseTopic,48134e6047a19aaz,AND-8AJ-0024,CN-8AJ-UBAINS,r8xvvvs4r7hhzhfi4i2zldoxoe4estss,219,20:59:20:00:28:84,AND-8AJ-0024
rebootResponseTopic,48134e6047a19aax,AND-8AJ-0025,CN-8AJ-UBAINS,r8xvvvs4r7hhzhfi4i2zldoxoe4estss,219,20:59:20:00:28:85,AND-8AJ-0025
\ No newline at end of file
topic,clientId,deviceId
/uams/android/broadcast,48134e6047a19aaf,aa44e258a4e1e571
/uams/android/broadcast,48134e6047a19aac,aa44e258a4e1e572
/uams/android/broadcast,48134e6047a19aab,aa44e258a4e1e573
/uams/android/broadcast,48134e6047a19aaz,aa44e258a4e1e574
/uams/android/broadcast,48134e6047a19aax,aa44e258a4e1e575
\ No newline at end of file
import pytest
import logging
from selenium.common import StaleElementReferenceException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import csv
from 预定系统.base.Broswer_driver import Browser_driver
def read_csv_data():
"""
读取 CSV 文件数据
"""
data = []
try:
with open('../测试数据/Login_Test.csv', mode='r', encoding='utf-8') as csvfile:
csv_reader = csv.DictReader(csvfile)
for row in csv_reader:
data.append((row['username'], row['password'], row['verification_code']))
except FileNotFoundError:
logger.error("CSV 文件未找到,请检查文件路径")
pytest.exit("CSV 文件未找到,请检查文件路径")
except Exception as e:
logger.error(f"出现错误: {e}")
pytest.exit(f"出现错误: {e}")
return data
# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@pytest.fixture(scope='session')
def driver():
"""
初始化浏览器并打开指定URL
"""
url = 'https://192.168.5.218'
logging.info("'----------' 正在初始化浏览器 '----------'")
try:
driver = Browser_driver().browser_init() # 初始化浏览器驱动
logging.info("'----------' 浏览器初始化成功 '----------'")
except Exception as e:
logging.error(f"浏览器初始化失败: {e}")
raise
driver.implicitly_wait(10) # 设置隐式等待时间为10秒
driver.maximize_window() # 最大化浏览器窗口
logging.info("'----------' 正在打开URL '----------'")
try:
driver.get(url)
logging.info(f"成功打开URL: {url}")
except Exception as e:
logging.error(f"打开URL失败: {e}")
raise
handle_ssl_warning(driver) # 处理可能存在的SSL证书警告
yield driver
driver.quit() # 在测试结束后关闭浏览器
def handle_ssl_warning(driver):
"""处理 SSL 证书警告"""
try:
logging.info("'----------' 正在处理SSL证书警告 '----------'")
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="details-button"]'))
).click()
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="proceed-link"]'))
).click()
# 等待页面加载完成
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, 'body'))
)
logging.info("'----------' SSL证书警告处理完成 '----------'")
except Exception as e:
logging.error(f"处理 SSL 证书警告遇到错误: {e}")
raise
def _find_element(driver, by, value):
"""
查找元素,并处理可能的异常
"""
try:
return WebDriverWait(driver, 20).until(
EC.presence_of_element_located((by, value))
)
except StaleElementReferenceException:
return WebDriverWait(driver, 20).until(
EC.presence_of_element_located((by, value))
)
def perform_login(driver, username, password, verification_code):
"""
执行登录操作
"""
try:
# 清除并输入用户名
username_input = _find_element(driver, By.XPATH,
'//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[1]/div/input')
username_input.clear()
username_input.send_keys(username)
# 清除并输入密码
password_input = _find_element(driver, By.XPATH,
'//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[2]/div/input')
password_input.clear()
password_input.send_keys(password)
# 清除并输入验证码
verification_input = _find_element(driver, By.XPATH,
'//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[3]/div[1]/div/input')
verification_input.clear()
verification_input.send_keys(verification_code)
# 点击登录按钮
login_button = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[2]/div/form/div[4]/input')
login_button.click()
if username | password | verification_code == "":
check_login_null(driver)
logger.info("登录失败,必填项不能为空!断言成功!\n")
elif check_login_failure(driver):
logger.info("登录失败, 必填项错误!断言成功!\n")
elif check_login_success(driver):
logger.info("登录成功,断言成功!\n")
return_to_login_page(driver) # 返回登录页面
# # 检查登录是否成功
# if check_login_null(driver):
# logger.info("登录失败,必填项不能为空!断言成功!\n")
#
# elif check_login_success(driver):
# logger.info("登录成功,断言成功!\n")
# return_to_login_page(driver) # 返回登录页面
# elif check_login_failure(driver):
# logger.info("登录失败, 必填项错误!断言成功!\n")
else:
logger.error("登录状态未知,断言失败!\n")
pytest.fail("登录状态未知,断言失败!")
except StaleElementReferenceException as e:
logger.error(f"元素已失效,重新查找... {e}\n")
pytest.fail(f"元素已失效,重新查找... {e}")
except Exception as e:
logger.error(f"登录操作失败: {e}\n")
pytest.fail(f"登录操作失败: {e}")
def return_to_login_page(driver):
"""
返回登录页面
"""
try:
logout_button = _find_element(driver, By.XPATH, '//*[@id="app"]/div/div[1]/div/div[1]/div[2]/div[2]')
logout_button.click()
logging.info("已成功返回登录页面\n")
except Exception as e:
logger.error(f"返回登录页面失败: {e}\n")
pytest.fail(f"返回登录页面失败: {e}")
def check_login_null(driver):
"""
检查登录失败,必填项为空的情况
"""
try:
login_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '/html/body/div[2]/p'))
).text
assert "请输入" in login_element_text, "登录失败后未找到'请输入'提示语"
return True
except Exception as e:
logger.error(f"登录失败检查失败: {e}")
return False
def check_login_success(driver):
"""
检查登录成功的情况
"""
try:
message_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, "//*[contains(text(), '欢迎')]"))
).text
assert "欢迎 预定标准版测试" == message_element_text, "登录成功后找到'欢迎 预定标准版测试'提示语"
driver.find_element(By.XPATH, '//*[@id="app"]/div/div[1]/div/img[3]').click()
driver.refresh()
driver.implicitly_wait(5)
return True
except Exception as e:
logger.error(f"登录成功检查失败: {e}")
return False
def check_login_failure(driver):
"""
检查登录失败的情况
"""
try:
login_element_text = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, '//*[@id="app"]/div/div[3]/div[1]/div[1]/div[1]'))
).text
assert "账号登录" == login_element_text, "登录失败后未找到'账号登录'提示语"
return True
except Exception as e:
logger.error(f"登录失败检查失败: {e}")
return False
@pytest.mark.parametrize("username,password,verification_code", read_csv_data())
def test_login_from_csv(driver, username, password, verification_code):
"""
从 CSV 文件读取并测试登录情况
"""
logger.info(f"'----------' 开始执行测试 '----------'\n")
perform_login(driver, username, password, verification_code)
logger.info(f"'----------' 执行完成测试 '----------'\n")
driver.implicitly_wait(10)
if __name__ == '__main__':
pytest.main()
此差异已折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论