AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Devlab Srv Test Api

skill-seed-forge-harness-ai-kit-devlab-srv-test-api · by seed-forge

后端 API 测试专家技能。支持 Java(JUnit)/ Python(pytest)/ Node.js(supertest + jest)后端项目的接口测试、Mock 服务、测试数据管理。

No reviews yet
0 installs
25 views
0.0% view→install

Install

$ agentstack add skill-seed-forge-harness-ai-kit-devlab-srv-test-api

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-seed-forge-harness-ai-kit-devlab-srv-test-api)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Devlab Srv Test Api? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Service API 测试专家技能

专注后端微服务 API 的自动化测试能力。

支持 REST/GraphQL/OpenAPI 规范的接口测试,覆盖身份认证、数据一致性、链路追踪等核心场景。


触发条件

当用户提到以下关键词时触发此 Skill:

  • "API 测试" / "接口测试" / "interface testing"
  • "OpenAPI 测试" / "Swagger 测试"
  • "微服务集成测试" / "microservice integration test"
  • "REST API 验证" / "GraphQL schema test"
  • "认证授权测试" / "authn/authz testing"

技术栈依赖

核心 CLI

# Node.js 环境
npm install -D jest supertest supertest-fetch

# Python 环境(可选)
pip install pytest requests-mock

# Java 环境(可选)
mvn add dependency:rest-assured

辅助工具

# Mock Server(推荐)
npm install -D msw

# 数据生成
npm install -D faker @faker-js/faker

# Schema 验证
npm install -D ajv zod

功能范围

Phase 1: API Schema 分析与测试点提取

输入

  • OpenAPI/Swagger YAML 文档
  • (可选)现有 API 客户端代码
  • (可选)业务需求描述

输出

  • specs/api-endpoints.md — 接口清单与测试点
  • specs/data-contracts.md — 数据模型定义
  • specs/auth-scenarios.md — 认证授权场景
Step 1.1: OpenAPI 解析算法
interface OpenAPIAnalysis {
  endpoints: {
    method: 'GET' | 'POST' | 'PUT' | 'DELETE';
    path: string;
    operationId: string;
    summary: string;
    parameters: Parameter[];
    requestBody?: RequestBody;
    responses: Response[];
    security?: SecurityRequirement[];
  }[];
  
  schemas: {
    [key: string]: {
      type: 'object' | 'array' | 'string' | 'number' | 'boolean';
      properties?: Record;
      required?: string[];
    };
  };
  
  securitySchemes: {
    [key: string]: {
      type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
      scheme?: string;
      bearerFormat?: string;
    };
  };
}
Step 1.2: 测试用例生成规则

| 维度 | 测试类型 | 示例 | |------|---------|------| | HTTP Method | CRUD 覆盖 | GET/POST/PUT/DELETE | | Authentication | 权限验证 | 未登录/普通用户/管理员 | | Query Params | 分页过滤排序 | ?limit=10&offset=20 | | Path Params | 边界值验证 | /users/{invalid-id} | | Request Body | 必填字段验证 | 缺失 email/password | | Response Codes | 状态码断言 | 200/400/401/404/500 | | Data Integrity | 一致性校验 | POST after GET shows new record |

Step 1.3: 输出测试计划
# specs/api-endpoints.md

## POST /api/users - 创建用户

### 测试场景
1. ✅ 有效数据创建成功 (201)
2. ✅ 缺少必填字段返回 400
3. ✅ 邮箱格式错误返回 400
4. ✅ 密码强度不足返回 400
5. ✅ 重复邮箱返回 409
6. ✅ 未认证请求返回 401

### 请求示例
```json
{
  "email": "user@example.com",
  "password": "SecurePass123!",
  "name": "John Doe"
}

响应示例

{
  "id": "uuid-1234",
  "email": "user@example.com",
  "name": "John Doe",
  "status": "active",
  "createdAt": "2026-07-22T10:00:00Z"
}

---

### Phase 2: API 测试代码生成

**输入**:
- `specs/api-endpoints.md` 测试计划
- 基础测试配置模板

**输出**:
- `tests/api/users.spec.ts`
- `tests/api/auth.spec.ts`
- `tests/integration/*.spec.ts`

#### Step 2.1: 基础配置模板

```typescript
// tests/api/setup.ts
import { test as base, expect } from '@playwright/test';
import { faker } from '@faker-js/faker';

// ========================================
// Type Definitions
// ========================================

interface UserTestData {
  email: string;
  password: string;
  name: string;
}

interface APITestFixtures {
  apiRequest: (method: string, url: string, data?: any) => Promise;
  authHeader: () => Promise>;
  createUser: (overrides?: Partial) => Promise;
}

// ========================================
// Custom Fixtures
// ========================================

export const test = base.extend({
  apiRequest: async ({ request }, use) => {
    const apiRequest = async (method: string, url: string, data?: any) => {
      const response = await request[method.toLowerCase()](url, {
        data,
        headers: { 'Content-Type': 'application/json' }
      });
      
      return response;
    };
    
    await use(apiRequest);
  },
  
  authHeader: async ({ request }, use) => {
    const authHeader = async () => {
      // Login and get token
      const loginResponse = await request.post('/api/auth/login', {
        data: {
          email: process.env.TEST_ADMIN_EMAIL || 'admin@test.com',
          password: process.env.TEST_ADMIN_PASSWORD || 'Admin123!'
        }
      });
      
      const { token } = await loginResponse.json();
      return { Authorization: `Bearer ${token}` };
    };
    
    await use(authHeader);
  },
  
  createUser: async ({ request }, use) => {
    const createUser = async (overrides?: Partial) => {
      const userData = {
        email: faker.internet.email(),
        password: 'TestPass123!',
        name: faker.person.fullName(),
        ...overrides
      };
      
      const response = await request.post('/api/users', {
        data: userData,
        headers: { 'Content-Type': 'application/json' }
      });
      
      if (response.status() !== 201) {
        throw new Error(`Failed to create user: ${await response.text()}`);
      }
      
      return userData;
    };
    
    await use(createUser);
  }
});

export { expect };
Step 2.2: CRUD 测试套件
// tests/api/users.spec.ts
import { test, expect } from './setup';
import { faker } from '@faker-js/faker';

test.describe('POST /api/users', () => {
  
  // ========================================
  // Happy Path Tests
  // ========================================
  
  test('should create user with valid data', async ({ apiRequest, createUser }) => {
    const userData = await createUser();
    
    // Verify response structure
    const response = await apiRequest('GET', `/api/users/${userData.email}`);
    expect(response.status()).toBe(200);
    
    const user = await response.json();
    expect(user.email).toBe(userData.email);
    expect(user.name).toBe(userData.name);
    expect(user.status).toBe('active');
  });
  
  test('should return correct response headers', async ({ apiRequest, createUser }) => {
    const userData = await createUser();
    
    const response = await apiRequest('POST', '/api/users', userData);
    
    expect(response.headers()['content-type']).toContain('application/json');
    expect(response.headers()['location']).toContain('/api/users/');
  });
  
  // ========================================
  // Required Fields Validation
  // ========================================
  
  test('should reject request missing email', async ({ apiRequest }) => {
    const response = await apiRequest('POST', '/api/users', {
      name: 'Test User',
      password: 'Test123!'
    });
    
    expect(response.status()).toBe(400);
    
    const error = await response.json();
    expect(error.errors).toContainEqual(
      expect.objectContaining({ field: 'email' })
    );
  });
  
  test('should reject request missing password', async ({ apiRequest }) => {
    const response = await apiRequest('POST', '/api/users', {
      email: faker.internet.email(),
      name: 'Test User'
    });
    
    expect(response.status()).toBe(400);
  });
  
  // ========================================
  // Field Constraints Validation
  // ========================================
  
  test('should reject email with invalid format', async ({ apiRequest }) => {
    const response = await apiRequest('POST', '/api/users', {
      email: 'not-an-email',
      password: 'Test123!',
      name: 'Test User'
    });
    
    expect(response.status()).toBe(400);
  });
  
  test('should reject weak password', async ({ apiRequest }) => {
    const response = await apiRequest('POST', '/api/users', {
      email: faker.internet.email(),
      password: '123',  // Too short
      name: 'Test User'
    });
    
    expect(response.status()).toBe(400);
  });
  
  // ========================================
  // Idempotency Tests
  // ========================================
  
  test('should prevent duplicate creation with same email', async ({ apiRequest, createUser }) => {
    const userData = await createUser();
    
    // Second creation attempt with same email
    const response = await apiRequest('POST', '/api/users', userData);
    
    expect([400, 409]).toContain(response.status());
  });
  
  // ========================================
  // Side Effect Tests
  // ========================================
  
  test('new user should be visible in GET /api/users immediately', async ({ apiRequest, createUser }) => {
    const userData = await createUser();
    
    // Verify in list
    const listResponse = await apiRequest('GET', '/api/users');
    const listData = await listResponse.json();
    
    const foundUser = listData.data.find(u => u.email === userData.email);
    expect(foundUser).toBeDefined();
  });
});

test.describe('GET /api/users/:id', () => {
  
  test('should return user by valid UUID', async ({ apiRequest, createUser }) => {
    const userData = await createUser();
    
    const response = await apiRequest('GET', `/api/users/${userData.email}`);
    
    expect(response.status()).toBe(200);
    const user = await response.json();
    
    expect(user.email).toBe(userData.email);
  });
  
  test('should return 404 for non-existent user', async ({ apiRequest }) => {
    const fakeId = faker.string.uuid();
    
    const response = await apiRequest('GET', `/api/users/${fakeId}`);
    
    expect(response.status()).toBe(404);
  });
  
  test('should exclude sensitive fields (password hash)', async ({ apiRequest, createUser }) => {
    const userData = await createUser();
    
    const response = await apiRequest('GET', `/api/users/${userData.email}`);
    const user = await response.json();
    
    expect(user).not.toHaveProperty('password');
    expect(user).not.toHaveProperty('passwordHash');
  });
});
Step 2.3: 认证授权测试
// tests/api/auth.spec.ts
import { test, expect } from './setup';

test.describe('Authentication & Authorization', () => {
  
  test('should reject requests without authentication', async ({ apiRequest }) => {
    const response = await apiRequest('GET', '/api/users');
    
    expect(response.status()).toBe(401);
  });
  
  test('should allow authenticated requests', async ({ apiRequest, authHeader }) => {
    const headers = await authHeader();
    
    const response = await apiRequest('GET', '/api/users', undefined, {
      headers
    });
    
    expect(response.status()).toBe(200);
  });
  
  test('should enforce role-based access control', async ({ apiRequest, authHeader }) => {
    const headers = await authHeader();
    
    // Regular user cannot access admin endpoint
    const response = await apiRequest('GET', '/api/admin/users', undefined, {
      headers
    });
    
    expect(response.status()).toBe(403);
  });
  
  test('should validate JWT token expiration', async ({ apiRequest }) => {
    const expiredToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';  // Expired token
    
    const response = await apiRequest('GET', '/api/users', undefined, {
      headers: { Authorization: `Bearer ${expiredToken}` }
    });
    
    expect(response.status()).toBe(401);
  });
});

Phase 3: 微服务集成测试

场景:跨服务业务流程验证

// tests/integration/order-flow.spec.ts
import { test, expect } from './setup';

test.describe('Order Processing Workflow', () => {
  
  test.beforeEach(async ({ request }) => {
    // Ensure all services are healthy
    await expectServiceHealthy('auth-service');
    await expectServiceHealthy('inventory-service');
    await expectServiceHealthy('order-service');
    await expectServiceHealthy('payment-service');
  });
  
  test('complete order flow with inventory update', async ({ apiRequest, authHeader }) => {
    const headers = await authHeader();
    
    // Step 1: Check initial inventory
    const initialInventory = await getInventory('SKU-123');
    expect(initialInventory).toBe(10);
    
    // Step 2: Create order
    const orderResponse = await apiRequest('POST', '/api/orders', {
      items: [
        { productId: 'SKU-123', quantity: 2 },
        { productId: 'SKU-456', quantity: 1 }
      ]
    }, { headers });
    
    const order = await orderResponse.json();
    expect(orderResponse.status()).toBe(201);
    
    // Step 3: Process payment
    const paymentResponse = await apiRequest('POST', `/api/payments`, {
      orderId: order.id,
      amount: order.total,
      cardNumber: '4111111111111111'
    }, { headers });
    
    expect(paymentResponse.status()).toBe(200);
    
    // Step 4: Wait for async events to process
    await waitForEvent('order.confirmed', 5000);
    await waitForEvent('inventory.updated', 5000);
    
    // Step 5: Verify final state
    const finalInventory = await getInventory('SKU-123');
    expect(finalInventory).toBe(8);  // 10 - 2 = 8
    
    // Step 6: Verify email was sent
    const emailSent = await checkEmailLog('test@example.com');
    expect(emailSent).toContain('Order confirmation');
  });
});

// Helper functions
async function getInventory(productId: string): Promise {
  const response = await test.request.get(`/api/inventory/${productId}`);
  const data = await response.json();
  return data.quantity;
}

async function waitForEvent(eventName: string, timeout: number): Promise {
  // Poll event log or use WebSocket
  const startTime = Date.now();
  
  while (Date.now() - startTime  e.type === eventName)) {
      return;
    }
    await new Promise(r => setTimeout(r, 100));
  }
  
  throw new Error(`Event ${eventName} not received within ${timeout}ms`);
}

Phase 4: Mock Server 集成

目的:隔离外部依赖,加速测试执行

// tests/mocks/setup.ts
import { setupServer } from 'msw/node';
import { rest } from 'msw';

export const handlers = [
  // Mock external payment gateway
  rest.post('https://api.stripe.com/charges', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({
        id: 'ch_mock_123',
        status: 'succeeded',
        amount: 1000
      })
    );
  }),
  
  // Mock email service
  rest.post('https://api.sendgrid.com/mail/send', (req, res, ctx) => {
    return res(ctx.status(202));
  }),
  
  // Mock slow third-party API
  rest.get('https://slow-api.example.com/data', async (req, res, ctx) => {
    await new Promise(r => setTimeout(r, 3000));
    return res(ctx.json({ data: 'mocked' }));
  })
];

export const server = setupServer(...handlers);

// In test setup
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Phase 5: 数据一致性验证

场景:分布式事务、最终一致性检查

test('should maintain data consistency across services', async ({ apiRequest }) => {
  // Create order
  const orderResponse = await apiRequest('POST', '/api/orders', {
    items: [{ productId: 'SKU-123', quantity: 1 }]
  });
  
  const order = await orderResponse.json();
  
  // Wait for eventual consistency (up to 5 seconds)
  await waitForConsistency(async () => {
    const inventoryResponse = await apiRequest('GET', '/api/inventory/SKU-123');
    const inventory = await inventoryResponse.json();
    
    // Inventory should be decremented
    return inventory.quantity === 9;
  }, 5000);
  
  // Verify audit log
  const auditResponse = await apiRequest('GET', `/api/audit?orderId=${order.id}`);
  const auditLog = await auditResponse.json();
  
  expect(auditLog).toContainEqual(
    expect.objectContaining({
      action: 'ORDER_CREATED',
      orderId: order.id
    })
  );
});

参考资源

模板库

  • [API Test Setup Template](./references/api-test-setup.md)
  • [CRUD Test Patterns](./references/crud-test-patterns.md)
  • [Auth Testing Strategies](./references/auth-testing-patterns.md)

最佳实践

  • [OpenAPI Analysis Guide](./references/openapi-analysis.md)
  • [Mock Server Integration](./references/mock-server-integration.md)
  • [Data Consistency Validation](./references/data-consistency-validation.md)

高级主题

  • [Distributed Transaction Testing](./references/distributed-transaction-testing.md)
  • [Event-Driven Architecture Testing](./references/event-driven-testing.md)
  • [Performance Benchmarking](./references/api-performance-benchmarking.md)

与父级 Skill 集成

devlab-test-onboard 调用方式

用户:"新项目需要配置测试"
  ↓
devlab-test-onboard 检测到项目特征:OpenAPI spec + k8s/
  ↓
自动推荐:dev

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [seed-forge](https://github.com/seed-forge)
- **Source:** [seed-forge/harness-ai-kit](https://github.com/seed-forge/harness-ai-kit)
- **License:** Apache-2.0
- **Homepage:** https://pypi.org/project/harness-ai-kit/

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.