主要特性概述
技术栈:基于 Python 语言,使用 pytest 测试框架、requests 库处理 HTTP 请求、YAML 文件管理测试数据、Allure 生成测试报告,以及 logging 模块处理日志。
模块化设计:框架分为四个核心模块,确保代码复用性和可维护性。
新手友好:提供完整示例代码、模块调用关系说明、YAML 格式规范,以及详细开发文档。
数据管理:所有测试数据通过结构化 YAML 文件统一管理,支持扩展。
报告与日志:Allure 报告包含执行状态、响应数据和错误日志;日志系统区分模块输出层级。
安装与设置
创建虚拟环境并安装依赖:pip install pytest requests pyyaml allure-pytest
。在 pytest.ini
中配置 Allure 输出:addopts = --alluredir allure-results
。运行测试:pytest
,然后生成报告:allure serve allure-results
。
示例用法
假设基础 API URL 为 https://api.example.com
。从 data/test_data.yaml
加载数据,执行测试,并通过 Allure 查看报告,包括响应和日志附件。
框架详细设计与实现
本框架旨在提供一个可扩展的 Python 接口自动化测试解决方案,结合 pytest 的灵活性、requests 的 HTTP 处理能力、PyYAML 的数据解析、Allure 的可视化报告,以及 Python logging 的追踪输出。设计强调模块化,以实现关注点分离,便于维护和扩展。例如,低层 HTTP 方法封装处理参数解析和错误重试,而高层接口和关键字在其基础上构建领域特定操作。这种分层方法减少了重复代码,并提升了复用性,符合 Python 测试生态中的最佳实践。
针对新手,项目结构扁平,提供独立示例和全面文档。测试采用数据驱动,从 YAML 拉取配置,支持多环境(如开发、生产)而无需修改代码。Allure 报告包括关键细节,如测试状态(通过/失败)、响应体、错误栈和时间戳;日志配置为每个模块输出 DEBUG/INFO/ERROR 级别,便于调试。
项目结构
为清晰起见,组织项目如下:
api_test_framework/
├── utils/ # 请求方法封装模块
│ └── request_handler.py
├── api/ # HTTP 接口封装模块
│ └── api_endpoints.py
├── keywords/ # 关键字封装模块
│ └── keywords.py
├── tests/ # 测试用例模块
│ └── test_cases.py
├── data/ # YAML 测试数据
│ └── test_data.yaml
├── logs/ # 日志输出(自动生成)
├── docs/ # 文档
│ └── framework_guide.md
├── conftest.py # Pytest fixture 和 Allure 设置
├── pytest.ini # Pytest 配置
├── logging_config.py # 日志配置
└── requirements.txt # 依赖项
requirements.txt
内容:
pytest
requests
pyyaml
allure-pytest
模块细节与代码示例
以下是四个核心模块的实现细节和代码片段。所有模块导入必要库。为便于新人理解,已简化 request_handler.py 和 api_endpoints.py,去除异常处理逻辑,使代码更简洁直接。
请求方法封装模块 (
utils/request_handler.py
)
该模块封装 requests 的基本 HTTP 方法,添加日志记录。去除异常处理,仅执行请求并返回响应。import requests import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') class RequestHandler: def __init__(self): self.logger = logging.getLogger('RequestHandler') def get(self, url, params=None, headers=None): response = requests.get(url, params=params, headers=headers) self.logger.info(f"GET {url} with status {response.status_code}") return response def post(self, url, data=None, json=None, headers=None): response = requests.post(url, data=data, json=json, headers=headers) self.logger.info(f"POST {url} with status {response.status_code}") return response # 类似实现 put() 和 delete()...
HTTP 接口封装模块 (
api/api_endpoints.py
)
基于请求处理器,定义接口特定配置,如路径、默认头和体。从 YAML 拉取数据以实现动态设置。去除异常处理,仅执行调用并返回响应。import yaml from utils.request_handler import RequestHandler import logging class APIEndpoints: def __init__(self, base_url, data_file='data/test_data.yaml'): self.base_url = base_url self.request = RequestHandler() self.logger = logging.getLogger('APIEndpoints') with open(data_file, 'r') as f: self.config = yaml.safe_load(f) def call_interface(self, interface_name, params=None, data=None, headers=None): config = self.config['interfaces'].get(interface_name) url = self.base_url + config['url'] method = config['method'].lower() default_headers = config.get('headers', {}) headers = {**default_headers, **(headers or {})} if method == 'get': return self.request.get(url, params=params, headers=headers) elif method == 'post': return self.request.post(url, json=data, headers=headers) # 类似添加 put/delete...
关键字封装模块 (
keywords/keywords.py
)
将常见操作封装为可复用函数,利用接口模块。例如,“login” 结合数据准备和 API 调用。from api.api_endpoints import APIEndpoints import logging class Keywords: def __init__(self, base_url): self.api = APIEndpoints(base_url) self.logger = logging.getLogger('Keywords') def login(self, username, password): data = {'username': username, 'password': password} response = self.api.call_interface('login', data=data) self.logger.info("Login keyword executed") return response.json().get('token') def query_resource(self, resource_id): params = {'id': resource_id} response = self.api.call_interface('query', params=params) self.logger.info("Query keyword executed") return response.json() # 添加更多关键字如 create()、update()...
测试用例模块 (
tests/test_cases.py
)
使用 pytest 组织测试,Allure 装饰器用于报告。从 YAML 加载预期结果并断言响应。import pytest import allure import yaml from keywords.keywords import Keywords @allure.feature("Authentication") class TestAuth: @allure.story("User Login") @allure.title("Test successful login") def test_login_success(self, base_url): with open('data/test_data.yaml', 'r') as f: data = yaml.safe_load(f) keywords = Keywords(base_url) token = keywords.login(data['test_cases']['login']['username'], data['test_cases']['login']['password']) allure.attach(str(token), name="Response Token", attachment_type=allure.attachment_type.TEXT) assert token is not None, "Login failed" expected = data['expected']['login']['status'] # 断言响应匹配预期... # 更多测试类...
模块调用关系
流程:测试 (
test_cases.py
) 调用关键字 (keywords.py
),后者调用接口 (api_endpoints.py
),依赖于请求 (request_handler.py
)。图示(文本形式): 测试 → 关键字(可复用动作) → 接口(配置驱动调用) → 请求(底层 HTTP)。 这种链式确保抽象:底层请求变更不影响高层测试。
YAML 数据文件格式规范
YAML 文件结构化以便阅读。示例 data/test_data.yaml
:
interfaces:
login:
url: /auth/login
method: POST
headers:
Content-Type: application/json
query:
url: /resources
method: GET
test_cases:
login:
username: testuser
password: testpass
expected:
login:
status: success
token_present: true
字段:interfaces
(url、method、headers);test_cases
(参数/数据);expected
(断言结果)。此格式支持扩展,通过添加键值。
日志配置
使用 logging_config.py
配置模块特定级别:
import logging
def setup_logging():
logging.basicConfig(filename='logs/framework.log', level=logging.DEBUG)
logging.getLogger('RequestHandler').setLevel(logging.ERROR) # 请求模块更高阈值
# 配置其他 logger...
在 conftest.py
中调用。日志通过命名 logger 区分模块,例如 “RequestHandler: ERROR - Failed request”。
Allure 报告集成
在 conftest.py
中:
import allure
import logging
@pytest.hookimpl(tryfirst=True)
def pytest_runtest_makereport(item, call):
if call.when == 'call' and call.excinfo is not None:
allure.attach(str(call.excinfo.value), name="Error Log", attachment_type=allure.attachment_type.TEXT)
报告包括:状态、步骤(通过 @allure.step
)、响应(附加 JSON)、错误(栈)、日志(自定义处理器)。使用 allure generate allure-results -o allure-report
生成。
开发文档 (docs/framework_guide.md
)
此 Markdown 文件涵盖:
安装:虚拟环境设置、pip 安装。
添加接口:更新 YAML,扩展
APIEndpoints
。编写测试:使用 pytest 标记、Allure 装饰器。
扩展关键字:在
keywords.py
添加方法。故障排除:常见错误、日志检查。
最佳实践:参数化测试、通过 YAML 处理环境。
框架组件比较表
此框架坚固、可扩展,符合 API 测试行业标准。