python pytest+yaml 接口自动化测试框架
时间: 2025-07-30 20:17:15 浏览: 17
<think>我们正在构建一个基于Python的接口自动化测试框架,使用pytest和YAML。根据引用内容,框架的主要组件包括:
- Python:主开发语言
- Requests:用于发送HTTP请求
- Pytest:测试执行与用例管理
- YAML:用于管理测试数据
- Allure:生成测试报告(可选,但常见)
- Logging:用于日志记录
搭建步骤一般包括:
1. 项目结构设计
2. 封装HTTP请求(使用requests)
3. 测试数据管理(YAML文件)
4. 测试用例编写(使用pytest)
5. 测试执行与报告生成(pytest结合Allure)
6. 日志配置
下面我们按照步骤详细说明。
### 1. 项目结构设计
典型的项目结构如下:
```
project/
├── common/ # 公共模块
│ ├── __init__.py
│ ├── request_util.py # 封装requests
│ └── log_util.py # 日志配置
├── testcases/ # 测试用例
│ ├── __init__.py
│ └── test_demo.py # 测试用例文件
├── testdata/ # 测试数据(YAML文件)
│ └── demo_data.yml
├── conftest.py # pytest全局配置
├── pytest.ini # pytest配置文件
└── requirements.txt # 依赖包
```
### 2. 封装HTTP请求
在`common/request_util.py`中,我们可以封装一个发送请求的类,例如:
```python
import requests
import logging
class RequestUtil:
def __init__(self):
self.session = requests.Session()
def send_request(self, method, url, **kwargs):
logging.info(f"请求方法: {method}, 请求URL: {url}, 请求参数: {kwargs}")
resp = self.session.request(method, url, **kwargs)
# 可以在这里添加统一的响应处理,比如状态码检查、日志记录等
logging.info(f"响应状态码: {resp.status_code}, 响应内容: {resp.text}")
return resp
```
### 3. 测试数据管理(YAML)
YAML文件用于存储测试数据,例如`testdata/demo_data.yml`:
```yaml
test_case1:
method: get
url: http://httpbin.org/get
params:
key1: value1
key2: value2
expected_status: 200
```
### 4. 测试用例编写
使用pytest编写测试用例,结合YAML数据驱动。我们可以使用`pytest.mark.parametrize`来实现数据驱动。但是,为了更灵活地使用YAML,我们可以先读取YAML文件,然后参数化。
在`testcases/test_demo.py`中:
```python
import pytest
import yaml
from common.request_util import RequestUtil
# 读取YAML文件
def load_testdata(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
return data
# 获取测试数据
test_data = load_testdata('../testdata/demo_data.yml')
class TestDemo:
@pytest.mark.parametrize('case_name, case_data', test_data.items())
def test_api(self, case_name, case_data):
req = RequestUtil()
method = case_data['method']
url = case_data['url']
params = case_data.get('params', {})
expected_status = case_data['expected_status']
resp = req.send_request(method, url, params=params)
assert resp.status_code == expected_status
```
### 5. 配置pytest
在项目根目录创建`pytest.ini`文件:
```ini
[pytest]
addopts = -v --alluredir=./allure-results
testpaths = testcases
python_files = test_*.py
python_classes = Test*
python_functions = test_*
```
### 6. 日志配置
在`common/log_util.py`中配置日志:
```python
import logging
import os
def setup_logging():
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
logging.basicConfig(level=logging.INFO, format=log_format)
# 在项目初始化时调用
setup_logging()
```
### 7. 安装依赖
创建`requirements.txt`文件:
```
requests
pytest
pyyaml
allure-pytest
```
安装依赖:
```bash
pip install -r requirements.txt
```
### 8. 运行测试并生成报告
运行测试:
```bash
pytest
```
生成Allure报告(需要先安装Allure命令行工具):
```bash
allure serve ./allure-results
```
### 9. 使用conftest.py进行全局配置
`conftest.py`可以用于定义pytest的fixture,例如我们可以在这里初始化日志和请求工具。
```python
import pytest
from common.log_util import setup_logging
from common.request_util import RequestUtil
@pytest.fixture(scope="session", autouse=True)
def init_logging():
setup_logging()
@pytest.fixture(scope="class")
def req():
return RequestUtil()
```
然后测试用例中可以这样使用:
```python
class TestDemo:
@pytest.mark.parametrize('case_name, case_data', test_data.items())
def test_api(self, req, case_name, case_data):
method = case_data['method']
url = case_data['url']
params = case_data.get('params', {})
expected_status = case_data['expected_status']
resp = req.send_request(method, url, params=params)
assert resp.status_code == expected_status
```
### 注意事项
- 路径问题:读取YAML文件时,注意相对路径。上述示例中,测试用例文件在`testcases`目录,YAML文件在`testdata`目录,所以使用`../testdata/demo_data.yml`。也可以使用绝对路径,但建议通过配置文件管理路径。
- 封装扩展:根据实际需求,可以进一步封装断言、数据库操作等。
- 环境配置:可以设计多环境配置(如测试环境、生产环境),通过配置文件或命令行参数切换。
以上就是一个基本的框架搭建指南。根据实际项目需求,可以在此基础上进行扩展和优化。
§§相关问题§§
1. 如何设计数据驱动测试,使得测试数据和测试用例分离?
2. 在接口自动化测试中,如何处理登录状态的保持(如cookies或token)?
3. 如何使用Allure报告来增强测试结果的可视化?
4. 如何将接口自动化测试框架集成到持续集成(CI)系统中?
5. 在接口测试中,如何对接口返回的复杂数据结构(如嵌套JSON)进行断言?</think>### Python + Pytest + YAML 接口自动化测试框架搭建指南
#### 1. 框架核心组件
```mermaid
graph TD
A[测试框架] --> B[Python]
A --> C[Requests]
A --> D[Pytest]
A --> E[YAML]
A --> F[Allure]
A --> G[Logging]
```
#### 2. 搭建步骤
**步骤1:环境准备**
```bash
# 创建虚拟环境
python -m venv venv
source venv/bin/activate
# 安装依赖
pip install requests pytest pyyaml allure-pytest pytest-html
```
**步骤2:项目结构设计**
```
project/
├── common/ # 公共模块
│ ├── request_util.py # 请求封装
│ └── log_util.py # 日志工具
├── testcases/ # 测试用例
│ ├── __init__.py
│ └── test_api.py # 测试脚本
├── testdata/ # 测试数据
│ └── api_data.yml # YAML数据文件
├── conftest.py # pytest全局配置
├── pytest.ini # pytest配置文件
└── requirements.txt # 依赖清单
```
**步骤3:封装HTTP请求(request_util.py)**
```python
import requests
import logging
class RequestUtil:
def __init__(self):
self.session = requests.Session()
logging.basicConfig(level=logging.INFO)
def send_request(self, method, url, **kwargs):
"""统一请求入口"""
logging.info(f"请求参数: {method} {url} {kwargs}")
resp = self.session.request(method, url, **kwargs)
logging.info(f"响应状态: {resp.status_code}, 响应内容: {resp.text[:200]}")
return resp
```
**步骤4:YAML测试数据管理(testdata/api_data.yml)**
```yaml
login_test:
description: "用户登录接口测试"
request:
method: POST
url: "/api/login"
headers:
Content-Type: "application/json"
json:
username: "testuser"
password: "Pass123"
validate:
- eq: [status_code, 200]
- contains: [content, "token"]
```
**步骤5:测试用例编写(testcases/test_api.py)**
```python
import pytest
import yaml
from common.request_util import RequestUtil
# 加载YAML测试数据
def load_testdata(file_path):
with open(file_path, 'r') as f:
return yaml.safe_load(f)
test_data = load_testdata('../testdata/api_data.yml')
class TestAPI:
@pytest.mark.parametrize("case_name", test_data.keys())
def test_api(self, case_name):
data = test_data[case_name]
req = RequestUtil()
resp = req.send_request(
data['request']['method'],
data['request']['url'],
headers=data['request'].get('headers', {}),
json=data['request'].get('json', {})
)
# 断言验证
for validate in data['validate']:
key, expected = validate['eq']
if key == "status_code":
assert resp.status_code == expected
elif key == "content":
assert expected in resp.text
```
**步骤6:配置全局Fixture(conftest.py)**
```python
import pytest
@pytest.fixture(scope="session", autouse=True)
def setup():
print("\n>>> 测试开始 <<<")
yield
print("\n>>> 测试结束 <<<")
```
**步骤7:Pytest配置(pytest.ini)**
```ini
[pytest]
addopts = -v --alluredir=./allure-results --html=report.html
testpaths = testcases
python_files = test_*.py
python_classes = Test*
python_functions = test_*
```
#### 3. 执行测试
```bash
# 运行测试
pytest
# 生成Allure报告
allure serve allure-results
# 生成HTML报告(直接查看report.html)
```
#### 4. 关键优化点
1. **参数化驱动**:通过YAML实现测试数据与代码分离
2. **动态关联**:使用`pytest`的`fixture`处理token传递
```python
@pytest.fixture
def auth_token():
# 获取登录token并传递给测试用例
return get_token()
```
3. **异常处理**:在请求封装中添加重试机制
```python
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3))
def send_request(self, method, url, **kwargs):
...
```
4. **多环境配置**:使用`pytest-base-url`插件切换测试环境
```bash
pytest --base-url https://api.test.com
```
#### 5. 框架优势
1. **可维护性**:YAML数据驱动便于非技术人员维护测试用例
2. **扩展性**:模块化设计支持添加数据库校验、消息队列等组件
3. **可视化报告**:Allure提供多维度测试分析
4. **CI/CD集成**:通过`pytest`命令轻松接入Jenkins/GitHub Actions[^3]
阅读全文
相关推荐




















