Python接口自动化框架pytest+requests+Allure

以下是一个基于 Python 的接口自动化框架示例,结合 pytest + requests + Allure 实现,包含完整的项目结构、数据驱动、断言机制和报告生成功能。


1. 项目目录结构

api_test_project/
├── config/                  # 配置文件
│   └── config.yaml          # 环境配置(测试/生产环境URL等)
├── test_cases/              # 测试用例
│   ├── __init__.py
│   ├── test_login.py        # 登录接口测试
│   └── test_user.py         # 用户管理接口测试
├── utils/                   # 工具类
│   ├── __init__.py
│   ├── request_util.py      # 封装requests请求
│   └── assert_util.py       # 自定义断言方法
├── data/                    # 测试数据
│   ├── login_data.json      # 登录接口参数化数据
│   └── user_data.csv
├── conftest.py              # pytest全局fixture
├── requirements.txt         # 依赖库
└── pytest.ini               # pytest配置文件

2. 核心代码示例

(1) 封装请求工具类 utils/request_util.py

import requests
import yaml
from pathlib import Path

class RequestUtil:
    def __init__(self):
        # 读取配置文件(YAML格式)
        config_path = Path(__file__).parent.parent / "config" / "config.yaml"
        with open(config_path, 'r') as f:
            self.config = yaml.safe_load(f)
        self.base_url = self.config['base_url']
        self.session = requests.Session()

    def send_request(self, method, endpoint, params=None, data=None, json=None, headers=None):
        url = f"{self.base_url}{endpoint}"
        # 发送请求
        response = self.session.request(
            method=method.upper(),
            url=url,
            params=params,
            data=data,
            json=json,
            headers=headers
        )
        return response

# 示例:全局请求对象
request_util = RequestUtil()

(2) 测试用例 test_cases/test_login.py

import pytest
import allure
from utils.request_util import request_util
from utils.assert_util import assert_status_code, assert_json_key

@allure.feature("登录模块")
class TestLogin:
    @allure.story("用户登录")
    @pytest.mark.parametrize("case_data", [
        {"username": "admin", "password": "123456", "expected_code": 200},
        {"username": "invalid", "password": "wrong", "expected_code": 401}
    ])
    def test_login(self, case_data):
        # 发送POST请求
        endpoint = "/api/login"
        payload = {
            "username": case_data["username"],
            "password": case_data["password"]
        }
        response = request_util.send_request("POST", endpoint, json=payload)
        
        # 断言状态码和响应体
        assert_status_code(response, case_data["expected_code"])
        if response.status_code == 200:
            assert_json_key(response, "token")  # 验证返回token字段

(3) 自定义断言工具 utils/assert_util.py

def assert_status_code(response, expected_code):
    assert response.status_code == expected_code, \
        f"状态码不符!预期: {expected_code}, 实际: {response.status_code}"

def assert_json_key(response, key):
    json_data = response.json()
    assert key in json_data, f"响应中缺少关键字段: {key}"
    return json_data[key]  # 返回字段值供后续使用(如获取token)

3. 数据驱动示例

(1) 从JSON文件读取数据 data/login_data.json

[
    {
        "username": "test_user",
        "password": "pass123",
        "expected_code": 200
    },
    {
        "username": "locked_user",
        "password": "wrong_pass",
        "expected_code": 403
    }
]

(2) 在测试用例中加载JSON数据

import json
from pathlib import Path

def load_json_data(file_name):
    data_path = Path(__file__).parent.parent / "data" / file_name
    with open(data_path, 'r') as f:
        return json.load(f)

@pytest.mark.parametrize("case_data", load_json_data("login_data.json"))
def test_login_with_json_data(case_data):
    # 测试逻辑同上
    pass

4. 配置文件 config/config.yaml

# 测试环境配置
base_url: "https://test-api.example.com"
headers:
  Content-Type: "application/json"

# 生产环境配置(通过环境变量切换)
# base_url: "https://prod-api.example.com"

5. 运行测试并生成报告

(1) 安装依赖 requirements.txt

pytest==7.4.0
requests==2.31.0
PyYAML==6.0.1
allure-pytest==2.13.2
pytest-html==4.1.1

(2) 执行测试命令

# 运行所有测试并生成Allure报告
pytest --alluredir=./results --clean-alluredir
allure serve ./results

# 或生成HTML报告
pytest --html=report.html

6. 高级功能扩展

(1) 接口依赖处理(获取Token)

# 在conftest.py中定义全局fixture
@pytest.fixture(scope="session")
def auth_token():
    payload = {"username": "admin", "password": "123456"}
    response = request_util.send_request("POST", "/api/login", json=payload)
    token = response.json()["token"]
    return token

# 在测试用例中使用token
def test_user_info(auth_token):
    headers = {"Authorization": f"Bearer {auth_token}"}
    response = request_util.send_request("GET", "/api/user/1", headers=headers)

(2) 数据库校验

# 添加数据库工具类(如使用SQLAlchemy)
from sqlalchemy import create_engine

class DBUtil:
    def __init__(self, db_url):
        self.engine = create_engine(db_url)
    
    def query_user(self, user_id):
        with self.engine.connect() as conn:
            result = conn.execute(f"SELECT * FROM users WHERE id = {user_id}")
            return result.fetchone()

# 在测试用例中验证数据库
def test_create_user():
    # 调用接口创建用户
    response = request_util.send_request("POST", "/api/users", json={"name": "Alice"})
    user_id = response.json()["id"]
    
    # 验证数据库
    db_util = DBUtil("mysql://user:pass@localhost/db")
    user = db_util.query_user(user_id)
    assert user["name"] == "Alice"

7. 框架选择建议

  • 轻量级需求:直接使用 pytest + requests(如上述示例)。
  • 企业级复杂场景:选择 HttpRunnerTavern,它们提供更丰富的内置功能:
    • HttpRunner:支持YAML/JSON用例编写、性能测试、CI/CD集成。
    - test:
        name: 登录接口测试
        request:
          url: /api/login
          method: POST
          json:
            username: admin
            password: 123456
        validate:
          - eq: [status_code, 200]
          - contains: $.token
    

总结

该框架具备以下特点:

  1. 模块化设计:分离请求封装、断言、数据管理。
  2. 易于扩展:支持数据库校验、Mock服务、分布式执行。
  3. 报告友好:Allure报告展示详细测试结果。
  4. 适合团队协作:标准化项目结构,方便多人维护。

可根据实际需求调整技术栈(如用 unittest 替代 pytest,或用 FastAPI 搭建Mock服务)。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容