API 测试工具
测试、验证 API 接口并实现自动化。
适用场景
✅ 以下场景使用此 skill:
- 测试 REST/GraphQL API 端点
- 验证响应状态、响应头、响应体和模式
- 编写 pytest/requests API 测试脚本
- 生成 Postman/Insomnia 集合
- 串联多步骤 API 工作流(认证 → CRUD → 验证)
- "帮我测一下这个接口" / "写个接口自动化脚本"
❌ 以下场景不得使用此 skill:
- 浏览器/UI 测试 → 使用 Web 自动化工具
- 仅设计而不执行测试用例 → 使用
test-case-gen - 大规模负载测试 → 使用专用工具(JMeter、k6、locust)
快速 API 测试
单次请求(curl)
# GET
curl -s -w "\n%{http_code} %{time_total}s" \
-H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users/1" | jq .
# POST with JSON body
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name":"test","email":"test@example.com"}' \
"https://api.example.com/users" | jq .
# PUT / PATCH / DELETE similar pattern
响应验证清单
对于每个 API 响应,验证以下内容:
- [ ] 状态码:符合预期(200/201/400/401/403/404/500)
- [ ] 响应时间:在 SLA 范围内(例如 < 500ms)
- [ ] Content-Type:正确(application/json 等)
- [ ] 响应体结构:必需字段存在,类型正确
- [ ] 数据准确性:值符合预期业务逻辑
- [ ] 错误格式:错误响应遵循一致的模式
- [ ] 响应头:包含安全响应头(CORS、CSP 等)
自动化脚本生成
Python pytest + requests
用户要求进行自动化 API 测试时,生成以下结构:
"""API Test Suite - {module_name}
Generated by 虫探 🔍
"""
import pytest
import requests
BASE_URL = "https://api.example.com"
TOKEN = "" # Set via env or fixture
@pytest.fixture
def auth_headers():
return {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
class TestUserAPI:
"""User module API tests"""
def test_get_user_success(self, auth_headers):
"""TC001: Get user by valid ID"""
resp = requests.get(f"{BASE_URL}/users/1", headers=auth_headers)
assert resp.status_code == 200
data = resp.json()
assert "id" in data
assert "name" in data
assert data["id"] == 1
def test_get_user_not_found(self, auth_headers):
"""TC002: Get user by non-existent ID"""
resp = requests.get(f"{BASE_URL}/users/99999", headers=auth_headers)
assert resp.status_code == 404
def test_create_user_success(self, auth_headers):
"""TC003: Create user with valid data"""
payload = {"name": "Test User", "email": "test@example.com"}
resp = requests.post(f"{BASE_URL}/users", json=payload, headers=auth_headers)
assert resp.status_code == 201
data = resp.json()
assert data["name"] == payload["name"]
def test_create_user_missing_field(self, auth_headers):
"""TC004: Create user missing required field"""
payload = {"name": "Test User"} # missing email
resp = requests.post(f"{BASE_URL}/users", json=payload, headers=auth_headers)
assert resp.status_code in (400, 422)
保存到工作区并运行:
# Save script
# Run tests
cd ~/.openclaw/workspace && python3 -m pytest test_api.py -v --tb=short
多步骤工作流测试
对于复杂流程(登录 → 创建 → 验证 → 删除):
class TestUserWorkflow:
"""End-to-end user CRUD workflow"""
def test_full_crud_flow(self):
# Step 1: Login
resp = requests.post(f"{BASE_URL}/auth/login",
json={"username": "admin", "password": "pass"})
assert resp.status_code == 200
token = resp.json()["token"]
headers = {"Authorization": f"Bearer {token}"}
# Step 2: Create
user = requests.post(f"{BASE_URL}/users",
json={"name": "E2E Test", "email": "e2e@test.com"},
headers=headers)
assert user.status_code == 201
user_id = user.json()["id"]
# Step 3: Read & Verify
get_resp = requests.get(f"{BASE_URL}/users/{user_id}", headers=headers)
assert get_resp.status_code == 200
assert get_resp.json()["name"] == "E2E Test"
# Step 4: Update
update = requests.put(f"{BASE_URL}/users/{user_id}",
json={"name": "Updated"}, headers=headers)
assert update.status_code == 200
# Step 5: Delete
delete = requests.delete(f"{BASE_URL}/users/{user_id}", headers=headers)
assert delete.status_code in (200, 204)
# Step 6: Verify deleted
verify = requests.get(f"{BASE_URL}/users/{user_id}", headers=headers)
assert verify.status_code == 404
Postman 集合导出
生成 Postman v2.1 集合 JSON:
{
"info": {
"name": "API Test Collection",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
{"key": "base_url", "value": "https://api.example.com"},
{"key": "token", "value": ""}
],
"item": [
{
"name": "Auth",
"item": [
{
"name": "Login",
"request": {
"method": "POST",
"url": "{{base_url}}/auth/login",
"header": [{"key": "Content-Type", "value": "application/json"}],
"body": {"mode": "raw", "raw": "{\"username\":\"admin\",\"password\":\"pass\"}"}
}
}
]
}
]
}
常见测试场景
对于任何 API,始终考虑以下场景:
| 类别 | 测试点 | |----------|-------------| | 认证 | 无 token、token 过期、token 无效、角色错误 | | 输入 | 请求体为空、缺少字段、类型错误、值溢出 | | 边界 | 最大长度字符串、0/负数、未来/过去日期 | | 安全 | SQL 注入、输入中的 XSS、路径遍历、IDOR | | 并发 | 重复请求、竞态条件 | | 分页 | page=0、page=-1、极大的 page_size、超出最后一页 | | 幂等性 | 重复相同的 PUT/DELETE,检查一致性 |
JSON 模式验证
验证 API 响应结构时:
import jsonschema
user_schema = {
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": {"type": "integer", "minimum": 1},
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"created_at": {"type": "string", "format": "date-time"}
},
"additionalProperties": False
}
def test_user_response_schema(auth_headers):
resp = requests.get(f"{BASE_URL}/users/1", headers=auth_headers)
jsonschema.validate(resp.json(), user_schema)
快速性能检查
# Simple latency test (10 requests)
for i in $(seq 1 10); do
curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" \
-H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users"
done
# Concurrent requests (requires GNU parallel or xargs)
seq 1 50 | xargs -P 10 -I {} curl -s -o /dev/null -w "{}: %{http_code} %{time_total}s\n" \
"https://api.example.com/health"
环境管理
管理多环境配置,避免硬编码:
import os
ENV_CONFIG = {
"dev": {"base_url": "https://dev-api.example.com", "token_env": "DEV_TOKEN"},
"staging": {"base_url": "https://staging-api.example.com", "token_env": "STG_TOKEN"},
"prod": {"base_url": "https://api.example.com", "token_env": "PROD_TOKEN"},
}
@pytest.fixture
def env():
name = os.getenv("TEST_ENV", "dev")
cfg = ENV_CONFIG[name]
cfg["token"] = os.getenv(cfg["token_env"], "")
return cfg
使用以下命令运行:TEST_ENV=staging python3 -m pytest test_api.py -v