给一段代码,实现python 使用pytest 框架进行接口测试,必须有setup和teardown函数,并且在setup 方法中获取token,在teardown中删除token,
时间: 2025-07-27 19:27:07 浏览: 3
<think>根据用户需求,我们需要实现一个使用pytest框架的接口测试示例,其中包含:1.在setup(使用fixture的setup部分)中获取token2.在teardown(使用fixture的teardown部分)中删除token3.在测试方法中调用接口(使用获取到的token)参考引用内容,我们可以设计如下:-使用一个fixture来管理token的生命周期,在fixture的setup部分获取token并传递给测试用例,在teardown部分删除token(调用登出接口并清理存储)。
-使用一个类来封装接口方法,如登录、登出以及其他需要token的接口。
-使用yaml文件来存储token(也可以使用其他方式,但根据引用[3]使用了yaml)。注意:我们假设有一个登录接口(返回token)和一个登出接口(使token失效)。同时,我们假设其他接口需要携带token(在请求头中)。下面是一个完整的示例代码:</think>以下是一个使用 Python pytest 框架进行接口测试的完整实现,包含在 setup 中获取 token、在 teardown 中删除 token,并在测试方法中进行接口调用:
```python
import pytest
import requests
import yaml
from typing import Dict, Optional
# 接口封装类
class APIClient:
BASE_URL = "http://api.example.com"
TOKEN_FILE = "tokens.yaml" # 存储token的文件
def __init__(self):
self.session = requests.Session()
self.token = None
def login(self, username: str, password: str) -> Optional[str]:
"""获取认证token"""
url = f"{self.BASE_URL}/login"
payload = {"username": username, "password": password}
response = self.session.post(url, json=payload)
if response.status_code == 200:
self.token = response.json().get("token")
return self.token
return None
def logout(self) -> bool:
"""注销token"""
if not self.token:
return False
url = f"{self.BASE_URL}/logout"
headers = {"Authorization": f"Bearer {self.token}"}
response = self.session.post(url, headers=headers)
return response.status_code == 200
def save_token(self, user: str):
"""保存token到YAML文件"""
if not self.token:
return
try:
# 读取现有token
tokens = {}
try:
with open(self.TOKEN_FILE, 'r') as f:
tokens = yaml.safe_load(f) or {}
except FileNotFoundError:
pass
# 更新并保存
tokens[user] = self.token
with open(self.TOKEN_FILE, 'w') as f:
yaml.dump(tokens, f)
except Exception as e:
print(f"保存token失败: {e}")
def clear_token(self, user: str):
"""清理token"""
try:
with open(self.TOKEN_FILE, 'r') as f:
tokens = yaml.safe_load(f) or {}
if user in tokens:
del tokens[user]
with open(self.TOKEN_FILE, 'w') as f:
yaml.dump(tokens, f)
except FileNotFoundError:
pass
def get_user_info(self):
"""获取用户信息"""
url = f"{self.BASE_URL}/user/info"
headers = {"Authorization": f"Bearer {self.token}"}
return self.session.get(url, headers=headers)
def create_resource(self, data: Dict):
"""创建资源"""
url = f"{self.BASE_URL}/resources"
headers = {"Authorization": f"Bearer {self.token}"}
return self.session.post(url, json=data, headers=headers)
# pytest fixture 管理token生命周期
@pytest.fixture(scope="function")
def api_client():
"""setup/teardown fixture管理token生命周期"""
client = APIClient()
user = "test_user"
password = "test_password"
# Setup: 获取并保存token
token = client.login(user, password)
if not token:
pytest.skip("登录失败,无法获取token")
client.save_token(user)
yield client # 将客户端实例传递给测试用例
# Teardown: 清理token
client.logout() # 调用登出接口
client.clear_token(user) # 清理本地存储
# 测试用例
def test_user_info(api_client):
"""测试获取用户信息接口"""
response = api_client.get_user_info()
assert response.status_code == 200
data = response.json()
assert "username" in data
assert "email" in data
def test_create_resource(api_client):
"""测试创建资源接口"""
test_data = {"name": "Test Resource", "type": "example"}
response = api_client.create_resource(test_data)
assert response.status_code == 201
data = response.json()
assert "id" in data
assert data["name"] == test_data["name"]
```
### 关键实现说明:
1. **Token 生命周期管理**:
- `login()` 方法实现登录认证并返回 token[^2]
- `save_token()` 使用 YAML 文件存储 token(实际项目中可用数据库或缓存)[^3]
- `logout()` 调用登出接口使 token 失效
- `clear_token()` 清理本地存储的 token
2. **Fixture 设计**:
- 使用 `@pytest.fixture` 创建测试夹具[^1]
- `scope="function"` 确保每个测试函数独立执行
- `yield` 实现 setup/teardown 分离:
```python
# Setup 代码
yield client # 测试执行点
# Teardown 代码
```
3. **测试用例设计**:
- 测试方法通过 `api_client` fixture 获取已认证的客户端
- 直接调用封装好的接口方法进行测试
- 验证响应状态码和返回数据
4. **异常处理**:
- 登录失败时使用 `pytest.skip()` 跳过测试
- 文件操作异常处理
- Token 为空时的安全校验
### 执行流程:
1. 测试开始时,`api_client` fixture 执行 setup:
- 创建 API 客户端实例
- 调用登录接口获取 token
- 保存 token 到文件
2. 测试方法使用已认证的客户端调用接口
3. 测试结束后,`api_client` fixture 执行 teardown:
- 调用登出接口使 token 失效
- 清理本地存储的 token
### 最佳实践建议:
1. **配置分离**:
```python
# config.py
BASE_URL = os.getenv("API_URL", "http://api.example.com")
TEST_USER = os.getenv("TEST_USER", "test_user")
TEST_PASSWORD = os.getenv("TEST_PASSWORD", "test_password")
```
2. **参数化测试**:
```python
@pytest.mark.parametrize("resource_type", ["A", "B", "C"])
def test_resource_types(api_client, resource_type):
data = {"name": f"Test-{resource_type}", "type": resource_type}
response = api_client.create_resource(data)
assert response.status_code == 201
```
3. **使用 pytest.ini 配置**:
```ini
[pytest]
addopts = -v --tb=short
markers =
smoke: smoke tests
regression: regression tests
```
4. **并行执行注意事项**:
- 使用 `scope="session"` 实现全局只登录一次
- 确保不同测试的 token 互不干扰
- 使用临时文件或内存存储替代文件存储
阅读全文
相关推荐


















