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

fix(testcase-generator): 修复测试用例生成器中的多条件定位问题以及按钮元素默认为span进行定位

- 移除XPATH定位中的多条件OR运算符,改为单一明确条件
- 将按钮定位从button标签改为span标签以适配Element UI结构
- 修正getTips类型元素的element_value为空字符串的规范
- 更新文档中的元素类型规范说明和示例代码
- 修复自动化部署脚本中的端口配置问题
- 补充Bash命令到工具配置中
上级 7452ce5f
...@@ -122,7 +122,8 @@ ...@@ -122,7 +122,8 @@
"mcp__chrome-devtools__new_page", "mcp__chrome-devtools__new_page",
"mcp__chrome-devtools__close_page", "mcp__chrome-devtools__close_page",
"mcp__chrome-devtools__list_pages", "mcp__chrome-devtools__list_pages",
"mcp__chrome-devtools__fill_form" "mcp__chrome-devtools__fill_form",
"Bash(grep:*)"
] ]
} }
} }
...@@ -420,7 +420,7 @@ class TestCaseGenerator: ...@@ -420,7 +420,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击【添加】按钮", "step": "点击【添加】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'添加')]", "locator_value": "//span[contains(text(),'添加')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -429,7 +429,7 @@ class TestCaseGenerator: ...@@ -429,7 +429,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "填写表单字段", "step": "填写表单字段",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']", "locator_value": "//input[@placeholder='请输入名称']",
"element_type": "input", "element_type": "input",
"element_value": "测试数据${timestamp}", "element_value": "测试数据${timestamp}",
"expected_result": "" "expected_result": ""
...@@ -438,7 +438,7 @@ class TestCaseGenerator: ...@@ -438,7 +438,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击【确定】按钮", "step": "点击【确定】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]", "locator_value": "//span[contains(text(),'确定')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -447,7 +447,7 @@ class TestCaseGenerator: ...@@ -447,7 +447,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "验证添加成功提示", "step": "验证添加成功提示",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//p[contains(text(),'添加成功') or contains(text(),'成功')]", "locator_value": "//p[contains(text(),'添加成功')]",
"element_type": "getTips", "element_type": "getTips",
"element_value": "", "element_value": "",
"expected_result": "添加成功" "expected_result": "添加成功"
...@@ -461,7 +461,7 @@ class TestCaseGenerator: ...@@ -461,7 +461,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击第一条记录的【编辑】按钮", "step": "点击第一条记录的【编辑】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'编辑')])[1]", "locator_value": "(//span[contains(text(),'编辑')])[1]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -470,7 +470,7 @@ class TestCaseGenerator: ...@@ -470,7 +470,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "修改表单字段", "step": "修改表单字段",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']", "locator_value": "//input[@placeholder='请输入名称']",
"element_type": "input", "element_type": "input",
"element_value": "修改后的数据${timestamp}", "element_value": "修改后的数据${timestamp}",
"expected_result": "" "expected_result": ""
...@@ -479,7 +479,7 @@ class TestCaseGenerator: ...@@ -479,7 +479,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击【确定】按钮", "step": "点击【确定】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]", "locator_value": "//span[contains(text(),'确定')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -488,7 +488,7 @@ class TestCaseGenerator: ...@@ -488,7 +488,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "验证编辑成功提示", "step": "验证编辑成功提示",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//p[contains(text(),'编辑成功') or contains(text(),'保存成功')]", "locator_value": "//p[contains(text(),'编辑成功')]",
"element_type": "getTips", "element_type": "getTips",
"element_value": "", "element_value": "",
"expected_result": "编辑成功" "expected_result": "编辑成功"
...@@ -502,7 +502,7 @@ class TestCaseGenerator: ...@@ -502,7 +502,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击第一条记录的【删除】按钮", "step": "点击第一条记录的【删除】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'删除')])[1]", "locator_value": "(//span[contains(text(),'删除')])[1]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -511,7 +511,7 @@ class TestCaseGenerator: ...@@ -511,7 +511,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "确认删除操作", "step": "确认删除操作",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]", "locator_value": "//span[contains(text(),'确定')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -534,7 +534,7 @@ class TestCaseGenerator: ...@@ -534,7 +534,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击第一条记录的【停用】按钮", "step": "点击第一条记录的【停用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'停用')])[1]", "locator_value": "(//span[contains(text(),'停用')])[1]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -566,7 +566,7 @@ class TestCaseGenerator: ...@@ -566,7 +566,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击记录的【启用】按钮", "step": "点击记录的【启用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'启用')]", "locator_value": "//span[contains(text(),'启用')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -616,7 +616,7 @@ class TestCaseGenerator: ...@@ -616,7 +616,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击【批量启用】按钮", "step": "点击【批量启用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'批量启用')]", "locator_value": "//span[contains(text(),'批量启用')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -657,7 +657,7 @@ class TestCaseGenerator: ...@@ -657,7 +657,7 @@ class TestCaseGenerator:
"page": page_url, "page": page_url,
"step": "点击【批量停用】按钮", "step": "点击【批量停用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'批量停用')]", "locator_value": "//span[contains(text(),'批量停用')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击第一条记录的【删除】按钮", "step": "点击第一条记录的【删除】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'删除')])[1]", "locator_value": "(//span[contains(text(),'删除')])[1]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "确认删除操作", "step": "确认删除操作",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]", "locator_value": "//span[contains(text(),'确定')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击【添加】按钮", "step": "点击【添加】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'添加')]", "locator_value": "//span[contains(text(),'添加')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "填写表单字段", "step": "填写表单字段",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']", "locator_value": "//input[@placeholder='请输入名称']",
"element_type": "input", "element_type": "input",
"element_value": "测试数据${timestamp}", "element_value": "测试数据${timestamp}",
"expected_result": "" "expected_result": ""
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击【确定】按钮", "step": "点击【确定】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]", "locator_value": "//span[contains(text(),'确定')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "验证添加成功提示", "step": "验证添加成功提示",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//p[contains(text(),'添加成功') or contains(text(),'成功')]", "locator_value": "//p[contains(text(),'添加成功')]",
"element_type": "getTips", "element_type": "getTips",
"element_value": "", "element_value": "",
"expected_result": "添加成功" "expected_result": "添加成功"
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击第一条记录的【编辑】按钮", "step": "点击第一条记录的【编辑】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'编辑')])[1]", "locator_value": "(//span[contains(text(),'编辑')])[1]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "修改表单字段", "step": "修改表单字段",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']", "locator_value": "//input[@placeholder='请输入名称']",
"element_type": "input", "element_type": "input",
"element_value": "修改后的数据${timestamp}", "element_value": "修改后的数据${timestamp}",
"expected_result": "" "expected_result": ""
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击【确定】按钮", "step": "点击【确定】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]", "locator_value": "//span[contains(text(),'确定')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "验证编辑成功提示", "step": "验证编辑成功提示",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//p[contains(text(),'编辑成功') or contains(text(),'保存成功')]", "locator_value": "//p[contains(text(),'编辑成功')]",
"element_type": "getTips", "element_type": "getTips",
"element_value": "", "element_value": "",
"expected_result": "编辑成功" "expected_result": "编辑成功"
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击第一条记录的【停用】按钮", "step": "点击第一条记录的【停用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'停用')])[1]", "locator_value": "(//span[contains(text(),'停用')])[1]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击记录的【启用】按钮", "step": "点击记录的【启用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'启用')]", "locator_value": "//span[contains(text(),'启用')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击【批量停用】按钮", "step": "点击【批量停用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'批量停用')]", "locator_value": "//span[contains(text(),'批量停用')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击【批量启用】按钮", "step": "点击【批量启用】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'批量启用')]", "locator_value": "//span[contains(text(),'批量启用')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击第一条记录的【编辑】按钮", "step": "点击第一条记录的【编辑】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'编辑')])[1]", "locator_value": "(//span[contains(text(),'编辑')])[1]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "修改表单字段", "step": "修改表单字段",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']", "locator_value": "//input[@placeholder='请输入名称']",
"element_type": "input", "element_type": "input",
"element_value": "修改后的数据${timestamp}", "element_value": "修改后的数据${timestamp}",
"expected_result": "" "expected_result": ""
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "点击【确定】按钮", "step": "点击【确定】按钮",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]", "locator_value": "//span[contains(text(),'确定')]",
"element_type": "click", "element_type": "click",
"element_value": "", "element_value": "",
"expected_result": "" "expected_result": ""
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
"page": "backend/backstage", "page": "backend/backstage",
"step": "验证编辑成功提示", "step": "验证编辑成功提示",
"locator_type": "XPATH", "locator_type": "XPATH",
"locator_value": "//p[contains(text(),'编辑成功') or contains(text(),'保存成功')]", "locator_value": "//p[contains(text(),'编辑成功')]",
"element_type": "getTips", "element_type": "getTips",
"element_value": "", "element_value": "",
"expected_result": "编辑成功" "expected_result": "编辑成功"
......
...@@ -201,13 +201,89 @@ class LocatorHelper: ...@@ -201,13 +201,89 @@ class LocatorHelper:
| element_type | element_value | expected_result | 状态 | | element_type | element_value | expected_result | 状态 |
|--------------|---------------|-----------------|------| |--------------|---------------|-----------------|------|
| input | 填写输入内容 | 通常留空 | 待实现 | | input | 填写输入内容 | 通常留空 | ✅ 已实现 |
| click | 留空 | 通常留空 | 待实现 | | click | 留空 | 通常留空 | ✅ 已实现 |
| getTips | **留空** | 填写预期提示文本 | 待实现 | | getTips | **必须留空** | **填写预期提示文本** | ✅ 已实现 |
| getText | **留空** | 填写验证描述 | 待实现 | | getText | **必须留空** | **填写验证描述** | ✅ 已实现 |
| select | 留空 | 通常留空 | 待实现 | | select | 留空 | 通常留空 | - |
| checkbox | 留空 | 通常留空 | 待实现 | | checkbox | 留空 | 通常留空 | - |
| switch | 留空 | 通常留空 | 待实现 | | switch | 留空 | 通常留空 | - |
**getTips 详细规范**
getTips用于获取弹窗提示信息(如Element UI的el-message组件中的"添加成功"、"删除成功"等提示)。
**错误的写法**
```json
{
"element_type": "getTips",
"element_value": "添加成功", // 错误
"expected_result": ""
}
```
**正确的写法**
```json
{
"element_type": "getTips",
"element_value": "", // 正确:必须留空
"expected_result": "添加成功" // 正确:填写预期提示文本
}
```
**规则说明**
- `element_value`**固定为空字符串 `""`**,不得填写任何内容
- `expected_result`**必须填写预期的提示文本**,如"添加成功"、"编辑成功"、"删除成功"、"停用成功"、"启用成功"、"批量启用成功"、"批量停用成功"等
**click 类型按钮定位规范**
对于按钮类型的click操作,**必须使用span标签定位**,而非button标签。
**原因**:Element UI等框架中,按钮的HTML结构为:
```html
<button>
<span>添加</span>
</button>
```
文本内容在嵌套的`<span>`元素中,而非直接在`<button>`标签内。
**错误的写法**
```json
{
"step": "点击【添加】按钮",
"locator_type": "XPATH",
"locator_value": "//button[contains(text(),'添加')]", // 错误
"element_type": "click"
}
```
**正确的写法**
```json
{
"step": "点击【添加】按钮",
"locator_type": "XPATH",
"locator_value": "//span[contains(text(),'添加')]", // 正确:使用span标签
"element_type": "click"
}
```
**规则说明**
- 按钮类定位**必须使用** `//span[contains(text(),'文本')]` 格式
- 不得使用 `//button[contains(text(),'文本')]` 格式
- 带索引的按钮:`(//span[contains(text(),'编辑')])[1]`
#### 4.3 文件命名规范
```json
{
"element_type": "getTips",
"element_value": "", // 正确:必须留空
"expected_result": "添加成功" // 正确:填写预期提示文本
}
```
**规则说明**
- `element_value`**固定为空字符串 `""`**,不得填写任何内容
- `expected_result`**必须填写预期的提示文本**,如"添加成功"、"编辑成功"、"删除成功"、"停用成功"、"启用成功"、"批量启用成功"、"批量停用成功"等
#### 4.3 文件命名规范 #### 4.3 文件命名规范
- 格式:`{module_name}_{module_name_son}_{function}.json` - 格式:`{module_name}_{module_name_son}_{function}.json`
......
# 生成的JSON数据中存在多条件
## 问题描述
### 问题现象
生成的测试用例JSON数据中,存在多条件内容:
- **错误**: `"//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']"`
- **正确**: `"//input[@placeholder='请输入名称']"` 或者 `"//input[@placeholder='请输入商品名称']"` 或者 `"//input[@placeholder='请输入']"`
### 影响
- 生成的测试用例因为是多条件导致无法正确定位元素,测试执行失败。
---
## 相关文档
- 代码规范: `Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md`
- 问题总结: `Docs/PRD/01规范文档/_PRD_问题总结_记录文档.md`
- 方法总结: `Docs/PRD/01规范文档/_PRD_方法总结_记录文档.md`
- 文档规范: `Docs/PRD/01规范文档/_PRD_规范文档_文档规范.md`
- 测试规范: `Docs/PRD/01规范文档/_PRD_规范文档_测试规范.md`
---
\ No newline at end of file
# 计划执行文档 - 生成的JSON数据中存在多条件
## 问题描述
### 问题现象
生成的测试用例JSON数据中,存在多条件XPATH定位表达式:
| 位置 | 当前定位值(错误) | 正确定位值 |
|------|------------------|-----------|
| 输入框 | `//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']` | `//input[@placeholder='请输入名称']` |
| 成功提示 | `//p[contains(text(),'添加成功') or contains(text(),'成功')]` | `//p[contains(text(),'添加成功')]` |
### 影响
- 多条件XPATH可能导致某些测试执行框架解析失败
- 定位不够精确,可能匹配到错误的元素
- 不符合"单一职责"原则,每个定位应该明确指向一个元素
---
## 根因分析
### 原因:代码中硬编码了多条件定位
`generate_testcases.py` 的方法中,直接使用了包含 `or` 运算符的XPATH表达式:
```python
# _add_add_steps 方法 - 第432行
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']"
# _add_add_steps 方法 - 第450行
"locator_value": "//p[contains(text(),'添加成功') or contains(text(),'成功')]"
# _add_edit_steps 方法 - 第473行
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']"
# _add_edit_steps 方法 - 第491行
"locator_value": "//p[contains(text(),'编辑成功') or contains(text(),'保存成功')]"
```
### XPATH `or` 运算符的问题
虽然XPATH 1.0规范支持 `or` 运算符,但在测试用例JSON中使用多条件定位存在以下问题:
1. **可读性差**:难以理解到底要匹配哪个元素
2. **维护困难**:当页面结构变化时,难以判断哪个条件在起作用
3. **调试不便**:测试失败时,无法确定是哪个条件匹配到了错误的元素
---
## 修复方案
### 方案:将多条件改为单一明确条件
**原则**:每个定位值应该精确、明确地指向目标元素
#### 1. 输入框定位修正
**修改前:**
```python
"locator_value": "//input[@placeholder='请输入名称' or @placeholder='请输入商品名称' or @placeholder='请输入']"
```
**修改后(使用最通用的定位):**
```python
"locator_value": "//input[@placeholder='请输入名称']"
```
#### 2. 提示验证定位修正
**修改前:**
```python
# 添加成功提示
"locator_value": "//p[contains(text(),'添加成功') or contains(text(),'成功')]"
# 编辑成功提示
"locator_value": "//p[contains(text(),'编辑成功') or contains(text(),'保存成功')]"
```
**修改后(使用精确匹配):**
```python
# 添加成功提示
"locator_value": "//p[contains(text(),'添加成功')]"
# 编辑成功提示
"locator_value": "//p[contains(text(),'编辑成功')]"
```
---
## 代码实现
### 修复位置:`generate_testcases.py`
#### 1. 修复 `_add_add_steps` 方法
```python
def _add_add_steps(self, testcase, page_url):
"""添加功能的步骤"""
testcase["para"].extend([
{
"page": page_url,
"step": "点击【添加】按钮",
"locator_type": "XPATH",
"locator_value": "//button[contains(text(),'添加')]",
"element_type": "click",
"element_value": "",
"expected_result": ""
},
{
"page": page_url,
"step": "填写表单字段",
"locator_type": "XPATH",
# 修正:移除多条件,使用单一明确定位
"locator_value": "//input[@placeholder='请输入名称']",
"element_type": "input",
"element_value": "测试数据${timestamp}",
"expected_result": ""
},
{
"page": page_url,
"step": "点击【确定】按钮",
"locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]",
"element_type": "click",
"element_value": "",
"expected_result": ""
},
{
"page": page_url,
"step": "验证添加成功提示",
"locator_type": "XPATH",
# 修正:使用精确匹配,移除 '成功' 这个过于宽泛的条件
"locator_value": "//p[contains(text(),'添加成功')]",
"element_type": "getTips",
"element_value": "",
"expected_result": "添加成功"
}
])
```
#### 2. 修复 `_add_edit_steps` 方法
```python
def _add_edit_steps(self, testcase, page_url):
"""编辑功能的步骤"""
testcase["para"].extend([
{
"page": page_url,
"step": "点击第一条记录的【编辑】按钮",
"locator_type": "XPATH",
"locator_value": "(//button[contains(text(),'编辑')])[1]",
"element_type": "click",
"element_value": "",
"expected_result": ""
},
{
"page": page_url,
"step": "修改表单字段",
"locator_type": "XPATH",
# 修正:移除多条件,使用单一明确定位
"locator_value": "//input[@placeholder='请输入名称']",
"element_type": "input",
"element_value": "修改后的数据${timestamp}",
"expected_result": ""
},
{
"page": page_url,
"step": "点击【确定】按钮",
"locator_type": "XPATH",
"locator_value": "//button[contains(text(),'确定')]",
"element_type": "click",
"element_value": "",
"expected_result": ""
},
{
"page": page_url,
"step": "验证编辑成功提示",
"locator_type": "XPATH",
# 修正:使用精确匹配,优先使用 '编辑成功'
"locator_value": "//p[contains(text(),'编辑成功')]",
"element_type": "getTips",
"element_value": "",
"expected_result": "编辑成功"
}
])
```
#### 3. 检查其他方法
同样需要检查并修复以下方法中的多条件定位:
- `_add_delete_steps`
- `_add_disable_steps`
- `_add_enable_steps`
- `_add_batch_enable_steps`
- `_add_batch_disable_steps`
---
## 执行步骤
### 步骤1:定位所有多条件
使用搜索功能查找代码中所有包含 ` or ` 的定位值:
```bash
grep -n " or " generate_testcases.py
```
### 步骤2:逐一修复
按照上述方案,将多条件定位改为单一明确条件
### 步骤3:更新已有测试用例文件
删除旧的测试用例文件,重新运行程序生成新的测试用例
### 步骤4:验证修复结果
检查新生成的测试用例文件,确认没有多条件定位
---
## 验证标准
### 代码修复验证
- [x] 所有 `locator_value` 中不包含 ` or ` 运算符
- [x] 每个定位值都是单一、明确的XPATH表达式
- [x] 定位值使用精确匹配而非模糊匹配
### 测试用例文件验证
- [x] 生成的JSON文件中,`locator_value` 字段都是单一条件
- [x] 验证提示类定位使用精确的文本匹配
- [x] 输入框类定位使用具体的placeholder值
---
## 注意事项
### 关于代码中的多条件 vs JSON中的多条件
**代码中的多条件(保留)**
`navigate_to_module` 等方法中,使用多个定位策略是合理的:
```python
menu_locators = [
(By.XPATH, f"//span[contains(text(),'{module_name}')]"),
(By.XPATH, f"//li//span[contains(text(),'{module_name}')]"),
# ...
]
for locator_type, locator_value in menu_locators:
try:
# 逐个尝试,成功即停止
except:
continue
```
这是代码运行时的**多策略尝试机制**,不同于JSON中的多条件。
**JSON中的多条件(移除)**
生成的测试用例JSON中,每个定位值应该是单一的:
```json
{
"locator_value": "//span[contains(text(),'区域管理')]"
}
```
而非:
```json
{
"locator_value": "//span[contains(text(),'区域管理') or contains(text(),'区域')]"
}
```
### 与运行时多策略的区别
| 类型 | 位置 | 形式 | 说明 |
|------|------|------|------|
| 运行时多策略 | Python代码 | 列表 + 循环尝试 | 合理,用于提高兼容性 |
| JSON多条件 | 定位值字符串 | XPATH `or` 运算符 | 不合理,应移除 |
---
## 优化功能回填
### 已完成
- [x] 修复代码中的多条件定位问题
- [x] 生成计划执行文档
- [x] 更新相关测试用例文件
### 待优化
- [ ] 根据实际页面结构,为不同模块定制更精确的定位值
- [ ] 考虑从配置文件读取定位模板,支持灵活配置
---
## 相关文档
- 问题文档: `Docs/PRD/生成自动化测试用例/问题修复/_PRD_生成的JSON数据中存在多条件_问题处理.md`
- 代码规范: `Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md`
---
*文档版本:v1.0*
*创建日期:2026-03-06*
*状态:已实现*
...@@ -212,7 +212,7 @@ ...@@ -212,7 +212,7 @@
### 3.3 支持的元素类型(element_type) ### 3.3 支持的元素类型(element_type)
#### 3.3.1 基础类型 #### 3.3.1 基础类型
- **click**:点击按钮、链接等可点击元素 - **click**:点击按钮、链接等可点击元素,如按钮元素,则用`span`标签中的文本进行定位(如Element UI的button组件中的span子元素)
- **input**:文本输入框(input type=text) - **input**:文本输入框(input type=text)
- **select**:下拉选择框(select) - **select**:下拉选择框(select)
...@@ -221,7 +221,7 @@ ...@@ -221,7 +221,7 @@
- **switch**:开关控件(如Element UI的switch) - **switch**:开关控件(如Element UI的switch)
#### 3.3.3 验证类型 #### 3.3.3 验证类型
- **getTips**:获取弹窗提示信息(如Element UI的el-message组件中的"添加成功""删除成功"等提示) - **getTips**:获取弹窗提示信息(如Element UI的el-message组件中的"添加成功""删除成功"等提示),元素值固定为:`"//p[@class='el-message__content']"`
- **getText**:获取列表中的文本数据(如表格td元素中的文本,用于验证数据是否存在于列表中) - **getText**:获取列表中的文本数据(如表格td元素中的文本,用于验证数据是否存在于列表中)
### 3.4 element_value expected_result 填写规范 ### 3.4 element_value expected_result 填写规范
......
...@@ -466,7 +466,7 @@ function firewalldjava() { ...@@ -466,7 +466,7 @@ function firewalldjava() {
log "INFO" "==================================================================" log "INFO" "=================================================================="
# 定义 TCP 和 UDP 需要开放的端口 # 定义 TCP 和 UDP 需要开放的端口
local tcp_ports=(22 443 8848 9848 1883 8883 8996) local tcp_ports=(22 443 8848 9848 1883 8883)
local udp_ports=(123 323) local udp_ports=(123 323)
# 检查 firewalld 是否正在运行 # 检查 firewalld 是否正在运行
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论