pytest+requests框架写接口自动化对 post 和 get 方法请求 body的 处理

  • 使用python写接口自动化,Http请求方式有OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法,本次主要对比post和get方法,两者请求body格式有差异,了解了一下大概区别和处理方式,如果分析有问题欢迎大家指正,首先post和get请求所使用有所不同:
  • Http get 方法: 主要用于向指定的URL(URI)请求资源(资源文件或是数据均可), 可以带参数也可以不带参数, 带参数时,参数是明文传递,你可以在浏览器的地址栏中看到参数名及参数值,get安全性不高,所以常用于安全性要求低的场合, 比如登录后请求数据。
  • Http post方法:主要是向指定的URL(URI)提交数据, 通常用于表单发送,POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中,像注册、登录、提交表单都是用该方法实现的。
  • post请求content-type类型是:Content-Type:application/x-www-form-urlencoded对应的请求参数形式为Form Data:

  • Reqeusts支持以form表单形式发送post请求,只需要将请求的参数构造成一个字典,然后传给requests.post()的data参数即可。
@request(url = config.TALARIS_URL + '/head/team/config/change_team',method='post',data_type='form')
def test_head_change_team(self,team_id):
    """
    切换团队
    """
    body = {
        'team_id': team_id
    }

  • post请求content-type类型是:Content-Type:application/json对应的请求参数形式为request payload:

     

  • Reqeusts支持以request payload形式发送post请求,application/json格式的请求头是指用来告诉服务端post过去的消息主体是序列化后的 JSON 字符串。使用python写接口自动化定义接口时需要使用json.dumps()将dict类型的数据转成str,因为如果直接将dict类型的数据写入json文件中会发生报错

@request(url = config.STARGATE_URL + '/head_api/process',data_type='form',method='post')
def test_head_process(self, dealRemark, headApplyId, reassignedTakerId, status, teamId, trackingId):
    """
    申请异常流程
    :param dealRemark:
    :param headApplyId:
    :param reassignedTakerId:
    :param status:
    :param teamId:
    :param trackingId:
    :return:
    """

    params= {
        'dealRemark': dealRemark,
        'headApplyId': headApplyId,
        'reassignedTakerId': reassignedTakerId,
        'status': status,
        'teamId': teamId,
        'trackingId': trackingId
    }
    body = json.dumps(params)
  • get请求的时候对应的请求参数形式为Query String Parameters,我们的参数直接反映在url里面,形式为key1=value1&key2=value2形式;
    例如:https://*****/taker_order_count?team_id=100

     

  • 使用python写get请求,支持直接使用使用params关键字,以一个字典来传递这些参数,例如:

@request(url = config.TALARIS_URL + '/web/subgroup/update_status',method='get',data_type='form')
def test_group_status(self,groupId,status):
    """
    更新分组状态
    :param groupId:
    :param status:
    :return:
    """
    params = {
        'groupId': groupId,
        'status': status
    }
<think>我们被要求使用pytestrequests实现接口功能自动化测试。根据引用资料,我们可以总结出以下关键步骤思路: 1. 环境准备:安装Python,使用pip安装requestspytest库。 2. 对requests进行二次封装,以便统一处理请求、响应异常。 3. 使用Excel或其他数据文件来管理测试数据(数据驱动)。 4. 编测试用例,使用pytest管理测试用例(通常以test_*.py或*_test.py命名)。 5. 使用断言进行结果验证。 6. 生成测试报告(如Allure报告)日志记录。 具体实现步骤: 1. 封装requests请求 我们可以创建一个类或模块来封装常见的HTTP方法GET, POST, PUT, DELETE等),这样可以在发送请求时统一添加头信息、处理异常、记录日志等。 2. 准备测试数据 通常将测试数据放在外部文件(如Excel、JSON、YAML)中,然后通过数据驱动的方式读取。pytest支持通过`@pytest.mark.parametrize`装饰器实现参数化。 3. 编测试用例 测试用例函数应该以`test_`开头,这样pytest可以自动发现。在测试用例中,调用封装的请求方法发送请求,然后对响应进行断言。 4. 断言 使用Python的`assert`语句或pytest提供的断言方法进行结果验证。 5. 生成报告 可以使用Allure框架生成漂亮的测试报告。需要安装Allure并配置pytest使用Allure。 6. 日志记录 使用Python的logging模块记录测试过程中的信息,便于调试查看。 下面是一个简单的示例: **步骤1:封装requests** 创建一个文件`api_client.py`,内容如下: ```python import requests import logging class APIClient: def __init__(self, base_url): self.base_url = base_url self.session = requests.Session() def get(self, endpoint, params=None, headers=None): url = self.base_url + endpoint try: response = self.session.get(url, params=params, headers=headers) response.raise_for_status() # 如果响应状态不是200,将抛出异常 return response except requests.exceptions.RequestException as e: logging.error(f"GET请求失败: {e}") raise def post(self, endpoint, data=None, json=None, headers=None): url = self.base_url + endpoint try: response = self.session.post(url, data=data, json=json, headers=headers) response.raise_for_status() return response except requests.exceptions.RequestException as e: logging.error(f"POST请求失败: {e}") raise ``` **步骤2:编测试用例** 创建一个测试文件`test_example.py`,内容如下: ```python import pytest from api_client import APIClient # 假设我们的基础URL BASE_URL = "https://jsonplaceholder.typicode.com" # 创建客户端实例 @pytest.fixture(scope="module") def api_client(): return APIClient(BASE_URL) # 测试用例:获取帖子列表 def test_get_posts(api_client): response = api_client.get("/posts") assert response.status_code == 200 data = response.json() assert isinstance(data, list) assert len(data) > 0 # 测试用例:创建新帖子 @pytest.mark.parametrize("userId, title, body", [ (1, "test title", "test body") ]) def test_create_post(api_client, userId, title, body): json_data = { "userId": userId, "title": title, "body": body } response = api_client.post("/posts", json=json_data) assert response.status_code == 201 created_post = response.json() assert created_post['userId'] == userId assert created_post['title'] == title assert created_post['body'] == body ``` **步骤3:运行测试并生成报告** 首先安装Allure-pytest: ```bash pip install allure-pytest ``` 然后运行测试并生成Allure报告: ```bash pytest --alluredir=./allure-results ``` 最后,使用Allure命令生成HTML报告: ```bash allure serve ./allure-results ``` 这样,我们就完成了一个简单的接口自动化测试框架的搭建。 **注意事项**: - 测试数据管理:更复杂的数据驱动可以通过读取外部文件(如Excel)来实现,然后使用`pytest.mark.parametrize`参数化。 - 配置管理:可以将基础URL等配置信息放在配置文件中(如config.ini或config.json),然后在代码中读取。 - 日志配置:可以配置日志级别、格式输出位置。 以上是一个基本的实现思路,根据实际项目需求可以进一步扩展优化。 §§相关问题§§ 1. 如何将测试数据存储在Excel文件中并进行数据驱动测试? 2. 在接口自动化测试中如何处理登录状态的保持(如cookies或token)? 3. 如何使用Allure报告添加详细的测试步骤描述? 4. 如何对接口返回的数据进行复杂的验证(如使用JSONPath)? 5. 在接口测试中如何模拟第三方接口的响应?</think>### 如何使用 pytest requests 实现接口功能自动化测试 接口自动化测试的实现主要包含以下核心步骤,结合 pytest requests 的完整流程如下: --- #### 1. **环境准备** ```bash pip install requests pytest pytest-html allure-pytest ``` --- #### 2. **目录结构设计** ```markdown project/ ├── api/ # 接口封装层 │ └── user_api.py # 用户相关接口封装 ├── testcases/ # 测试用例层 │ └── test_user.py # 用户接口测试用例 ├── data/ # 测试数据层 │ └── user_data.yaml # 数据驱动文件 ├── utils/ # 工具层 │ ├── request_util.py # requests二次封装 │ └── assert_util.py # 断言工具 ├── conftest.py # pytest全局配置 └── reports/ # 测试报告目录 ``` --- #### 3. **核心实现步骤** ##### (1) 封装 requests 工具 (utils/request_util.py) ```python import requests import logging class RequestUtil: def __init__(self): self.session = requests.Session() self.base_url = "https://api.example.com" # 基础URL def send_request(self, method, endpoint, **kwargs): url = f"{self.base_url}{endpoint}" try: response = self.session.request(method, url, **kwargs) response.raise_for_status() logging.info(f"请求成功: {method} {url}") return response.json() except requests.exceptions.RequestException as e: logging.error(f"请求失败: {e}") raise ``` ##### (2) 封装断言工具 (utils/assert_util.py) ```python 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}" def assert_json_value(response, key, expected_value): json_data = response.json() assert json_data[key] == expected_value, \ f"字段{key}值不匹配, 预期:{expected_value}, 实际:{json_data[key]}" ``` ##### (3) 接口业务封装 (api/user_api.py) ```python from utils.request_util import RequestUtil class UserAPI: def __init__(self): self.request = RequestUtil() def login(self, username, password): """登录接口""" endpoint = "/login" payload = {"username": username, "password": password} return self.request.send_request("POST", endpoint, json=payload) def get_user_info(self, user_id): """获取用户信息""" endpoint = f"/users/{user_id}" return self.request.send_request("GET", endpoint) ``` ##### (4) 编测试用例 (testcases/test_user.py) ```python import pytest from api.user_api import UserAPI from utils.assert_util import * @pytest.fixture(scope="module") def user_api(): return UserAPI() # 参数化测试数据 @pytest.mark.parametrize("username, password", [ ("admin", "admin123"), ("testuser", "test456") ]) def test_login_success(user_api, username, password): """测试登录成功场景""" response = user_api.login(username, password) assert_status_code(response, 200) assert_json_key(response, "token") def test_get_user_info(user_api): """测试获取用户信息""" response = user_api.get_user_info(1) assert_json_value(response, "username", "admin") assert_json_value(response, "email", "admin@example.com") ``` ##### (5) 全局配置 (conftest.py) ```python import pytest import logging @pytest.fixture(autouse=True) def setup_logging(): logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 失败用例重试机制 def pytest_addoption(parser): parser.addoption("--retries", action="store", default=1, type=int) @pytest.hookimpl(tryfirst=True) def pytest_runtest_makereport(item, call): if "retry" in item.keywords: if call.excinfo is not None: item.add_marker(pytest.mark.xfail(reason="Flaky test")) ``` --- #### 4. **执行测试与报告生成** ```bash # 执行测试并生成HTML报告 pytest --html=reports/report.html # 使用Allure生成高级报告 pytest --alluredir=reports/allure-results allure serve reports/allure-results ``` --- #### 5. **关键实践技巧 1. **数据驱动** 使用 YAML/JSON 管理测试数据: ```yaml # data/user_data.yaml login_cases: - case: 正确密码 username: "admin" password: "admin123" expected_code: 200 - case: 错误密码 username: "testuser" password: "wrong" expected_code: 401 ``` 2. **关联接口处理** 通过 session 保持登录状态: ```python @pytest.fixture def auth_session(user_api): user_api.login("admin", "admin123") return user_api.request.session # 返回已认证的session ``` 3. **自动化断言扩展** 使用 JSONSchema 验证响应结构: ```python from jsonschema import validate schema = { "type": "object", "properties": { "id": {"type": "number"}, "username": {"type": "string"}, "email": {"type": "string", "format": "email"} }, "required": ["id", "username"] } def test_user_schema(user_api): response = user_api.get_user_info(1) validate(instance=response.json(), schema=schema) ``` --- ### 典型问题解决方案 | 问题类型 | 解决方案 | |------------------|--------------------------------------------------------------------------| | 接口依赖 | 使用 `pytest.fixture` 管理前置条件 | | 测试数据管理 | YAML/Excel + `@pytest.mark.parametrize` 实现数据驱动 | | 异步接口验证 | 添加轮询机制(如使用 `tenacity` 库) | | 敏感数据处理 | 使用 `python-dotenv` 管理环境变量 | | 多环境切换 | 通过命令行参数切换 base_url | | 文件上传/下载 | 使用 requests 的 `files` 参数流式下载 | 通过以上实现,可构建可维护的接口自动化测试框架,平均提升测试效率 60% 以上[^5]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值