🚀 API-SOS
API-SOS 是一个用于 API 测试的工具,它可以从 OpenAPI 规范生成测试用例,并支持记录和验证 API 响应。
📦 安装
pip install api-sos
🚀 快速开始
📚 作为 Python 库使用
API-SOS 既可以通过命令行使用,也可以作为库直接集成到你的代码中。作为库调用时,它不会主动 sys.exit(1),而是返回结果,你可以自行决定如何处理错误或失败。
✅ 基础示例:运行已生成的用例
import asyncio
from api_sos import has_failures, run_checks
async def main() -> None:
results = await run_checks(
"output.yaml",
concurrent=5,
endpoint="http://localhost:8000",
variables="vars.yaml",
interactive=False,
verbose=True,
)
if has_failures(results):
# 这里由你决定如何处理失败,例如抛出异常或返回错误码
raise RuntimeError("API checks failed")
asyncio.run(main())
✅ 生成用例并写入文件
import asyncio
from api_sos import generate_checks
async def main() -> None:
await generate_checks(
"openapi.yaml",
"output.yaml",
endpoint="http://localhost:8000",
concurrent=3,
headers="headers.yaml",
headers_variables="vars.yaml",
no_record=False,
no_example=False,
verbose=True,
)
asyncio.run(main())
🔍 直接使用底层运行函数
如果你想完全掌控运行过程(比如批量处理多个 Input),可以直接调用 api_sos.run:
import asyncio
from api_sos import Input, run
async def main() -> None:
input_ = Input.load("output.yaml")
results = await run(input_, concurrent=2, variables={"token": "xxx"})
# results 是 CheckResult 或 Exception 的列表
asyncio.run(main())
🎯 生成测试用例
从 OpenAPI 规范生成测试用例:
# 指定端点并记录响应
api-sos generate openapi.yaml output.yaml --endpoint http://localhost:8000
# 使用并发请求记录响应
api-sos generate openapi.yaml output.yaml --endpoint http://localhost:8000 --concurrent 5
# 使用自定义请求头
api-sos generate openapi.yaml output.yaml --headers headers.yaml --endpoint http://localhost:8000
# 使用带模板变量的请求头(secretes场景)
api-sos generate openapi.yaml output.yaml --headers headers.yaml --headers-variables vars.yaml --endpoint http://localhost:8000
# 跳过响应记录
api-sos generate openapi.yaml output.yaml --no-record
# 跳过从示例生成检查
api-sos generate openapi.yaml output.yaml --no-example --endpoint http://localhost:8000
▶️ 运行测试
运行生成的测试用例:
# 基本用法
api-sos run output.yaml
# 使用并发执行
api-sos run output.yaml --concurrent 5
# 指定端点
api-sos run output.yaml --endpoint http://localhost:8000
# 使用变量替换
api-sos run output.yaml --variables vars.yaml
# 交互式编辑
api-sos run output.yaml --interactive
🔄 交互式编辑模式
当使用--interactive或-i参数运行测试时,如果检查结果与预期不符(存在差异),系统会自动打开编辑器让你修改断言:
# 启用交互式编辑模式
api-sos run output.yaml -i
# 使用自定义编辑器(通过环境变量设置)
EDITOR=vim api-sos run output.yaml -i
交互式编辑工作流程
-
当检测到断言与实际结果不匹配时,系统会打开你的编辑器
-
编辑器中会显示以下内容:
assert: 当前的断言内容,你可以修改这部分actual: 实际响应内容(仅供参考,保存时会被丢弃)name: 检查项名称(仅供参考,保存时会被丢弃)- 使用说明
-
你可以:
- 从
actual部分复制值到assert部分 - 修改断言中的特定字段
- 使用Jinja2模板表达式创建动态断言,如
{{ actual|is_type('int') }}
- 从
-
保存并退出编辑器后,修改将自动应用到原始文件中
这种交互式方式非常适合初始测试开发和调试过程。
📝 配置文件示例
所有配置的文件名可以是任意名称,请通过命令的参数进行传递
🔑 请求头配置 (headers.yaml) 在调用generate时,这部分请求头会自动被插入到生成的结构中
Authorization: Bearer {{token}}
Content-Type: application/json
X-Custom-Header: xxx
🔄 变量配置 (vars.yaml)
token: "your-token-here"
custom_value: "test"
✅ 测试用例配置 (output.yaml)
version: "1.0.0"
endpoint: "http://localhost:8000"
checks:
- name: "Get User"
pathname: "/api/users/1"
method: "GET"
# 可选:用于在 diff 结果中标记标签
tags: ["user", "smoke"]
headers:
Authorization: "Bearer {{token}}"
assert_:
http_status: 200
content:
id: 1
name: "John Doe"
✨ 功能特性
- 从 OpenAPI 规范自动生成测试用例
- 支持记录和验证 API 响应
- 支持并发请求
- 支持请求头模板变量
- 支持变量替换
- 支持交互式编辑
- 支持自定义端点
- 支持多种 HTTP 方法(GET, POST, PUT, DELETE 等)
- 灵活的响应断言系统
- 支持 Jinja2 模板表达式
- 内置丰富的断言过滤器
- 支持代理和认证
- 支持超时配置
🔧 高级用法
🎯 断言系统
🎨 支持的过滤器
matches(pattern): 正则表达式匹配contains(substr): 包含子字符串gt(other): 大于lt(other): 小于gte(other): 大于等于lte(other): 小于等于ne(other): 不等于is_numeric(): 是否为数字is_date(): 是否为日期格式is_email(): 是否为邮箱格式length(): 获取长度starts_with(prefix): 是否以指定字符串开头ends_with(suffix): 是否以指定字符串结尾in_range(min_val, max_val): 是否在指定范围内is_empty(): 是否为空is_type(expected_type): 检查值是否为指定的 Python 类型(如 'str', 'int', 'float', 'list', 'dict' 等)
📊 上下文变量
在表达式中可以使用以下变量:
actual: 当前字段的实际值response: 整个响应对象status: HTTP 状态码headers: 响应头body: 响应体
📋 高级配置示例
🔄 使用变量
version: "1.0.0"
endpoint: "https://api.example.com"
variables:
min_age: 18
valid_status: ["active", "pending"]
checks:
- name: "创建用户"
pathname: "/users"
method: POST
payload:
value:
name: "test_user"
email: "test@example.com"
assert:
http_status: 201
content:
age: "{{ actual|gte(min_age) }}"
status: "{{ actual in valid_status }}"
🌐 代理设置
checks:
- name: "使用代理"
pathname: "/api"
method: GET
proxy: "http://proxy.example.com:8080"
proxy_auth:
login: "user"
password: "pass"
⏱️ 超时设置
checks:
- name: "设置超时"
pathname: "/api"
method: GET
timeout:
total: 30
connect: 10
sock_read: 20
🎯 复杂断言示例
checks:
- name: "复杂断言示例"
pathname: "/orders"
method: POST
assert:
http_status: 201
content:
# 使用多个条件
is_valid: "{{ actual.amount >= 100 and actual.status in ['pending', 'processing'] }}"
# 使用过滤器链
is_valid_email: "{{ actual.email|is_email and actual.email|contains('@example.com') }}"
# 使用范围检查
is_valid_amount: "{{ actual.amount|in_range(100, 1000) }}"
# 使用正则表达式
is_valid_date: "{{ actual.created_at|matches('^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$') }}"
🛠️ 开发
# 安装开发依赖
uv sync --dev
# 运行代码格式化
black src
isort src
📄 许可证
MIT
Release files for api-sos 1.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| api_sos-1.4.0.tar.gz | 102.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| api_sos-1.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 126.1 kB
Release files / api_sos-1.4.0.tar.gz
| Download URL | api_sos-1.4.0.tar.gz |
|---|---|
| Size | 102.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
78b0e6ef70e218ef666d6b123293d4367893f8546f0832a3afd36febf65863c7
|
|
BLAKE2b-256 checksum How to use checksums |
039f60a4b0572514b16020a9fe626b4d8911e6180ad2ccef510308f73be9581a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.6
|
Release files / api_sos-1.4.0-py3-none-any.whl
| Download URL | api_sos-1.4.0-py3-none-any.whl |
|---|---|
| Size | 23.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
563322a1b725c4fba55abc7f38e4e1e2e4df7532384060c080470a524d1c2555
|
|
BLAKE2b-256 checksum How to use checksums |
cb07294103a38fcfaa3e028cae622bf1f1dd5da0aec602156f78ddf58e10b545
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.6
|