基于Python + Requests + Unitest + HTMLTestRunner_PY3的接口自动化测试框架
前言:
2025开年第一篇((#^.^#))。
此框架是基于Python + Requests + Unitest + HTMLTestRunner_PY3接口自动化测试框架,测试接口和测试数据的维护都是通过代码维护的。
对于接口的请求URL、请求方式、请求头、请求体以及响应结果的断言都需要自己去做对应的维护。
一、执行逻辑介绍
获取测试Token → 授权测试接口 → 执行测试用例 → 输出测试报告
二、代码目录结构介绍
- case:测试用例
- config:配置文件(Token、Requests二封)
- data:接口数据(请求URL、请求方式、请求头、请求体、断言、日志)
- debug:调试数据
- framework:三方工具
- report:测试报告
- run:运行主文件
三、代码介绍
config(config.py):
# -*- coding: UTF-8 -*- import os import logging import requests from requests.adapters import HTTPAdapter from urllib3.util import Retry BASE_URL = os.getenv("BASE_URL", "http://127.0.0.1") LOGIN_URL = "/lit/login" LOGIN_USER = { "username": os.getenv("LOGIN_USER", "lit"), "password": os.getenv("LOGIN_PWD", "lit"), "token": os.getenv("LOGIN_TOKEN", "wntoken"), } logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s") class RequestHandle: def __init__(self, base_url: str = BASE_URL, timeout: float = 5.0): self.base_url = base_url.rstrip("/") self.timeout = timeout self.session = requests.Session() retry = Retry( total=3, backoff_factor=0.3, status_forcelist=(500, 502, 503, 504), allowed_methods=["GET", "POST", "PUT", "DELETE", "PATCH"], ) adapter = HTTPAdapter(max_retries=retry) self.session.mount("http://", adapter) self.session.mount("https://", adapter) def request(self, path: str, method: str, **kwargs): url = path if path.startswith("http") else f"{self.base_url}{path}" try: res = self.session.request(method=method, url=url, timeout=self.timeout, verify=False, **kwargs) res.raise_for_status() return res except requests.RequestException as exc: logger.error("请求失败: %s %s, err=%s", method, url, exc) raise class TokenMes: def __init__(self, client: RequestHandle | None = None): self.client = client or RequestHandle() def token(self) -> str: payload = { "username": LOGIN_USER["username"], "password": LOGIN_USER["password"], "token": LOGIN_USER["token"], } res = self.client.request(LOGIN_URL, "POST", json=payload) data = res.json() # 假设 token 在 data["res"]["token"] token = data.get("res", {}).get("token") if not token: raise ValueError(f"未获取到 token,响应: {data}") logger.info("Token 获取成功") return token
data(product_data.py):
# -*- coding: UTF-8 -*- from config.token_cf import TokenMes, RequestHandle class ProductManagement: def __init__(self): self.client = RequestHandle() self.auth_token = f"Bearer {TokenMes(self.client).token()}" def add_product(self, name="API测试新增产品", desc="产品描述字段", status=1): headers = { "Authorization": self.auth_token, "Content-Type": "application/json", } body = { "product_name": name, "description": desc, "status": status, } res = self.client.request("/product", "POST", headers=headers, json=body) data = res.json() assert data.get("code") == "200", f"预期 code=200, 实际: {data}" return data
case(test_product.py):
# -*- coding: UTF-8 -*- import unittest from data.product_data import ProductManagement class ProdList(unittest.TestCase): """产品列表""" def test_add_product(self): """新增产品""" data = ProductManagement().add_product() # 可根据响应结构进一步校验 self.assertEqual(data.get("code"), "200") self.assertTrue(data.get("res"), "返回结果为空")
run.py:
************
四、执行结果(报告示例)



浙公网安备 33010602011771号