API test suite builder
Use when the user asks to generate API tests, create integration test suites, test REST endpoints, or build contract tests.
How to use it
Claude Code
- Run the line below. It pulls the whole folder into
~/.claude/skills/api-test-suite-builder, including the files SKILL.md points to. - Describe your job in plain words. Claude Code follows the skill from there.
npx degit alirezarezvani/claude-skills/engineering/skills/api-test-suite-builder#main ~/.claude/skills/api-test-suite-builderFor one project only, change the path to .claude/skills/api-test-suite-builder. This skill also uses Next.js, route.ts, route.js — copying SKILL.md alone won't be enough. See the folder on GitHub.
Claude (web or desktop app)
- On this page open ⋯ → Download .md.
- Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
- Pick the file and Save. Claude shows the name and description and runs a security scan.
- Check the skill is switched on.
- Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
- ChatGPT: make a Project and paste it into Instructions.
- Neither? Paste it at the top of a new chat — it works for that chat.
Not working?
- Check which app you pasted it into — the steps above name the right one.
- Some skills need the paid tier of Claude or ChatGPT.
Paste into Claude, ChatGPT or Cursor.
Source of API test suite builder
Show the full text178 lines
| name | description |
|---|---|
| api-test-suite-builder | Use when the user asks to generate API tests, create integration test suites, test REST endpoints, or build contract tests. |
API Test Suite Builder
Tier: POWERFUL Category: Engineering Domain: Testing / API Quality
Overview
Scans API route definitions across frameworks (Next.js App Router, Express, FastAPI, Django REST) and auto-generates comprehensive test suites covering auth, input validation, error codes, pagination, file uploads, and rate limiting. Outputs ready-to-run test files for Vitest+Supertest (Node) or Pytest+httpx (Python).
Core Capabilities
- Route detection — scan source files to extract all API endpoints
- Auth coverage — valid/invalid/expired tokens, missing auth header
- Input validation — missing fields, wrong types, boundary values, injection attempts
- Error code matrix — 400/401/403/404/422/500 for each route
- Pagination — first/last/empty/oversized pages
- File uploads — valid, oversized, wrong MIME type, empty
- Rate limiting — burst detection, per-user vs global limits
When to Use
- New API added — generate test scaffold before writing implementation (TDD)
- Legacy API with no tests — scan and generate baseline coverage
- API contract review — verify existing tests match current route definitions
- Pre-release regression check — ensure all routes have at least smoke tests
- Security audit prep — generate adversarial input tests
Route Detection
Next.js App Router
# Find all route handlers
find ./app/api -name "route.ts" -o -name "route.js" | sort
# Extract HTTP methods from each route file
grep -rn "export async function\|export function" app/api/**/route.ts | \
grep -oE "(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)" | sort -u
# Full route map
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 all router files
find ./src -name "*.ts" -o -name "*.js" | xargs grep -l "router\.\(get\|post\|put\|delete\|patch\)" 2>/dev/null
# Extract routes with line numbers
grep -rn "router\.\(get\|post\|put\|delete\|patch\)\|app\.\(get\|post\|put\|delete\|patch\)" \
src/ --include="*.ts" | grep -oE "(get|post|put|delete|patch)\(['\"][^'\"]*['\"]"
# Generate route map
grep -rn "router\.\|app\." src/ --include="*.ts" | \
grep -oE "\.(get|post|put|delete|patch)\(['\"][^'\"]+['\"]" | \
sed "s/\.\(.*\)('\(.*\)'/\U\1 \2/"
FastAPI
# Find all route decorators
grep -rn "@app\.\|@router\." . --include="*.py" | \
grep -E "@(app|router)\.(get|post|put|delete|patch)"
# Extract with path and function name
grep -rn "@\(app\|router\)\.\(get\|post\|put\|delete\|patch\)" . --include="*.py" | \
grep -oE "@(app|router)\.(get|post|put|delete|patch)\(['\"][^'\"]*['\"]"
Django REST Framework
# urlpatterns extraction
grep -rn "path\|re_path\|url(" . --include="*.py" | grep "urlpatterns" -A 50 | \
grep -E "path\(['\"]" | grep -oE "['\"][^'\"]+['\"]" | head -40
# ViewSet router registration
grep -rn "router\.register\|DefaultRouter\|SimpleRouter" . --include="*.py"
Test Generation Patterns
Auth Test Matrix
For every authenticated endpoint, generate:
| Test Case | Expected Status |
|---|---|
| No Authorization header | 401 |
| Invalid token format | 401 |
| Valid token, wrong user role | 403 |
| Expired JWT token | 401 |
| Valid token, correct role | 2xx |
| Token from deleted user | 401 |
Input Validation Matrix
For every POST/PUT/PATCH endpoint with a request body:
| Test Case | Expected Status |
|---|---|
Empty body {} |
400 or 422 |
| Missing required fields (one at a time) | 400 or 422 |
| Wrong type (string where int expected) | 400 or 422 |
| Boundary: value at min-1 | 400 or 422 |
| Boundary: value at min | 2xx |
| Boundary: value at max | 2xx |
| Boundary: value at max+1 | 400 or 422 |
| SQL injection in string field | 400 or 200 (sanitized) |
| XSS payload in string field | 400 or 200 (sanitized) |
| Null values for required fields | 400 or 422 |
Example Test Files
→ See references/example-test-files.md for details
Generating Tests from Route Scan
When given a codebase, follow this process:
- Scan routes using the detection commands above
- Read each route handler to understand:
- Expected request body schema
- Auth requirements (middleware, decorators)
- Return types and status codes
- Business rules (ownership, role checks)
- Generate test file per route group using the patterns above
- Name tests descriptively:
"returns 401 when token is expired"not"auth test 3" - Use factories/fixtures for test data — never hardcode IDs
- Assert response shape, not just status code
Common Pitfalls
- Testing only happy paths — 80% of bugs live in error paths; test those first
- Hardcoded test data IDs — use factories/fixtures; IDs change between environments
- Shared state between tests — always clean up in afterEach/afterAll
- Testing implementation, not behavior — test what the API returns, not how it does it
- Missing boundary tests — off-by-one errors are extremely common in pagination and limits
- Not testing token expiry — expired tokens behave differently from invalid ones
- Ignoring Content-Type — test that API rejects wrong content types (xml when json expected)
Best Practices
- One describe block per endpoint — keeps failures isolated and readable
- Seed minimal data — don't load the entire DB; create only what the test needs
- Use
beforeAllfor shared setup,afterAllfor cleanup — notbeforeEachfor expensive ops - Assert specific error messages/fields, not just status codes
- Test that sensitive fields (password, secret) are never in responses
- For auth tests, always test the "missing header" case separately from "invalid token"
- Add rate limit tests last — they can interfere with other test suites if run in parallel
| 1 | |
| 2 | name "api-test-suite-builder" |
| 3 | description "Use when the user asks to generate API tests, create integration test suites, test REST endpoints, or build contract tests." |
| 4 | |
| 5 | |
| 6 | # API Test Suite Builder |
| 7 | |
| 8 | **Tier:** POWERFUL |
| 9 | **Category:** Engineering |
| 10 | **Domain:** Testing / API Quality |
| 11 | |
| 12 | |
| 13 | |
| 14 | ## Overview |
| 15 | |
| 16 | Scans API route definitions across frameworks (Next.js App Router, Express, FastAPI, Django REST) and |
| 17 | auto-generates comprehensive test suites covering auth, input validation, error codes, pagination, file |
| 18 | uploads, and rate limiting. Outputs ready-to-run test files for Vitest+Supertest (Node) or Pytest+httpx |
| 19 | (Python). |
| 20 | |
| 21 | |
| 22 | |
| 23 | ## Core Capabilities |
| 24 | |
| 25 | **Route detection** — scan source files to extract all API endpoints |
| 26 | **Auth coverage** — valid/invalid/expired tokens, missing auth header |
| 27 | **Input validation** — missing fields, wrong types, boundary values, injection attempts |
| 28 | **Error code matrix** — 400/401/403/404/422/500 for each route |
| 29 | **Pagination** — first/last/empty/oversized pages |
| 30 | **File uploads** — valid, oversized, wrong MIME type, empty |
| 31 | **Rate limiting** — burst detection, per-user vs global limits |
| 32 | |
| 33 | |
| 34 | |
| 35 | ## When to Use |
| 36 | |
| 37 | New API added — generate test scaffold before writing implementation (TDD) |
| 38 | Legacy API with no tests — scan and generate baseline coverage |
| 39 | API contract review — verify existing tests match current route definitions |
| 40 | Pre-release regression check — ensure all routes have at least smoke tests |
| 41 | Security audit prep — generate adversarial input tests |
| 42 | |
| 43 | |
| 44 | |
| 45 | ## Route Detection |
| 46 | |
| 47 | ### Next.js App Router |
| 48 | |
| 49 | # Find all route handlers |
| 50 | find ./app/api -name "route.ts" -o -name "route.js" | sort |
| 51 | |
| 52 | # Extract HTTP methods from each route file |
| 53 | grep -rn "export async function\|export function" app/api/**/route.ts | \ |
| 54 | grep -oE "(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)" | sort -u |
| 55 | |
| 56 | # Full route map |
| 57 | find ./app/api -name "route.ts" | while read f; do |
| 58 | route=$(echo $f | sed 's|./app||' | sed 's|/route.ts||') |
| 59 | methods=$(grep -oE "export (async )?function (GET|POST|PUT|PATCH|DELETE)" "$f" | \ |
| 60 | grep -oE "(GET|POST|PUT|PATCH|DELETE)") |
| 61 | echo "$methods $route" |
| 62 | done |
| 63 | |
| 64 | |
| 65 | ### Express |
| 66 | |
| 67 | # Find all router files |
| 68 | find ./src -name "*.ts" -o -name "*.js" | xargs grep -l "router\.\(get\|post\|put\|delete\|patch\)" 2>/dev/null |
| 69 | |
| 70 | # Extract routes with line numbers |
| 71 | grep -rn "router\.\(get\|post\|put\|delete\|patch\)\|app\.\(get\|post\|put\|delete\|patch\)" \ |
| 72 | src/ --include="*.ts" | grep -oE "(get|post|put|delete|patch)\(['\"][^'\"]*['\"]" |
| 73 | |
| 74 | # Generate route map |
| 75 | grep -rn "router\.\|app\." src/ --include="*.ts" | \ |
| 76 | grep -oE "\.(get|post|put|delete|patch)\(['\"][^'\"]+['\"]" | \ |
| 77 | sed "s/\.\(.*\)('\(.*\)'/\U\1 \2/" |
| 78 | |
| 79 | |
| 80 | ### FastAPI |
| 81 | |
| 82 | # Find all route decorators |
| 83 | grep -rn "@app\.\|@router\." . --include="*.py" | \ |
| 84 | grep -E "@(app|router)\.(get|post|put|delete|patch)" |
| 85 | |
| 86 | # Extract with path and function name |
| 87 | grep -rn "@\(app\|router\)\.\(get\|post\|put\|delete\|patch\)" . --include="*.py" | \ |
| 88 | grep -oE "@(app|router)\.(get|post|put|delete|patch)\(['\"][^'\"]*['\"]" |
| 89 | |
| 90 | |
| 91 | ### Django REST Framework |
| 92 | |
| 93 | # urlpatterns extraction |
| 94 | grep -rn "path\|re_path\|url(" . --include="*.py" | grep "urlpatterns" -A 50 | \ |
| 95 | grep -E "path\(['\"]" | grep -oE "['\"][^'\"]+['\"]" | head -40 |
| 96 | |
| 97 | # ViewSet router registration |
| 98 | grep -rn "router\.register\|DefaultRouter\|SimpleRouter" . --include="*.py" |
| 99 | |
| 100 | |
| 101 | |
| 102 | |
| 103 | ## Test Generation Patterns |
| 104 | |
| 105 | ### Auth Test Matrix |
| 106 | |
| 107 | For every authenticated endpoint, generate: |
| 108 | |
| 109 | | Test Case | Expected Status | |
| 110 | |-----------|----------------| |
| 111 | | No Authorization header | 401 | |
| 112 | | Invalid token format | 401 | |
| 113 | | Valid token, wrong user role | 403 | |
| 114 | | Expired JWT token | 401 | |
| 115 | | Valid token, correct role | 2xx | |
| 116 | | Token from deleted user | 401 | |
| 117 | |
| 118 | ### Input Validation Matrix |
| 119 | |
| 120 | For every POST/PUT/PATCH endpoint with a request body: |
| 121 | |
| 122 | | Test Case | Expected Status | |
| 123 | |-----------|----------------| |
| 124 | | Empty body `{}` | 400 or 422 | |
| 125 | | Missing required fields (one at a time) | 400 or 422 | |
| 126 | | Wrong type (string where int expected) | 400 or 422 | |
| 127 | | Boundary: value at min-1 | 400 or 422 | |
| 128 | | Boundary: value at min | 2xx | |
| 129 | | Boundary: value at max | 2xx | |
| 130 | | Boundary: value at max+1 | 400 or 422 | |
| 131 | | SQL injection in string field | 400 or 200 (sanitized) | |
| 132 | | XSS payload in string field | 400 or 200 (sanitized) | |
| 133 | | Null values for required fields | 400 or 422 | |
| 134 | |
| 135 | |
| 136 | |
| 137 | ## Example Test Files |
| 138 | → See references/example-test-files.md for details |
| 139 | |
| 140 | ## Generating Tests from Route Scan |
| 141 | |
| 142 | When given a codebase, follow this process: |
| 143 | |
| 144 | **Scan routes** using the detection commands above |
| 145 | **Read each route handler** to understand: |
| 146 | Expected request body schema |
| 147 | Auth requirements (middleware, decorators) |
| 148 | Return types and status codes |
| 149 | Business rules (ownership, role checks) |
| 150 | **Generate test file** per route group using the patterns above |
| 151 | **Name tests descriptively**: `"returns 401 when token is expired"` not `"auth test 3"` |
| 152 | **Use factories/fixtures** for test data — never hardcode IDs |
| 153 | **Assert response shape**, not just status code |
| 154 | |
| 155 | |
| 156 | |
| 157 | ## Common Pitfalls |
| 158 | |
| 159 | **Testing only happy paths** — 80% of bugs live in error paths; test those first |
| 160 | **Hardcoded test data IDs** — use factories/fixtures; IDs change between environments |
| 161 | **Shared state between tests** — always clean up in afterEach/afterAll |
| 162 | **Testing implementation, not behavior** — test what the API returns, not how it does it |
| 163 | **Missing boundary tests** — off-by-one errors are extremely common in pagination and limits |
| 164 | **Not testing token expiry** — expired tokens behave differently from invalid ones |
| 165 | **Ignoring Content-Type** — test that API rejects wrong content types (xml when json expected) |
| 166 | |
| 167 | |
| 168 | |
| 169 | ## Best Practices |
| 170 | |
| 171 | One describe block per endpoint — keeps failures isolated and readable |
| 172 | Seed minimal data — don't load the entire DB; create only what the test needs |
| 173 | Use `beforeAll` for shared setup, `afterAll` for cleanup — not `beforeEach` for expensive ops |
| 174 | Assert specific error messages/fields, not just status codes |
| 175 | Test that sensitive fields (password, secret) are never in responses |
| 176 | For auth tests, always test the "missing header" case separately from "invalid token" |
| 177 | Add rate limit tests last — they can interfere with other test suites if run in parallel |
| 178 |
Discussion
Browse more free Claude skills or everything in Development.