pytest框架的接口自动化写法

1. 项目结构

project/
├── conftest.py           # pytest 全局配置和共享 Fixture
├── requirements.txt      # 依赖库列表
├── config/
│   └── settings.py       # 环境配置(测试/生产环境切换)
├── tests/                # 测试用例目录
│   ├── test_user_api.py  # 用户相关接口测试
│   └── test_order_api.py # 订单相关接口测试
├── utils/                # 工具类
│   ├── http_client.py    # 封装的 HTTP 请求工具
│   └── logger.py         # 日志管理
└── data/                 # 测试数据
    └── test_data.json

2. 安装依赖

在 requirements.txt 中添加:

pytest
requests
pytest-html  # 生成HTML报告
pytest-xdist  # 并行执行
python-dotenv  # 环境变量管理

安装依赖:

pip install -r requirements.txt

3. 核心代码实现

3.1 配置文件 config/settings.py
import os
from dotenv import load_dotenv

load_dotenv()  # 加载 .env 文件

class Config:
    BASE_URL = os.getenv("BASE_URL", "https://api.example.com")
    API_KEY = os.getenv("API_KEY")  # 认证密钥
3.2 HTTP 请求工具 utils/http_client.py
import requests
from config.settings import Config

class HttpClient:
    def __init__(self):
        self.base_url = Config.BASE_URL
        self.headers = {"Authorization": f"Bearer {Config.API_KEY}"}

    def get(self, endpoint, params=None):
        url = f"{self.base_url}{endpoint}"
        return requests.get(url, headers=self.headers, params=params)

    def post(self, endpoint, data=None):
        url = f"{self.base_url}{endpoint}"
        return requests.post(url, headers=self.headers, json=data)

    # 可扩展 PUT、DELETE 等方法

4. 编写测试用例 tests/test_user_api.py

4.1 基础用例
import pytest
from utils.http_client import HttpClient

client = HttpClient()

def test_get_user():
    """测试获取用户信息"""
    response = client.get("/users/1")
    assert response.status_code == 200
    assert response.json()["id"] == 1

def test_create_user():
    """测试创建用户"""
    user_data = {"name": "Alice", "email": "[email protected]"}
    response = client.post("/users", data=user_data)
    assert response.status_code == 201
    assert "id" in response.json()
4.2 参数化测试
import pytest

test_data = [
    (1, 200),  # 存在的用户ID
    (999, 404),  # 不存在的用户ID
]

@pytest.mark.parametrize("user_id, expected_status", test_data)
def test_get_user_status(user_id, expected_status):
    response = client.get(f"/users/{user_id}")
    assert response.status_code == expected_status

5. 使用 Fixture 管理资源

在 conftest.py 中定义共享 Fixture:

import pytest
from utils.http_client import HttpClient

@pytest.fixture(scope="module")
def client():
    """共享的 HTTP 客户端"""
    return HttpClient()

@pytest.fixture
def cleanup_user(client):
    """清理测试用户"""
    user_id = None
    yield user_id  # 测试执行前
    if user_id:  # 测试执行后清理
        client.delete(f"/users/{user_id}")

在测试用例中使用:

def test_create_and_delete_user(client, cleanup_user):
    user_data = {"name": "Bob", "email": "[email protected]"}
    response = client.post("/users", data=user_data)
    user_id = response.json()["id"]
    cleanup_user = user_id  # 传递给 Fixture 清理
    assert response.status_code == 201

6. 运行测试

6.1 基础运行
pytest tests/ -v  # 详细模式
6.2 生成 HTML 报告
pytest tests/ --html=report.html
6.3 并行执行(利用多核CPU)
pytest tests/ -n 4  # 启动4个进程

7. 高级功能

7.1 动态环境切换

在 .env 文件中定义环境变量:

BASE_URL=https://test-api.example.com
API_KEY=test_key

通过命令行切换环境:

BASE_URL=https://prod-api.example.com pytest tests/
7.2 Mock 外部依赖

使用 pytest-mock 模拟第三方服务:

def test_external_api(mocker):
    mock_response = mocker.Mock()
    mock_response.status_code = 200
    mock_response.json.return_value = {"success": True}
    mocker.patch("requests.get", return_value=mock_response)

    response = client.get("/external-api")
    assert response.json()["success"] is True
7.3 数据驱动测试

从 JSON 文件加载测试数据:

import json
import pytest

with open("data/test_data.json") as f:
    test_data = json.load(f)

@pytest.mark.parametrize("data", test_data)
def test_create_users(data):
    response = client.post("/users", data=data)
    assert response.status_code == 201

8. 最佳实践

  1. 分离测试逻辑与数据:将测试数据存储在外部文件(JSON/YAML)中。

  2. 统一断言处理:封装公共断言方法(如检查响应格式)。

  3. 异常处理:捕获预期异常并验证错误码。

  4. 日志记录:在 utils/logger.py 中集成日志,记录请求和响应详情。

  5. 持续集成:通过 GitHub Actions/Jenkins 定时执行测试。


9. 完整示例:带日志和异常处理的测试

import logging
from utils.logger import setup_logger

setup_logger()  # 初始化日志
logger = logging.getLogger(__name__)

def test_complex_flow(client):
    try:
        # 步骤1:创建用户
        user_data = {"name": "Charlie"}
        create_res = client.post("/users", data=user_data)
        assert create_res.status_code == 201
        user_id = create_res.json()["id"]
        logger.info(f"Created user {user_id}")

        # 步骤2:查询用户
        get_res = client.get(f"/users/{user_id}")
        assert get_res.json()["name"] == "Charlie"

    except Exception as e:
        logger.error(f"Test failed: {str(e)}")
        raise  # 标记测试失败

通过以上设计,你可以快速搭建一个 高可维护性、可扩展的接口自动化测试框架

你可能感兴趣的:(python,pytest,接口自动化)