API Test Suite Builder
层级:POWERFUL 类别:Engineering 领域:Testing / API Quality
概述
扫描多种框架(Next.js App Router、Express、FastAPI、Django REST)中的 API 路由定义,自动生成全面的测试套件,覆盖鉴权、输入校验、错误码、分页、文件上传和速率限制。输出可直接运行的测试文件,用于 Vitest+Supertest(Node)或 Pytest+httpx(Python)。
核心能力
路由检测——扫描源文件以提取所有 API 端点
鉴权覆盖——有效/无效/过期令牌、缺失鉴权头
输入校验——缺失字段、错误类型、边界值、注入尝试
错误码矩阵——每个路由的 400/401/403/404/422/500
分页——首页/末页/空页/超大页
文件上传——有效、超大、错误 MIME 类型、空文件
速率限制——突发检测、按用户与全局限制
何时使用
新增 API 时——在编写实现前生成测试脚手架(TDD)
无测试的遗留 API——扫描并生成基线覆盖率
API 契约审查——验证现有测试是否与当前路由定义匹配
发布前回归检查——确保所有路由至少有冒烟测试
安全审计准备——生成对抗性输入测试
路由检测
Next.js App Router
查找所有路由处理器
find ./app/api -name "route.ts" -o -name "route.js" | sort
从每个路由文件提取 HTTP 方法
grep -rn "export async function|export function" app/api/**/route.ts |
grep -oE "(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)" | sort -u
完整路由映射
find ./app/api -name "route.ts" | while read f; do
route=$(echo $f | sed 's|./app||' | sed 's|/route.ts||')
methods=$(grep -oE "export (async )?function (GET|POST|PUT|PATCH|DELETE)" "$f" |
grep -oE "(GET|POST|PUT|PATCH|DELETE)")
echo "$methods $route"
done
Express
查找所有路由文件
find ./src -name ".ts" -o -name ".js" | xargs grep -l "router.(get|post|put|delete|patch)" 2>/dev/null
提取带行号的路由
grep -rn "router.(get|post|put|delete|patch)|app.(get|post|put|delete|patch)"
src/ --include=".ts" | grep -oE "(get|post|put|delete|patch)(['"][^'"]['"]"
生成路由映射
grep -rn "router.|app." src/ --include=".ts" |
grep -oE ".(get|post|put|delete|patch)(['"][^'"]+['"]" |
sed "s/.(.)('(.*)'/\U\1 \2/"
FastAPI
查找所有路由装饰器
grep -rn "@app.|@router." . --include="*.py" |
grep -E "@(app|router).(get|post|put|delete|patch)"
提取路径与函数名
grep -rn "@(app|router).(get|post|put|delete|patch)" . --include=".py" |
grep -oE "@(app|router).(get|post|put|delete|patch)(['"][^'"]['"]"
Django REST Framework
urlpatterns 提取
grep -rn "path|re_path|url(" . --include="*.py" | grep "urlpatterns" -A 50 |
grep -E "path(['"]" | grep -oE "['"][^'"]+['"]" | head -40
ViewSet 路由注册
grep -rn "router.register|DefaultRouter|SimpleRouter" . --include="*.py"
测试生成模式
鉴权测试矩阵
对每个需要鉴权的端点生成:
测试用例 | 预期状态 无 Authorization 头 | 401 无效令牌格式 | 401 有效令牌,错误用户角色 | 403 过期 JWT 令牌 | 401 有效令牌,正确角色 | 2xx 已删除用户的令牌 | 401
输入校验矩阵
对每个带请求体的 POST/PUT/PATCH 端点生成:
测试用例 | 预期状态 空 body {} | 400 或 422 缺失必填字段(逐个测试) | 400 或 422 类型错误(需要 int 却传 string) | 400 或 422 边界:值等于 min-1 | 400 或 422 边界:值等于 min | 2xx 边界:值等于 max | 2xx 边界:值等于 max+1 | 400 或 422 字符串字段 SQL 注入 | 400 或 200(已清洗) 字符串字段 XSS 载荷 | 400 或 200(已清洗) 必填字段传 null | 400 或 422
示例测试文件
→ 详见 references/example-test-files.md
从路由扫描生成测试
拿到代码库后,按以下流程操作:
- 使用上述检测命令扫描路由
- 阅读每个路由处理器,理解:
- 预期请求体 schema
- 鉴权要求(中间件、装饰器)
- 返回类型与状态码
- 业务规则(归属、角色检查)
- 按路由组使用上述模式生成测试文件
- 测试命名要具描述性:如 "returns 401 when token is expired",而不是 "auth test 3"
- 使用工厂/夹具生成测试数据——绝不硬编码 ID
- 断言响应结构,而不仅是状态码
常见陷阱
只测正常路径——80% 的 bug 藏在错误路径;应优先测试它们
硬编码测试数据 ID——使用工厂/夹具;ID 在不同环境会变化
测试间共享状态——始终在 afterEach/afterAll 中清理
测试实现而非行为——测试 API 返回什么,而非它如何实现
缺少边界测试——分页和限制中的差一错误极其常见
未测试令牌过期——过期令牌的行为与无效令牌不同
忽略 Content-Type——测试 API 拒绝错误内容类型(预期 json 却传 xml)
最佳实践
每个端点一个 describe 块——保持失败隔离且可读
最小化种子数据——不要加载整个数据库;只创建测试所需的数据
用 beforeAll 做共享设置,afterAll 做清理——不要用 beforeEach 做昂贵操作
断言具体错误消息/字段,而不仅状态码
测试敏感字段(password、secret)绝不出现在响应中
鉴权测试中,始终将"缺失头"与"无效令牌"分开测试
最后添加速率限制测试——若并行运行,它们可能干扰其他测试套件