api-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API Testing

API测试

Expert knowledge for testing HTTP APIs with Supertest (TypeScript/JavaScript) and httpx/pytest (Python).
具备使用Supertest(TypeScript/JavaScript)和httpx/pytest(Python)进行HTTP API测试的专业知识。

Core Expertise

核心能力

API Testing Capabilities
  • Request testing: Headers, query params, request bodies
  • Response validation: Status codes, headers, JSON schemas
  • Authentication: Bearer tokens, cookies, OAuth flows
  • Error handling: 4xx/5xx responses, validation errors
  • Integration: Database state, external services
  • Performance: Response times, load testing basics
API测试能力
  • 请求测试:请求头、查询参数、请求体
  • 响应验证:状态码、响应头、JSON Schema
  • 身份认证:Bearer令牌、Cookie、OAuth流程
  • 错误处理:4xx/5xx响应、验证错误
  • 集成测试:数据库状态、外部服务
  • 性能测试:响应时间、基础负载测试

TypeScript/JavaScript (Supertest)

TypeScript/JavaScript(Supertest)

Installation

安装

bash
undefined
bash
undefined

Using Bun

Using Bun

bun add -d supertest @types/supertest
bun add -d supertest @types/supertest

Using npm

Using npm

npm install -D supertest @types/supertest
undefined
npm install -D supertest @types/supertest
undefined

Basic Setup with Express

与Express的基础配置

typescript
// app.ts
import express from 'express'

export const app = express()
app.use(express.json())

app.get('/api/health', (req, res) => {
  res.json({ status: 'ok' })
})

app.post('/api/users', (req, res) => {
  const { name, email } = req.body
  if (!name || !email) {
    return res.status(400).json({ error: 'Missing required fields' })
  }
  res.status(201).json({ id: 1, name, email })
})
typescript
// app.test.ts
import { describe, it, expect } from 'vitest'
import request from 'supertest'
import { app } from './app'

describe('API Tests', () => {
  it('returns health status', async () => {
    const response = await request(app)
      .get('/api/health')
      .expect(200)

    expect(response.body).toEqual({ status: 'ok' })
  })

  it('creates a user', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'John Doe', email: 'john@example.com' })
      .expect(201)

    expect(response.body).toMatchObject({
      id: expect.any(Number),
      name: 'John Doe',
      email: 'john@example.com',
    })
  })

  it('validates required fields', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'John Doe' })
      .expect(400)

    expect(response.body.error).toBeDefined()
  })
})
typescript
// app.ts
import express from 'express'

export const app = express()
app.use(express.json())

app.get('/api/health', (req, res) => {
  res.json({ status: 'ok' })
})

app.post('/api/users', (req, res) => {
  const { name, email } = req.body
  if (!name || !email) {
    return res.status(400).json({ error: 'Missing required fields' })
  }
  res.status(201).json({ id: 1, name, email })
})
typescript
// app.test.ts
import { describe, it, expect } from 'vitest'
import request from 'supertest'
import { app } from './app'

describe('API Tests', () => {
  it('returns health status', async () => {
    const response = await request(app)
      .get('/api/health')
      .expect(200)

    expect(response.body).toEqual({ status: 'ok' })
  })

  it('creates a user', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'John Doe', email: 'john@example.com' })
      .expect(201)

    expect(response.body).toMatchObject({
      id: expect.any(Number),
      name: 'John Doe',
      email: 'john@example.com',
    })
  })

  it('validates required fields', async () => {
    const response = await request(app)
      .post('/api/users')
      .send({ name: 'John Doe' })
      .expect(400)

    expect(response.body.error).toBeDefined()
  })
})

Request Methods

请求方法

typescript
import request from 'supertest'
import { app } from './app'

// GET request
await request(app).get('/api/users').expect(200)

// POST request with body
await request(app).post('/api/users')
  .send({ name: 'John', email: 'john@example.com' }).expect(201)

// PUT request
await request(app).put('/api/users/1')
  .send({ name: 'Jane' }).expect(200)

// PATCH request
await request(app).patch('/api/users/1')
  .send({ email: 'jane@example.com' }).expect(200)

// DELETE request
await request(app).delete('/api/users/1').expect(204)
typescript
import request from 'supertest'
import { app } from './app'

// GET request
await request(app).get('/api/users').expect(200)

// POST request with body
await request(app).post('/api/users')
  .send({ name: 'John', email: 'john@example.com' }).expect(201)

// PUT request
await request(app).put('/api/users/1')
  .send({ name: 'Jane' }).expect(200)

// PATCH request
await request(app).patch('/api/users/1')
  .send({ email: 'jane@example.com' }).expect(200)

// DELETE request
await request(app).delete('/api/users/1').expect(204)

Headers and Query Parameters

请求头与查询参数

typescript
// Set headers
await request(app)
  .get('/api/protected')
  .set('Authorization', 'Bearer token123')
  .set('Content-Type', 'application/json')
  .expect(200)

// Query parameters
await request(app)
  .get('/api/users')
  .query({ page: 1, limit: 10 })
  .expect(200)
typescript
// Set headers
await request(app)
  .get('/api/protected')
  .set('Authorization', 'Bearer token123')
  .set('Content-Type', 'application/json')
  .expect(200)

// Query parameters
await request(app)
  .get('/api/users')
  .query({ page: 1, limit: 10 })
  .expect(200)

Response Assertions

响应断言

typescript
describe('Response validation', () => {
  it('validates status code', async () => {
    await request(app).get('/api/users').expect(200)
  })

  it('validates headers', async () => {
    await request(app).get('/api/users')
      .expect('Content-Type', /json/).expect(200)
  })

  it('validates response body', async () => {
    const response = await request(app).get('/api/users/1').expect(200)
    expect(response.body).toEqual({
      id: 1,
      name: 'John Doe',
      email: 'john@example.com',
      createdAt: expect.any(String),
    })
  })

  it('validates array responses', async () => {
    const response = await request(app).get('/api/users').expect(200)
    expect(response.body).toBeInstanceOf(Array)
    expect(response.body).toHaveLength(5)
    expect(response.body[0]).toHaveProperty('id')
  })
})
typescript
describe('Response validation', () => {
  it('validates status code', async () => {
    await request(app).get('/api/users').expect(200)
  })

  it('validates headers', async () => {
    await request(app).get('/api/users')
      .expect('Content-Type', /json/).expect(200)
  })

  it('validates response body', async () => {
    const response = await request(app).get('/api/users/1').expect(200)
    expect(response.body).toEqual({
      id: 1,
      name: 'John Doe',
      email: 'john@example.com',
      createdAt: expect.any(String),
    })
  })

  it('validates array responses', async () => {
    const response = await request(app).get('/api/users').expect(200)
    expect(response.body).toBeInstanceOf(Array)
    expect(response.body).toHaveLength(5)
    expect(response.body[0]).toHaveProperty('id')
  })
})

Python (httpx + pytest)

Python(httpx + pytest)

Installation

安装

bash
undefined
bash
undefined

Using uv

Using uv

uv add --dev httpx pytest-asyncio
uv add --dev httpx pytest-asyncio

Using pip

Using pip

pip install httpx pytest-asyncio
undefined
pip install httpx pytest-asyncio
undefined

Basic Setup with FastAPI

与FastAPI的基础配置

python
undefined
python
undefined

main.py

main.py

from fastapi import FastAPI, HTTPException from pydantic import BaseModel
app = FastAPI()
class User(BaseModel): name: str email: str
@app.get("/api/health") def health_check(): return {"status": "ok"}
@app.post("/api/users", status_code=201) def create_user(user: User): return {"id": 1, "name": user.name, "email": user.email}
@app.get("/api/users/{user_id}") def get_user(user_id: int): if user_id == 999: raise HTTPException(status_code=404, detail="User not found") return {"id": user_id, "name": "John Doe", "email": "john@example.com"}

```python
from fastapi import FastAPI, HTTPException from pydantic import BaseModel
app = FastAPI()
class User(BaseModel): name: str email: str
@app.get("/api/health") def health_check(): return {"status": "ok"}
@app.post("/api/users", status_code=201) def create_user(user: User): return {"id": 1, "name": user.name, "email": user.email}
@app.get("/api/users/{user_id}") def get_user(user_id: int): if user_id == 999: raise HTTPException(status_code=404, detail="User not found") return {"id": user_id, "name": "John Doe", "email": "john@example.com"}

```python

test_main.py

test_main.py

from fastapi.testclient import TestClient from main import app
client = TestClient(app)
def test_health_check(): response = client.get("/api/health") assert response.status_code == 200 assert response.json() == {"status": "ok"}
def test_create_user(): response = client.post( "/api/users", json={"name": "John Doe", "email": "john@example.com"} ) assert response.status_code == 201 data = response.json() assert data["name"] == "John Doe" assert "id" in data
def test_validation_error(): response = client.post("/api/users", json={"name": "John"}) assert response.status_code == 422 # FastAPI validation error
def test_not_found(): response = client.get("/api/users/999") assert response.status_code == 404

For detailed examples including authentication testing, file uploads, cookie testing, database integration, schema validation, GraphQL testing, performance testing, best practices, and troubleshooting, see [REFERENCE.md](REFERENCE.md).
from fastapi.testclient import TestClient from main import app
client = TestClient(app)
def test_health_check(): response = client.get("/api/health") assert response.status_code == 200 assert response.json() == {"status": "ok"}
def test_create_user(): response = client.post( "/api/users", json={"name": "John Doe", "email": "john@example.com"} ) assert response.status_code == 201 data = response.json() assert data["name"] == "John Doe" assert "id" in data
def test_validation_error(): response = client.post("/api/users", json={"name": "John"}) assert response.status_code == 422 # FastAPI validation error
def test_not_found(): response = client.get("/api/users/999") assert response.status_code == 404

如需包含身份认证测试、文件上传、Cookie测试、数据库集成、Schema验证、GraphQL测试、性能测试、最佳实践以及故障排查的详细示例,请查看[REFERENCE.md](REFERENCE.md)。

Agentic Optimizations

智能优化命令

ContextCommand
Quick test (Bun)
bun test --dots --bail=1 api
Quick test (pytest)
pytest -x --tb=short tests/api/
Run single test file
bun test --dots path/to/test.ts
Verbose on failure
bun test --bail=1 api
场景命令
快速测试(Bun)
bun test --dots --bail=1 api
快速测试(pytest)
pytest -x --tb=short tests/api/
运行单个测试文件
bun test --dots path/to/test.ts
失败时显示详细信息
bun test --bail=1 api

See Also

相关链接

  • vitest-testing
    - Unit testing framework
  • python-testing
    - Python pytest patterns
  • playwright-testing
    - E2E API testing
  • test-quality-analysis
    - Test quality patterns
  • vitest-testing
    - 单元测试框架
  • python-testing
    - Python pytest测试模式
  • playwright-testing
    - 端到端API测试
  • test-quality-analysis
    - 测试质量分析模式

References

参考资料