API测试示例

备注

本文API测试 特指HTTP API 测试

场景分析

HTTP是一个无状态协议,其通讯过程可简要描述为:发送请求、回复响应,所以,API测试步有不同的类型需要处理:

  • 构造请求

  • 断言响应

备注

在复杂的项目场景下,可能包含更多的步骤类型,例如接口mock、变量提取、延迟请求等

其中请求在前响应在后,这就需要钩子在处理步骤时注意顺序。

此外,一个用例中可能需要多次调用不同的接口,而后仅进行一次断言,这就需要钩子在处理步骤时放松约束。

安装依赖

pytest自身无法发送HTTP请求,也无法断言响应,需要安装第三方依赖

pip install requests responses-validator

其中:

  • requests :用来发送HTTP请求

  • responses-validator :用来断言HTTP响应

如果还需要其他步骤类型,安装对应的依赖即可。

设计用例

根据分析结论和依赖的具体用法,设计yaml版API测试用例如下:

name: 访问百度首页
steps:
  - request: # 步骤 1:发送请求
      method: get
      url: https://www.baidu.com

  - response: # 步骤 2:断言响应(成功)
      status_code: 200
      text: "*baidu*"

  - response: # 步骤 3:另一个断言(失败)
      status_code: 404

在这个用例中,进行了一次HTTP请求,并对结果进行2次断言, 其中一次断言成功,第二次断言失败,使用例整体的结果为:测试失败。

实现钩子

# conftest.py

from requests import request
from responses_validator import validator

from pytest_yaml import YamlItem


def pytest_yaml_run_step(item: YamlItem):
    step = item.current_step  # 从参数值中取出字典格式的测试步骤

    step_type = list(step.keys())[0]  # 从字典的key即为类型
    step_data = list(step.values())[0]  # 从字典的value即为步骤内容

    match step_type:  # 根据不同的步骤类型,匹配不同的测试动作
        case 'request':
            # 发送请求,并将响应保存到item中,以便后续hook进行处理
            item.resp = request(**step_data)
            print(f'请求成功!{step_data["method"]} {step_data["url"]}')

        case 'response':

            validator(item.resp, **step_data)
            print('断言成功!')

    return True

执行结果如下:

(.venv) C:\demo\pytest-yaml-demo>pytest
=========================== test session starts ============================
platform win32 -- Python 3.12.0, pytest-8.3.4, pluggy-1.5.0
rootdir: C:\demo\pytest-yaml-demo
configfile: pytest.ini
plugins: yaml-1.1.0
collected 1 item

test_api.yaml F                                               [100%]

================================= FAILURES =================================
__________________________________ 访问百度首页 __________________________________

:
Step no: 2
Step Content:
--------------------
response:
  status_code: 404
--------------------

src\\responses_validator\\__init__.py:49: ResponseAssertionError
{'status_code': "status_code is 200 and does not match the pattern '404'."}
--------------------------- Captured stdout call ---------------------------
测试步骤:0, 步骤类型: request, 步骤内容: {'method': 'get', 'url': 'https://www.baidu.com'} ...请求成功!
测试步骤:1, 步骤类型: response, 步骤内容: {'status_code': 200, 'text': '*baidu*'} ...断言成功!
测试步骤:2, 步骤类型: response, 步骤内容: {'status_code': 404} ...
========================= short test summary info ==========================
FAILED test_api.yaml::访问百度首页
============================ 1 failed in 0.15s =============================

从结果来看,请求接口和第一次断言都成功了,第二次断言失败了。

具体原因是: status_code is 200 and does not match the pattern '404' (状态码是200,和预期结果404不匹配)

小结

和此前的数学运算相比,接口测试更加添加真实的业务需求。 在真实的业务需求中,往往需要对口的第三方库进行配合,还熟悉业务特征,了解业务步骤。 这些最终都会反应在yaml用例文件和hook钩子函数中。

pytest-yaml-sanmu 并不会代替你理解业务特征,也不会贸然提供一个解决方案。而是帮助你将自己的想法和理解进行落地。