================================================================================================================= ERRORS ================================================================================================================= ________________________________________________________________________________________________ ERROR collecting test_moudle/testHome.py ________________________________________________________________________________________________ test_moudle\testHome.py:9: in <module> @pytest.mark.parametrize("case", read_yaml("./test_moudle/baidu.yaml")) yaml_untils.py:5: in read_yaml readYaml=yaml.safe_load(f) d:\python\lib\site-packages\yaml\__init__.py:125: in safe_load return load(stream, SafeLoader) d:\python\lib\site-packages\yaml\__init__.py:81: in load return loader.get_single_data() d:\python\lib\site-packages\yaml\constructor.py:49: in get_single_data node = self.get_single_node() d:\python\lib\site-packages\yaml\composer.py:36: in get_single_node document = self.compose_document() d:\python\lib\site-packages\yaml\composer.py:55: in compose_document node = self.compose_node(None, None) d:\python\lib\site-packages\yaml\composer.py:84: in compose_node node = self.compose_mapping_node(anchor) d:\python\lib\site-packages\yaml\composer.py:127: in compose_mapping_node while not self.check_event(MappingEndEvent): d:\python\lib\site-packages\yaml\parser.py:98: in check_event self.current_event = self.state() d:\python\lib\site-packages\yaml\parser.py:439: in parse_block_mapping_key "expected <block end>, but found %r" % token.id, token.start_mark) E yaml.parser.ParserError: while parsing a block mapping E in "./test_moudle/baidu.yaml", line 1, column 1 E expected <block end>, but found '-' E in "./test_moudle/baidu.yaml", line 3, column 1 ======================================================================================================== short test summary info ========================================================================================================= ERROR test_moudle/testHome.py - yaml.parser.ParserError: while parsing a block mapping !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ========================================================================================================
时间: 2025-07-23 14:09:33 浏览: 3
<think>我们正在解决一个特定的问题:在pytest参数化测试中解析YAML文件时遇到`yaml.parser.ParserError`,错误信息为`while parsing a block mapping`。这个错误通常表示YAML文件的结构有问题,特别是在缩进或映射的键值对方面。
根据用户提供的信息,我们上一次讨论涉及了pytest的使用(引用[1])和一些数据验证库(引用[2]),但当前问题聚焦于YAML解析错误。因此,我们将重点放在YAML文件的解析问题上。
### 问题分析
YAML文件对格式要求严格,常见的错误原因包括:
1. **缩进问题**:YAML使用空格缩进(通常为2或4个空格),不允许使用制表符(Tab)。
2. **映射格式错误**:在块映射中,键值对必须使用正确的分隔符(冒号`:`后必须跟一个空格)。
3. **字符串引号**:字符串有时需要引号,特别是当字符串包含特殊字符时。
4. **多行字符串**:多行字符串的管道符(`|`)或大于符号(`>`)使用不当。
5. **重复键**:同一个映射中键必须唯一。
在pytest参数化测试中,我们可能使用YAML文件来提供测试数据。例如,使用`pytest.mark.parametrize`从YAML文件中读取参数。
### 解决步骤
#### 1. 检查YAML文件的基本语法
使用在线的YAML验证器(例如:https://www.yamllint.com/)或安装yamllint工具来检查YAML文件。
在命令行中,可以使用:
```bash
pip install yamllint
yamllint your_file.yaml
```
#### 2. 检查YAML文件中的具体错误位置
错误信息`while parsing a block mapping`通常指出在解析一个块映射(即键值对集合)时出现问题。查看错误信息中给出的行号和列号,定位到具体位置。
例如,错误信息可能是:
```
yaml.parser.ParserError: while parsing a block mapping
in "<unicode string>", line 2, column 1:
key1: value1
^
expected <block end>, but found '<scalar>'
in "<unicode string>", line 3, column 1:
key2: value2
^
```
这通常表示在第一个映射(key1)之后,解析器期望一个结束标记(如减号`-`表示列表项或另一个键),但遇到了另一个键(key2)而没有正确的缩进或分隔。
#### 3. 修复常见的YAML格式问题
- **缩进问题**:确保使用空格,并且同一层级的元素缩进一致。
- **冒号后缺少空格**:每个键后面的冒号必须紧跟一个空格,然后是值。
- **特殊字符处理**:如果值中包含冒号、井号(#)等特殊字符,需要将整个字符串用引号括起来。
- **多行字符串**:使用`|`保留换行符或`>`折叠换行符时,注意缩进。
#### 4. 在Python中调试YAML加载
在测试代码中,单独加载YAML文件以确认问题:
```python
import yaml
with open('test_data.yaml', 'r') as f:
data = yaml.safe_load(f)
print(data)
```
如果出现错误,可以捕获异常并打印详细信息:
```python
try:
with open('test_data.yaml', 'r') as f:
data = yaml.safe_load(f)
except yaml.YAMLError as exc:
print(exc)
```
#### 5. 在pytest参数化中使用YAML
假设我们有一个YAML文件`test_data.yaml`,内容如下:
```yaml
- name: test1
input: 1
expected: 2
- name: test2
input: 3
expected: 4
```
在测试文件中,我们这样使用:
```python
import pytest
import yaml
def load_test_data():
with open('test_data.yaml', 'r') as f:
return yaml.safe_load(f)
@pytest.mark.parametrize('data', load_test_data())
def test_example(data):
# 这里data是一个字典,包含name, input, expected
assert data['input'] + 1 == data['expected']
```
如果YAML文件格式错误,上述代码在收集测试用例时就会抛出`yaml.parser.ParserError`。
### 示例修复
假设你的YAML文件如下(有错误的):
```yaml
test_cases:
- name: test1
input: 1
expected: 2
- name: test2
input: 3
expected:4 # 这里冒号后面没有空格
```
修正后:
```yaml
test_cases:
- name: test1
input: 1
expected: 2
- name: test2
input: 3
expected: 4 # 添加了空格
```
### 总结
遇到`yaml.parser.ParserError`时,重点检查YAML文件的格式,特别是缩进、冒号后的空格以及特殊字符的处理。通过工具验证和单独加载调试,可以快速定位问题。
§§相关问题§§
1. 如何避免在YAML文件中出现解析错误?
2. 在pytest中除了YAML,还有哪些常用的参数化数据源?
3. 如何为YAML文件编写测试以确保其格式正确?</think>### 解决 pytest 参数化测试中的 YAML 解析错误
当在 pytest 参数化测试中出现 `yaml.parser.ParserError: while parsing a block mapping` 错误时,通常是由于 YAML 文件格式问题导致的。以下是完整解决方案:
#### 1. **错误原因分析**
- **块映射格式错误**:YAML 要求键值对使用 `key: value` 格式,冒号后必须有空格
- **缩进问题**:YAML 严格依赖空格缩进(推荐 2 空格),禁止使用 Tab 制表符
- **特殊字符处理**:未转义的特殊字符(如 `:`、`#`、`{}`)会破坏解析
- **数据结构不匹配**:参数化期望的数据结构与 YAML 文件实际结构不一致
#### 2. **解决方案步骤**
##### (1) 验证 YAML 格式
使用在线验证工具(如 [YAMLLint](https://www.yamllint.com/))或命令行工具检查:
```bash
pip install yamllint
yamllint your_test_data.yaml
```
##### (2) 修正常见格式问题
```yaml
# ✅ 正确示例(注意冒号后的空格和缩进)
test_cases:
- case_id: 1
input: "value"
expected: 42
- case_id: 2
input:
nested:
key: "data" # 嵌套结构缩进
```
##### (3) 在 pytest 中添加安全加载
修改测试代码中的 YAML 加载方式:
```python
import yaml
import pytest
def load_test_data():
with open("test_data.yaml", "r") as f:
# 使用 safe_load 避免意外类型转换
return yaml.safe_load(f)["test_cases"]
@pytest.mark.parametrize("case", load_test_data())
def test_example(case):
assert process(case["input"]) == case["expected"]
```
##### (4) 处理特殊字符
对包含 `:`、`#` 等字符的值使用引号:
```yaml
- input: "special:character#value" # 用引号包裹
expected: "result"
```
#### 3. **调试技巧**
在测试文件中添加预处理检查:
```python
# conftest.py
def pytest_collection_modifyitems(items):
try:
with open("test_data.yaml") as f:
yaml.safe_load(f)
except yaml.parser.ParserError as e:
print(f"❌ YAML 解析错误: {e}")
raise
```
#### 4. **替代方案**
对于复杂数据结构,改用 JSON 格式(更严格的语法):
```python
# test_data.json
[
{"input": "value1", "expected": 42},
{"input": "value2", "expected": 100}
]
# 在测试中加载
import json
with open("test_data.json") as f:
test_data = json.load(f)
```
### 常见错误场景修复
| 错误场景 | 错误示例 | 修复方案 |
|---------|---------|---------|
| 缺少空格 | `key:value` | `key: value` |
| Tab缩进 | `→key: value` | 替换为 2 空格 |
| 未转义字符 | `input: foo:bar` | `input: "foo:bar"` |
| 结构不一致 | 参数化期望列表但 YAML 是字典 | 调整 YAML 结构匹配测试期望 |
> **关键提示**:当使用 `@pytest.mark.parametrize` 时,确保 YAML 文件顶层是列表结构(除非在代码中做了额外处理),因为参数化直接需要可迭代对象[^1]。
阅读全文