Skip to content
Development
Skill

/api-testing

API 接口测试方法论,覆盖 RESTful/GraphQL 接口的功能、边界、安全、契约测试,参考 Supertest、REST Assured 等开源实践

From plugin
boss
54438 skills16 agents10 commands

Claude Code

$ npx -y skills add echoVic/boss-skill --skill api-testing --agent claude-code

SKILL.md

api-testing.SKILL.md
name: qa/api-testing
description: API 接口测试方法论,覆盖 RESTful/GraphQL 接口的功能、边界、安全、契约测试,参考 Supertest、REST Assured 等开源实践
version: 1.0.0
agent: qa
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
- shared/tech-stack-detection
  triggers:
- 需要编写或执行 API 接口测试时
- 需要验证 API 契约一致性时
- 需要覆盖接口边界和安全场景时
  metadata:
  internal: true

API 接口测试方法论

> 参考开源实践:Supertest、REST Assured、Postman/Newman、HTTPie、Testcontainers

适用场景

  • 后端 API 端点需要功能验证
  • 需要测试接口边界值、错误处理、权限控制
  • 需要验证 API 契约(请求/响应 schema 一致性)
  • 需要覆盖认证、授权、越权等安全场景
  • 需要测试完整业务流程的 API 链路

测试类型矩阵

| 测试类型 | 目的 | 工具 | 示例 | | ------------ | ----------------------- | ------------------------ | ------------------------------- | | **功能测试** | 验证接口正常行为 | Supertest / REST Assured | 创建资源返回 201 | | **边界测试** | 验证边界值和错误处理 | Supertest | 空 payload、超长字符串、非法 ID | | **安全测试** | 认证、授权、越权 | Supertest + auth header | 无 Token 访问受保护资源 | | **契约测试** | 请求/响应 schema 一致性 | Zod / JSON Schema | 响应字段类型校验 | | **流程测试** | 多接口业务链路 | Supertest 链式调用 | 注册→登录→下单→支付 |

1. RESTful API 测试

1.1 Node.js (Supertest + Jest/Vitest)

// tests/api/users.test.ts
import request from 'supertest';
import { app } from '../../src/app';

describe('User API', () => {
  describe('POST /api/users', () => {
    it('creates user with valid data', async () => {
      const res = await request(app)
        .post('/api/users')
        .send({ name: 'Alice', email: 'alice@example.com' })
        .expect(201)
        .expect('Content-Type', /json/);

      expect(res.body.success).toBe(true);
      expect(res.body.data).toMatchObject({ name: 'Alice', email: 'alice@example.com' });
      expect(res.body.data.id).toBeDefined();
    });

    it('rejects empty name with 400', async () => {
      const res = await request(app)
        .post('/api/users')
        .send({ name: '', email: 'test@example.com' })
        .expect(400);

      expect(res.body.error.code).toBe('VALIDATION_ERROR');
    });

    it('rejects duplicate email with 409', async () => {
      await request(app).post('/api/users').send({ name: 'A', email: 'dup@example.com' });
      const res = await request(app)
        .post('/api/users')
        .send({ name: 'B', email: 'dup@example.com' })
        .expect(409);

      expect(res.body.error.code).toBe('CONFLICT');
    });
  });
});

1.2 Python (pytest + requests)

# tests/api/test_users.py
import pytest
import requests

BASE_URL = "http://localhost:3000"

def test_create_user():
    res = requests.post(f"{BASE_URL}/api/users", json={"name": "Alice", "email": "alice@example.com"})
    assert res.status_code == 201
    assert res.json()["data"]["name"] == "Alice"

def test_create_user_empty_name():
    res = requests.post(f"{BASE_URL}/api/users", json={"name": "", "email": "test@example.com"})
    assert res.status_code == 400

1.3 Go (net/http/httptest)

// handlers/users_test.go
func TestCreateUser(t *testing.T) {
    app := setupTestApp()
    body := strings.NewReader(`{"name":"Alice","email":"alice@example.com"}`)
    req := httptest.NewRequest("POST", "/api/users", body)
    req.Header.Set("Content-Type", "application/json")
    w := httptest.NewRecorder()

    app.ServeHTTP(w, req)

    if w.Code != http.StatusCreated {
        t.Errorf("expected 201, got %d", w.Code)
    }
}

2. GraphQL API 测试

// tests/api/graphql.test.ts
import request from 'supertest';
import { app } from '../../src/app';

describe('GraphQL API', () => {
  it('queries user by id', async () => {
    const query = `
      query GetUser($id: ID!) {
        user(id: $id) { id name email }
      }
    `;
    const res = await request(app)
      .post('/graphql')
      .send({ query, variables: { id: '1' } })
      .expect(200);

    expect(res.body.data.user).toBeDefined();
    expect(res.body.errors).toBeUndefined();
  });

  it('mutates: create user', async () => {
    const mutation = `
      mutation CreateUser($input: CreateUserInput!) {
        createUser(input: $input) { id name }
      }
    `;
    const res = await request(app)
      .post('/graphql')
      .send({ mutation, variables: { input: { name: 'Bob', email: 'bob@example.com' } } })
      .expect(200);

    expect(res.body.data.createUser.id).toBeDefined();
  });
});

3. 认证与授权测试

3.1 Token 认证

describe('Protected endpoints', () => {
  let token: string;

  beforeAll(async () => {
    const res = await request(app)
      .post('/api/auth/login')
      .send({ email: 'admin@example.com', password: '<PASSWORD>' });
    token = res.body.data.token;
  });

  it('returns 401 without token', async () => {
    await request(app).get('/api/users/profile').expect(401);
  });

  it('returns 401 with invalid token', async () => {
    await request(app)
      .get('/api/users/profile')
      .set('Authorization', 'Bearer <INVALID_TOKEN>')
      .expect(401);
  });

  it('returns 200 with valid token', async () => {
    await request(app)
      .get('/api/users/profile')
      .set('Authorization', `Bearer ${token}`)
      .expect(200);
  });
});

3.2 权限/越权测试

describe('Authorization', () => {
  let adminToken: string;
  let userToken: string;

  beforeAll(async () => {
    adminToken = await login('admin@example.com', '<PASSWORD>');
    userToken = await login('user@example.com', '<PASSWORD>');
  });

  it('admin can delete any user', async () => {
    await request(app)
      .delete('/api/users/123')
      .set('Authorization', `Bearer ${adminToken}`)
      .expect(200);
  });

  it('regular user cannot delete others (403)', async () => {
    await request(app)
      .delete('/api/users/123')
      .set('Authorization', `Bearer ${userToken}`)
      .expect(403);
  });
});

4. 边界值与错误用例

4.1 输入边界

describe('Input boundaries', () =>
Read more
@echovic
Ships withboss

Languages / 语言 / 言語 / 언어 / Idiomas / Langues: English · 中文 · 日本語 · 한국어 · Español · Français · Português This project is part of the AtomGit G-Star Incubation Program.

54438 skills16 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
544
Star history of echoVic/boss-skill on GitHub, a chart by star-history.com

Other skills on boss.

brainstorming
Skill

brainstorming

你是 Boss 的前置环节。用户通常只会丢过来一句话——可能是"帮我做个 XX"或者"我想搞个 XX"。你的工作是把这句话**翻译成下游流水线能跑起来的需求**。

@echovic@echovicInstall Skill

More skills from other plugins.

brainstorming
Skill
Popular
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
accessibility
Skill
Popular
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc4d290k
@affaan-m@affaan-mInstall Skill
compiler-commit
Skill
Popular

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

reacttoday252k
@facebook@facebookInstall Skill

Questions about api-testing.

Which coding agents can use api-testing?
api-testing installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.