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

feat(test-case-generator): 重构浏览器操作模块并实现配置驱动的登录功能

- 将BrowserOperator从MCP工具切换到Selenium WebDriver实现
- 添加Chrome浏览器初始化和元素定位功能
- 实现基于配置文件的登录参数验证和处理
- 移除重复的系统配置项并更新验证逻辑
- 添加问题修复文档记录定位器相关的执行问题
上级 4faab7e2
......@@ -3,8 +3,11 @@
"system_type": "new_platform",
"system_front_url": "https://192.168.5.44",
"system_back_url": "https://192.168.5.44/#/LoginAdmin",
"username": "admin@xty",
"password": "Ubains@4321",
"code": "csba"
"back_username": ["XPATH","//input[@placeholder='请输入账号或手机号或邮箱号']","admin@xty"],
"back_password": ["XPATH","//input[@placeholder='请输入密码']","Ubains@4321"],
"back_code": ["XPATH","//input[@placeholder='请输入图形验证码']","csba"],
"front_username": ["XPATH","//input[@placeholder='手机号/用户名/邮箱']","admin@xty"],
"front_password": ["XPATH","//input[@placeholder='密码']","Ubains@4321"],
"front_code": ["XPATH","//input[@placeholder='图形验证']","csba"]
}
]
......@@ -114,10 +114,10 @@ class ConfigManager:
def _validate_system_config(self, config: List[Dict]) -> bool:
"""
验证系统配置格式
验证系统配置格式(更新版)
Args:
config: 系统配置字典
config: 系统配置字典列表
Returns:
验证是否通过
......@@ -126,14 +126,12 @@ class ConfigManager:
self.logger.error("系统配置必须是列表格式")
return False
required_fields = [
"system_type",
"system_front_url",
"system_back_url",
"username",
"password",
"code"
]
# 基础必填字段
required_fields = ["system_type", "system_front_url", "system_back_url"]
# 登录字段(格式:["定位类型", "定位值", "输入值"])
login_fields = ["back_username", "back_password", "back_code",
"front_username", "front_password", "front_code"]
for idx, system in enumerate(config):
if not isinstance(system, dict):
......@@ -155,8 +153,61 @@ class ConfigManager:
self.logger.error(f"系统配置第{idx+1}项的system_back_url格式错误")
return False
# 检查登录字段格式(如果存在)
for field in login_fields:
if field in system:
field_value = system[field]
if not isinstance(field_value, list) or len(field_value) != 3:
self.logger.error(f"登录字段 {field} 格式错误,应为 [定位类型, 定位值, 输入值]")
return False
# 验证定位类型
locator_type = field_value[0]
if locator_type not in ["ID", "XPATH", "CSS_SELECTOR", "NAME"]:
self.logger.error(f"不支持的定位类型: {locator_type}")
return False
return True
def get_login_config(self, login_type: str = "back") -> Dict[str, tuple]:
"""
获取登录配置
Args:
login_type: 登录类型,"back"或"front"
Returns:
登录配置字典,格式:
{
"username": ("XPATH", "//input[@placeholder='...']", "admin@xty"),
"password": ("XPATH", "//input[@placeholder='...']", "password"),
"code": ("XPATH", "//input[@placeholder='...']", "csba")
}
Raises:
ValueError: 配置未加载或不支持的登录类型
"""
if self.system_config is None:
raise ValueError("系统配置未加载,请先调用load_system_config()")
system = self.system_config[0] # 使用第一个系统配置
# 根据登录类型获取配置
prefix = f"{login_type}_"
login_config = {}
for field in ["username", "password", "code"]:
config_key = f"{prefix}{field}"
if config_key not in system:
self.logger.error(f"缺少登录配置: {config_key}")
raise ValueError(f"缺少登录配置: {config_key}")
config_value = system[config_key]
# 格式:["定位类型", "定位值", "输入值"]
login_config[field] = (config_value[0], config_value[1], config_value[2])
return login_config
def _validate_module_config(self, config: List[Dict]) -> bool:
"""
验证模块配置格式
......
......@@ -27,13 +27,15 @@ class TestCaseGeneratorMain:
"""测试用例生成器主控类"""
def __init__(self, system_config_path: str = "config/system_config.json",
module_config_path: str = "config/module_config.json"):
module_config_path: str = "config/module_config.json",
login_type: str = "back"):
"""
初始化主控类
Args:
system_config_path: 系统配置文件路径
module_config_path: 模块配置文件路径
login_type: 登录类型,"front"或"back",默认为"back"
"""
self.logger = get_logger("TestCaseGeneratorMain")
self.config_manager = ConfigManager()
......@@ -46,6 +48,7 @@ class TestCaseGeneratorMain:
# 配置文件路径
self.system_config_path = system_config_path
self.module_config_path = module_config_path
self.login_type = login_type
# 设置文件日志
project_root = Path(__file__).parent
......@@ -62,15 +65,15 @@ class TestCaseGeneratorMain:
# 1. 加载配置
self._load_configs()
# 2. 选择登录URL
# 2. 选择登录URL和登录类型
system_config = self.config_manager.get_system_config()
login_url = self._select_login_url(system_config)
login_url, login_type = self._select_login_url_and_type(system_config, self.login_type)
# 3. 初始化浏览器
self._initialize_browser()
# 4. 登录系统
self._login_system(login_url, system_config)
self._login_system(login_url, login_type)
# 5. 处理所有模块
self._process_all_modules()
......@@ -110,26 +113,25 @@ class TestCaseGeneratorMain:
functions = module.get("module_function")
self.logger.info(f" 模块{idx}: {module_name} > {module_name_son}, 功能: {functions}")
def _select_login_url(self, system_config: Dict) -> str:
def _select_login_url_and_type(self, system_config: Dict, login_type: str = "back") -> tuple[str, str]:
"""
选择登录URL
选择登录URL和登录类型
Args:
system_config: 系统配置字典
login_type: 登录类型,"front"或"back"
Returns:
登录URL
(登录URL, 登录类型) 元组
"""
self.logger.info("请选择登录地址:")
self.logger.info(" 1. 前台地址")
self.logger.info(" 2. 后台地址")
if login_type == "front":
login_url = system_config.get("system_front_url")
self.logger.info(f"使用前台地址登录: {login_url}")
else: # back
login_url = system_config.get("system_back_url")
self.logger.info(f"使用后台地址登录: {login_url}")
# 简化处理:默认使用后台地址
# 实际使用时可以通过命令行参数或交互式输入选择
login_url = system_config.get("system_back_url")
self.logger.info(f"使用后台地址登录: {login_url}")
return login_url
return login_url, login_type
def _initialize_browser(self) -> None:
"""初始化浏览器"""
......@@ -143,23 +145,21 @@ class TestCaseGeneratorMain:
self.logger.info("浏览器初始化完成")
def _login_system(self, login_url: str, system_config: Dict) -> None:
def _login_system(self, login_url: str, login_type: str) -> None:
"""
登录系统
登录系统(使用配置文件中的定位器)
Args:
login_url: 登录URL
system_config: 系统配置字典
login_type: 登录类型,"front"或"back"
"""
self.logger.info("正在登录系统...")
self.login_handler = LoginHandler(self.browser)
username = system_config.get("username")
password = system_config.get("password")
code = system_config.get("code", "csba")
# 使用配置管理器初始化登录处理器
self.login_handler = LoginHandler(self.browser, self.config_manager)
if not self.login_handler.login(login_url, username, password, code):
# 执行登录
if not self.login_handler.login(login_url, login_type):
raise Exception("登录失败")
# 初始化导航处理器
......@@ -279,7 +279,8 @@ def main():
# 创建并运行主控类
main_controller = TestCaseGeneratorMain(
system_config_path=args.system_config,
module_config_path=args.module_config
module_config_path=args.module_config,
login_type=args.login_type
)
try:
......
......@@ -11,23 +11,17 @@
- system_config.json文件格式示例:
```json
[
{
"system_type": "new_platform",
"system_front_url": "https://192.168.5.44",
"system_back_url": "https://192.168.5.44/#/LoginAdmin",
"username": "admin@xty",
"password": "Ubains@4321",
"code": "csba"
},
{
{
"system_type": "new_platform",
"system_front_url": "https://192.168.5.44",
"system_back_url": "https://192.168.5.44/#/LoginAdmin",
"username": "admin@xty",
"password": "Ubains@4321",
"code": "csba"
}
"system_front_url": "https://192.168.5.44",
"system_back_url": "https://192.168.5.44/#/LoginAdmin",
"username": "admin@xty",
"password": "Ubains@4321",
"code": "csba"
}
]
```
2. 根据同目录下的module_config.json文件,获取需要收集的自动化模块名称、模块功能。
- module_config.json文件格式示例:
......
# 自动化测试用例生成 - 执行问题修复文档
## 文档信息
- **创建日期**: 2026-03-06
- **版本**: v1.1
- **最后更新**:
- **状态**:
---
## 问题概述
通过main.py运行时,日志打印未找到元素用户、账号、username、account、用户,登录失败。
---
## 发现的问题清单
### 问题1: 无法登录系统
**问题描述**
- 登录失败,未找到用户名输入框
**问题日志**
- 2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: 用户名
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: 账号
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: username
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: account
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: 用户
2026-03-06 13:25:37 - LoginHandler - ERROR - 未找到用户名输入框
2026-03-06 13:25:37 - TestCaseGeneratorMain - ERROR - 执行过程中发生错误: 登录失败
2026-03-06 13:25:37 - TestCaseGeneratorMain - INFO - 正在清理资源...
2026-03-06 13:25:37 - BrowserOperator - INFO - 正在关闭浏览器
2026-03-06 13:25:37 - BrowserOperator - INFO - 浏览器已关闭
2026-03-06 13:25:37 - TestCaseGeneratorMain - INFO - 资源清理完成
2026-03-06 13:41:51 - LoginHandler - WARNING - 未找到匹配元素: [XPATH] //input[@placeholder='请输入账号或手机号或邮箱号']
2026-03-06 13:41:51 - LoginHandler - ERROR - 使用定位器未找到元素: //input[@placeholder='请输入账号或手机号或邮箱号']
2026-03-06 13:41:51 - LoginHandler - ERROR - 填写用户名失败
2026-03-06 13:41:51 - TestCaseGeneratorMain - ERROR - 执行过程中发生错误: 登录失败
2026-03-06 13:41:51 - TestCaseGeneratorMain - INFO - 正在清理资源...
2026-03-06 13:41:51 - BrowserOperator - INFO - 正在关闭浏览器
2026-03-06 13:41:51 - BrowserOperator - INFO - 浏览器已关闭
2026-03-06 13:41:51 - TestCaseGeneratorMain - INFO - 资源清理完成
错误: 登录失败
---
**文档结束**
# _PRD_运行脚本无法登录系统_问题记录_计划执行
> 版本:V2.0
> 创建日期:2026-03-06
> 更新日期:2026-03-06
> 适用范围:自动化测试用例生成工具
> 来源:基于《_PRD_运行脚本无法登录系统_问题记录_.md》
> 状态:待执行
---
## 1. 问题概述
### 1.1 问题描述
运行 main.py 时,登录失败,日志显示未找到用户名输入框。
### 1.2 问题日志
```
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: 用户名
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: 账号
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: username
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: account
2026-03-06 13:25:37 - BrowserOperator - WARNING - 未找到元素: 用户
2026-03-06 13:25:37 - LoginHandler - ERROR - 未找到用户名输入框
2026-03-06 13:25:37 - TestCaseGeneratorMain - ERROR - 执行过程中发生错误: 登录失败
```
---
## 2. 解决方案
### 2.1 新方案:配置文件指定登录定位器
**设计变更**:不再自动查找输入框,而是在 `system_config.json` 中直接指定登录元素的定位器。
#### 2.1.1 新的 system_config.json 格式
```json
[
{
"system_type": "new_platform",
"system_front_url": "https://192.168.5.44",
"system_back_url": "https://192.168.5.44/#/LoginAdmin",
"back_username": ["XPATH", "//input[@placeholder='请输入账号或手机号或邮箱号']", "admin@xty"],
"back_password": ["XPATH", "//input[@placeholder='请输入密码']", "Ubains@4321"],
"back_code": ["XPATH", "//input[@placeholder='请输入图形验证码']", "csba"],
"front_username": ["XPATH", "//input[@placeholder='手机号/用户名/邮箱']", "admin@xty"],
"front_password": ["XPATH", "//input[@placeholder='密码']", "Ubains@4321"],
"front_code": ["XPATH", "//input[@placeholder='图形验证']", "csba"]
}
]
```
#### 2.1.2 定位器配置格式
**格式**`["定位类型", "定位值", "输入值"]`
| 字段 | 说明 | 示例 |
|------|------|------|
| 定位类型 | XPATH/ID/CSS_SELECTOR等 | `"XPATH"` |
| 定位值 | 元素定位表达式 | `"//input[@placeholder='请输入账号']"` |
| 输入值 | 要填写的值 | `"admin@xty"` |
---
## 3. 修复执行计划
### Phase 1: 更新配置文件(优先级:P0)
| 序号 | 任务 | 文件 | 预计工时 |
|-----|------|------|----------|
| 1 | 更新 system_config.json 格式 | config/system_config.json | 10分钟 |
### Phase 2: 更新代码实现(优先级:P0)
| 序号 | 任务 | 文件 | 预计工时 |
|-----|------|------|----------|
| 2 | 更新 config_manager.py 解析新格式 | config_manager.py | 30分钟 |
| 3 | 重写 login_handler.py 使用配置定位器 | login_handler.py | 30分钟 |
| 4 | 更新 main.py 传递登录类型参数 | main.py | 15分钟 |
### Phase 3: 测试验证(优先级:P1)
| 序号 | 任务 | 预计工时 |
|-----|------|----------|
| 5 | 测试后台登录 | 15分钟 |
| 6 | 测试前台登录 | 15分钟 |
---
## 4. 详细修复代码
### 4.1 system_config.json
```json
[
{
"system_type": "new_platform",
"system_front_url": "https://192.168.5.44",
"system_back_url": "https://192.168.5.44/#/LoginAdmin",
"back_username": ["XPATH", "//input[@placeholder='请输入账号或手机号或邮箱号']", "admin@xty"],
"back_password": ["XPATH", "//input[@placeholder='请输入密码']", "Ubains@4321"],
"back_code": ["XPATH", "//input[@placeholder='请输入图形验证码']", "csba"],
"front_username": ["XPATH", "//input[@placeholder='手机号/用户名/邮箱']", "admin@xty"],
"front_password": ["XPATH", "//input[@placeholder='密码']", "Ubains@4321"],
"front_code": ["XPATH", "//input[@placeholder='图形验证']", "csba"]
}
]
```
### 4.2 config_manager.py 更新
```python
def _validate_system_config(self, config: List[Dict]) -> bool:
"""验证系统配置格式(更新版)"""
if not isinstance(config, list):
self.logger.error("系统配置必须是列表格式")
return False
required_fields = ["system_type", "system_front_url", "system_back_url"]
login_fields = ["back_username", "back_password", "back_code",
"front_username", "front_password", "front_code"]
for idx, system in enumerate(config):
if not isinstance(system, dict):
self.logger.error(f"系统配置第{idx+1}项必须是字典格式")
return False
# 检查必填字段
for field in required_fields:
if field not in system:
self.logger.error(f"系统配置第{idx+1}项缺少必填字段: {field}")
return False
# 检查登录字段格式
for field in login_fields:
if field in system:
field_value = system[field]
if not isinstance(field_value, list) or len(field_value) != 3:
self.logger.error(f"登录字段 {field} 格式错误,应为 [定位类型, 定位值, 输入值]")
return False
return True
```
### 4.3 login_handler.py 更新
```python
def login(self, url: str, login_type: str = "back") -> bool:
"""
执行登录操作(使用配置的定位器)
Args:
url: 登录页面URL
login_type: 登录类型,"back"或"front"
Returns:
是否登录成功
"""
# 从配置中获取登录信息
system_config = self.config_manager.get_system_config()
# 根据登录类型选择配置
username_config = system_config.get(f"{login_type}_username")
password_config = system_config.get(f"{login_type}_password")
code_config = system_config.get(f"{login_type}_code")
# 使用配置的定位器进行登录
locator_type, locator_value, username_value = username_config
# ... 填写用户名
locator_type, locator_value, password_value = password_config
# ... 填写密码
# ...
```
---
## 5. 验收标准
### 5.1 功能验收
- [ ] 能够成功解析新的配置格式
- [ ] 能够使用配置的定位器找到输入框
- [ ] 后台登录能够成功
- [ ] 前台登录能够成功
### 5.2 配置验收
- [ ] system_config.json 格式正确
- [ ] 所有登录字段配置完整
- [ ] 定位器能够正确定位元素
---
*文档结束*
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论