api-tester
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAPI Tester Skill
API Tester 技能
Quick API endpoint testing with comprehensive request/response validation.
快速进行API端点测试,包含全面的请求/响应验证。
Instructions
使用说明
You are an API testing expert. When invoked:
-
Test API Endpoints:
- Validate HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Test request headers and body formats
- Verify response status codes
- Validate response schema and data types
- Check authentication and authorization
-
Generate Test Cases:
- Create curl commands for testing
- Generate Postman collections
- Write automated test scripts
- Test edge cases and error scenarios
- Validate API contracts
-
Performance Testing:
- Load testing with concurrent requests
- Response time benchmarking
- Rate limit verification
- Timeout handling
- Connection pooling tests
-
Security Testing:
- Authentication/authorization checks
- Input validation testing
- SQL injection prevention
- XSS prevention
- CORS configuration
你是一名API测试专家。被调用时:
-
测试API端点:
- 验证HTTP方法(GET、POST、PUT、PATCH、DELETE)
- 测试请求头和请求体格式
- 验证响应状态码
- 校验响应 schema 和数据类型
- 检查认证与授权
-
生成测试用例:
- 创建用于测试的curl命令
- 生成Postman集合
- 编写自动化测试脚本
- 测试边缘情况和错误场景
- 验证API契约
-
性能测试:
- 并发请求的负载测试
- 响应时间基准测试
- 速率限制验证
- 超时处理测试
- 连接池测试
-
安全测试:
- 认证/授权检查
- 输入验证测试
- SQL注入防护测试
- XSS防护测试
- CORS配置验证
Usage Examples
使用示例
@api-tester
@api-tester --endpoint /api/users
@api-tester --method POST
@api-tester --load-test
@api-tester --generate-collection@api-tester
@api-tester --endpoint /api/users
@api-tester --method POST
@api-tester --load-test
@api-tester --generate-collectionREST API Testing
REST API 测试
GET Request Examples
GET 请求示例
Basic GET Request
基础GET请求
bash
undefinedbash
undefinedcurl
curl
curl -X GET https://api.example.com/api/users
-H "Content-Type: application/json"
-H "Content-Type: application/json"
curl -X GET https://api.example.com/api/users
-H "Content-Type: application/json"
-H "Content-Type: application/json"
With authentication
带认证
curl -X GET https://api.example.com/api/users
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
curl -X GET https://api.example.com/api/users
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
With query parameters
带查询参数
curl -X GET "https://api.example.com/api/users?page=1&limit=10&sort=created_at"
-H "Authorization: Bearer YOUR_TOKEN"
-H "Authorization: Bearer YOUR_TOKEN"
curl -X GET "https://api.example.com/api/users?page=1&limit=10&sort=created_at"
-H "Authorization: Bearer YOUR_TOKEN"
-H "Authorization: Bearer YOUR_TOKEN"
Verbose output (includes headers)
详细输出(包含请求头)
curl -v -X GET https://api.example.com/api/users
undefinedcurl -v -X GET https://api.example.com/api/users
undefinedJavaScript/Node.js
JavaScript/Node.js
javascript
// Using fetch
async function getUsers() {
const response = await fetch('https://api.example.com/api/users', {
method: 'GET',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
}
// Using axios
const axios = require('axios');
async function getUsers() {
try {
const response = await axios.get('https://api.example.com/api/users', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
},
params: {
page: 1,
limit: 10
}
});
return response.data;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
throw error;
}
}javascript
// 使用 fetch
async function getUsers() {
const response = await fetch('https://api.example.com/api/users', {
method: 'GET',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
}
// 使用 axios
const axios = require('axios');
async function getUsers() {
try {
const response = await axios.get('https://api.example.com/api/users', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
},
params: {
page: 1,
limit: 10
}
});
return response.data;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
throw error;
}
}Python
Python
python
import requestspython
import requestsBasic GET request
基础GET请求
response = requests.get('https://api.example.com/api/users')
print(response.json())
response = requests.get('https://api.example.com/api/users')
print(response.json())
With authentication and parameters
带认证和参数
headers = {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
params = {
'page': 1,
'limit': 10,
'sort': 'created_at'
}
response = requests.get(
'https://api.example.com/api/users',
headers=headers,
params=params
)
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f"Error: {response.status_code}")
print(response.text)
undefinedheaders = {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
params = {
'page': 1,
'limit': 10,
'sort': 'created_at'
}
response = requests.get(
'https://api.example.com/api/users',
headers=headers,
params=params
)
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f"Error: {response.status_code}")
print(response.text)
undefinedPOST Request Examples
POST 请求示例
Create Resource
创建资源
bash
undefinedbash
undefinedcurl
curl
curl -X POST https://api.example.com/api/users
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Doe", "email": "john@example.com", "role": "user" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Doe", "email": "john@example.com", "role": "user" }'
curl -X POST https://api.example.com/api/users
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Doe", "email": "john@example.com", "role": "user" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Doe", "email": "john@example.com", "role": "user" }'
From file
从文件读取
curl -X POST https://api.example.com/api/users
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d @user.json
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d @user.json
undefinedcurl -X POST https://api.example.com/api/users
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d @user.json
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d @user.json
undefinedJavaScript/Node.js
JavaScript/Node.js
javascript
// Using fetch
async function createUser(userData) {
const response = await fetch('https://api.example.com/api/users', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
});
const data = await response.json();
return data;
}
// Usage
const newUser = {
name: 'John Doe',
email: 'john@example.com',
role: 'user'
};
createUser(newUser)
.then(user => console.log('Created:', user))
.catch(error => console.error('Error:', error));
// Using axios with error handling
async function createUser(userData) {
try {
const response = await axios.post(
'https://api.example.com/api/users',
userData,
{
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
}
}
);
return response.data;
} catch (error) {
if (error.response) {
// Server responded with error
console.error('Error:', error.response.status);
console.error('Message:', error.response.data);
} else if (error.request) {
// No response received
console.error('No response from server');
} else {
console.error('Error:', error.message);
}
throw error;
}
}javascript
// 使用 fetch
async function createUser(userData) {
const response = await fetch('https://api.example.com/api/users', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
});
const data = await response.json();
return data;
}
// 使用示例
const newUser = {
name: 'John Doe',
email: 'john@example.com',
role: 'user'
};
createUser(newUser)
.then(user => console.log('Created:', user))
.catch(error => console.error('Error:', error));
// 使用 axios 并处理错误
async function createUser(userData) {
try {
const response = await axios.post(
'https://api.example.com/api/users',
userData,
{
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
}
}
);
return response.data;
} catch (error) {
if (error.response) {
// 服务器返回错误
console.error('Error:', error.response.status);
console.error('Message:', error.response.data);
} else if (error.request) {
// 未收到响应
console.error('No response from server');
} else {
console.error('Error:', error.message);
}
throw error;
}
}Python
Python
python
import requestspython
import requestsCreate user
创建用户
user_data = {
'name': 'John Doe',
'email': 'john@example.com',
'role': 'user'
}
headers = {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
response = requests.post(
'https://api.example.com/api/users',
json=user_data,
headers=headers
)
if response.status_code == 201:
print('User created:', response.json())
else:
print(f'Error: {response.status_code}')
print(response.json())
undefineduser_data = {
'name': 'John Doe',
'email': 'john@example.com',
'role': 'user'
}
headers = {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
response = requests.post(
'https://api.example.com/api/users',
json=user_data,
headers=headers
)
if response.status_code == 201:
print('User created:', response.json())
else:
print(f'Error: {response.status_code}')
print(response.json())
undefinedPUT/PATCH Request Examples
PUT/PATCH 请求示例
bash
undefinedbash
undefinedPUT - Replace entire resource
PUT - 替换整个资源
curl -X PUT https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Updated", "email": "john.updated@example.com", "role": "admin" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Updated", "email": "john.updated@example.com", "role": "admin" }'
curl -X PUT https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Updated", "email": "john.updated@example.com", "role": "admin" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "name": "John Updated", "email": "john.updated@example.com", "role": "admin" }'
PATCH - Partial update
PATCH - 部分更新
curl -X PATCH https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "role": "admin" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "role": "admin" }'
undefinedcurl -X PATCH https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "role": "admin" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "role": "admin" }'
undefinedDELETE Request Examples
DELETE 请求示例
bash
undefinedbash
undefinedDelete resource
删除资源
curl -X DELETE https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "Authorization: Bearer YOUR_TOKEN"
curl -X DELETE https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "Authorization: Bearer YOUR_TOKEN"
Delete with confirmation
带确认的删除
curl -X DELETE https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "X-Confirm-Delete: true"
-H "Authorization: Bearer YOUR_TOKEN"
-H "X-Confirm-Delete: true"
undefinedcurl -X DELETE https://api.example.com/api/users/123
-H "Authorization: Bearer YOUR_TOKEN"
-H "X-Confirm-Delete: true"
-H "Authorization: Bearer YOUR_TOKEN"
-H "X-Confirm-Delete: true"
undefinedAuthentication Examples
认证示例
Bearer Token (JWT)
Bearer Token (JWT)
bash
undefinedbash
undefinedGet token
获取令牌
curl -X POST https://api.example.com/auth/login
-H "Content-Type: application/json"
-d '{ "email": "user@example.com", "password": "password123" }'
-H "Content-Type: application/json"
-d '{ "email": "user@example.com", "password": "password123" }'
curl -X POST https://api.example.com/auth/login
-H "Content-Type: application/json"
-d '{ "email": "user@example.com", "password": "password123" }'
-H "Content-Type: application/json"
-d '{ "email": "user@example.com", "password": "password123" }'
Use token
使用令牌
curl -X GET https://api.example.com/api/users
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
undefinedcurl -X GET https://api.example.com/api/users
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
undefinedAPI Key
API Key
bash
undefinedbash
undefinedIn header
在请求头中
curl -X GET https://api.example.com/api/users
-H "X-API-Key: your-api-key-here"
-H "X-API-Key: your-api-key-here"
curl -X GET https://api.example.com/api/users
-H "X-API-Key: your-api-key-here"
-H "X-API-Key: your-api-key-here"
In query parameter
在查询参数中
undefinedundefinedBasic Auth
Basic Auth
bash
undefinedbash
undefinedUsername and password
用户名和密码
curl -X GET https://api.example.com/api/users
-u username:password
-u username:password
curl -X GET https://api.example.com/api/users
-u username:password
-u username:password
Base64 encoded
Base64编码
curl -X GET https://api.example.com/api/users
-H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="
-H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="
undefinedcurl -X GET https://api.example.com/api/users
-H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="
-H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="
undefinedOAuth 2.0
OAuth 2.0
javascript
// Get access token
async function getAccessToken() {
const response = await fetch('https://oauth.example.com/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET'
})
});
const data = await response.json();
return data.access_token;
}
// Use access token
async function callAPI() {
const token = await getAccessToken();
const response = await fetch('https://api.example.com/api/users', {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
}javascript
// 获取访问令牌
async function getAccessToken() {
const response = await fetch('https://oauth.example.com/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET'
})
});
const data = await response.json();
return data.access_token;
}
// 使用访问令牌
async function callAPI() {
const token = await getAccessToken();
const response = await fetch('https://api.example.com/api/users', {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
}GraphQL Testing
GraphQL 测试
Basic Query
基础查询
bash
undefinedbash
undefinedcurl
curl
curl -X POST https://api.example.com/graphql
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "{ users { id name email } }" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "{ users { id name email } }" }'
curl -X POST https://api.example.com/graphql
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "{ users { id name email } }" }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "{ users { id name email } }" }'
With variables
带变量
curl -X POST https://api.example.com/graphql
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "query GetUser($id: ID!) { user(id: $id) { id name email } }", "variables": { "id": "123" } }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "query GetUser($id: ID!) { user(id: $id) { id name email } }", "variables": { "id": "123" } }'
undefinedcurl -X POST https://api.example.com/graphql
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "query GetUser($id: ID!) { user(id: $id) { id name email } }", "variables": { "id": "123" } }'
-H "Authorization: Bearer YOUR_TOKEN"
-H "Content-Type: application/json"
-d '{ "query": "query GetUser($id: ID!) { user(id: $id) { id name email } }", "variables": { "id": "123" } }'
undefinedGraphQL Mutations
GraphQL 变更
javascript
// Create user mutation
async function createUser(name, email) {
const query = `
mutation CreateUser($name: String!, $email: String!) {
createUser(input: { name: $name, email: $email }) {
id
name
email
createdAt
}
}
`;
const response = await fetch('https://api.example.com/graphql', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
query,
variables: { name, email }
})
});
const data = await response.json();
return data.data.createUser;
}javascript
// 创建用户变更
async function createUser(name, email) {
const query = `
mutation CreateUser($name: String!, $email: String!) {
createUser(input: { name: $name, email: $email }) {
id
name
email
createdAt
}
}
`;
const response = await fetch('https://api.example.com/graphql', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
query,
variables: { name, email }
})
});
const data = await response.json();
return data.data.createUser;
}Automated Testing
自动化测试
Jest Test Suite
Jest 测试套件
javascript
const axios = require('axios');
describe('User API Tests', () => {
const API_URL = 'https://api.example.com';
const token = 'YOUR_TEST_TOKEN';
const api = axios.create({
baseURL: API_URL,
headers: {
'Authorization': `Bearer ${token}`
}
});
describe('GET /api/users', () => {
test('should return list of users', async () => {
const response = await api.get('/api/users');
expect(response.status).toBe(200);
expect(Array.isArray(response.data)).toBe(true);
expect(response.data.length).toBeGreaterThan(0);
});
test('should return user by ID', async () => {
const response = await api.get('/api/users/123');
expect(response.status).toBe(200);
expect(response.data).toHaveProperty('id', '123');
expect(response.data).toHaveProperty('name');
expect(response.data).toHaveProperty('email');
});
test('should return 404 for non-existent user', async () => {
try {
await api.get('/api/users/999999');
} catch (error) {
expect(error.response.status).toBe(404);
}
});
});
describe('POST /api/users', () => {
test('should create new user', async () => {
const newUser = {
name: 'Test User',
email: 'test@example.com'
};
const response = await api.post('/api/users', newUser);
expect(response.status).toBe(201);
expect(response.data).toHaveProperty('id');
expect(response.data.name).toBe(newUser.name);
expect(response.data.email).toBe(newUser.email);
});
test('should validate required fields', async () => {
const invalidUser = { name: 'Test' }; // missing email
try {
await api.post('/api/users', invalidUser);
} catch (error) {
expect(error.response.status).toBe(400);
expect(error.response.data).toHaveProperty('error');
}
});
test('should prevent duplicate emails', async () => {
const user = {
name: 'Duplicate',
email: 'existing@example.com'
};
try {
await api.post('/api/users', user);
} catch (error) {
expect(error.response.status).toBe(409);
}
});
});
describe('Authentication', () => {
test('should reject requests without token', async () => {
const noAuthAPI = axios.create({ baseURL: API_URL });
try {
await noAuthAPI.get('/api/users');
} catch (error) {
expect(error.response.status).toBe(401);
}
});
test('should reject invalid token', async () => {
const badAuthAPI = axios.create({
baseURL: API_URL,
headers: { 'Authorization': 'Bearer invalid-token' }
});
try {
await badAuthAPI.get('/api/users');
} catch (error) {
expect(error.response.status).toBe(401);
}
});
});
});javascript
const axios = require('axios');
describe('User API Tests', () => {
const API_URL = 'https://api.example.com';
const token = 'YOUR_TEST_TOKEN';
const api = axios.create({
baseURL: API_URL,
headers: {
'Authorization': `Bearer ${token}`
}
});
describe('GET /api/users', () => {
test('should return list of users', async () => {
const response = await api.get('/api/users');
expect(response.status).toBe(200);
expect(Array.isArray(response.data)).toBe(true);
expect(response.data.length).toBeGreaterThan(0);
});
test('should return user by ID', async () => {
const response = await api.get('/api/users/123');
expect(response.status).toBe(200);
expect(response.data).toHaveProperty('id', '123');
expect(response.data).toHaveProperty('name');
expect(response.data).toHaveProperty('email');
});
test('should return 404 for non-existent user', async () => {
try {
await api.get('/api/users/999999');
} catch (error) {
expect(error.response.status).toBe(404);
}
});
});
describe('POST /api/users', () => {
test('should create new user', async () => {
const newUser = {
name: 'Test User',
email: 'test@example.com'
};
const response = await api.post('/api/users', newUser);
expect(response.status).toBe(201);
expect(response.data).toHaveProperty('id');
expect(response.data.name).toBe(newUser.name);
expect(response.data.email).toBe(newUser.email);
});
test('should validate required fields', async () => {
const invalidUser = { name: 'Test' }; // 缺少邮箱
try {
await api.post('/api/users', invalidUser);
} catch (error) {
expect(error.response.status).toBe(400);
expect(error.response.data).toHaveProperty('error');
}
});
test('should prevent duplicate emails', async () => {
const user = {
name: 'Duplicate',
email: 'existing@example.com'
};
try {
await api.post('/api/users', user);
} catch (error) {
expect(error.response.status).toBe(409);
}
});
});
describe('Authentication', () => {
test('should reject requests without token', async () => {
const noAuthAPI = axios.create({ baseURL: API_URL });
try {
await noAuthAPI.get('/api/users');
} catch (error) {
expect(error.response.status).toBe(401);
}
});
test('should reject invalid token', async () => {
const badAuthAPI = axios.create({
baseURL: API_URL,
headers: { 'Authorization': 'Bearer invalid-token' }
});
try {
await badAuthAPI.get('/api/users');
} catch (error) {
expect(error.response.status).toBe(401);
}
});
});
});Python pytest
Python pytest
python
import pytest
import requests
API_URL = 'https://api.example.com'
TOKEN = 'YOUR_TEST_TOKEN'
@pytest.fixture
def headers():
return {
'Authorization': f'Bearer {TOKEN}',
'Content-Type': 'application/json'
}
def test_get_users(headers):
response = requests.get(f'{API_URL}/api/users', headers=headers)
assert response.status_code == 200
assert isinstance(response.json(), list)
assert len(response.json()) > 0
def test_get_user_by_id(headers):
response = requests.get(f'{API_URL}/api/users/123', headers=headers)
assert response.status_code == 200
data = response.json()
assert data['id'] == '123'
assert 'name' in data
assert 'email' in data
def test_create_user(headers):
user_data = {
'name': 'Test User',
'email': 'test@example.com'
}
response = requests.post(
f'{API_URL}/api/users',
json=user_data,
headers=headers
)
assert response.status_code == 201
data = response.json()
assert 'id' in data
assert data['name'] == user_data['name']
def test_unauthorized_access():
response = requests.get(f'{API_URL}/api/users')
assert response.status_code == 401python
import pytest
import requests
API_URL = 'https://api.example.com'
TOKEN = 'YOUR_TEST_TOKEN'
@pytest.fixture
def headers():
return {
'Authorization': f'Bearer {TOKEN}',
'Content-Type': 'application/json'
}
def test_get_users(headers):
response = requests.get(f'{API_URL}/api/users', headers=headers)
assert response.status_code == 200
assert isinstance(response.json(), list)
assert len(response.json()) > 0
def test_get_user_by_id(headers):
response = requests.get(f'{API_URL}/api/users/123', headers=headers)
assert response.status_code == 200
data = response.json()
assert data['id'] == '123'
assert 'name' in data
assert 'email' in data
def test_create_user(headers):
user_data = {
'name': 'Test User',
'email': 'test@example.com'
}
response = requests.post(
f'{API_URL}/api/users',
json=user_data,
headers=headers
)
assert response.status_code == 201
data = response.json()
assert 'id' in data
assert data['name'] == user_data['name']
def test_unauthorized_access():
response = requests.get(f'{API_URL}/api/users')
assert response.status_code == 401Postman Collection
Postman 集合
Collection Structure
集合结构
json
{
"info": {
"name": "API Test Collection",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{access_token}}",
"type": "string"
}
]
},
"item": [
{
"name": "Users",
"item": [
{
"name": "Get All Users",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/api/users?page=1&limit=10",
"host": ["{{base_url}}"],
"path": ["api", "users"],
"query": [
{ "key": "page", "value": "1" },
{ "key": "limit", "value": "10" }
]
}
},
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('Status code is 200', function () {",
" pm.response.to.have.status(200);",
"});",
"",
"pm.test('Response is array', function () {",
" var jsonData = pm.response.json();",
" pm.expect(jsonData).to.be.an('array');",
"});"
]
}
}
]
},
{
"name": "Create User",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"{{$randomFullName}}\",\n \"email\": \"{{$randomEmail}}\",\n \"role\": \"user\"\n}"
},
"url": {
"raw": "{{base_url}}/api/users",
"host": ["{{base_url}}"],
"path": ["api", "users"]
}
},
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('Status code is 201', function () {",
" pm.response.to.have.status(201);",
"});",
"",
"pm.test('User has ID', function () {",
" var jsonData = pm.response.json();",
" pm.expect(jsonData).to.have.property('id');",
" pm.environment.set('user_id', jsonData.id);",
"});"
]
}
}
]
}
]
}
],
"variable": [
{
"key": "base_url",
"value": "https://api.example.com"
}
]
}json
{
"info": {
"name": "API Test Collection",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{access_token}}",
"type": "string"
}
]
},
"item": [
{
"name": "Users",
"item": [
{
"name": "Get All Users",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/api/users?page=1&limit=10",
"host": ["{{base_url}}"],
"path": ["api", "users"],
"query": [
{ "key": "page", "value": "1" },
{ "key": "limit", "value": "10" }
]
}
},
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('Status code is 200', function () {",
" pm.response.to.have.status(200);",
"});",
"",
"pm.test('Response is array', function () {",
" var jsonData = pm.response.json();",
" pm.expect(jsonData).to.be.an('array');",
"});"
]
}
}
]
},
{
"name": "Create User",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"{{$randomFullName}}\",\n \"email\": \"{{$randomEmail}}\",\n \"role\": \"user\"\n}"
},
"url": {
"raw": "{{base_url}}/api/users",
"host": ["{{base_url}}"],
"path": ["api", "users"]
}
},
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('Status code is 201', function () {",
" pm.response.to.have.status(201);",
"});",
"",
"pm.test('User has ID', function () {",
" var jsonData = pm.response.json();",
" pm.expect(jsonData).to.have.property('id');",
" pm.environment.set('user_id', jsonData.id);",
"});"
]
}
}
]
}
]
}
],
"variable": [
{
"key": "base_url",
"value": "https://api.example.com"
}
]
}Load Testing
负载测试
Using Apache Bench
使用Apache Bench
bash
undefinedbash
undefined1000 requests, 10 concurrent
1000次请求,10个并发
ab -n 1000 -c 10 -H "Authorization: Bearer TOKEN"
https://api.example.com/api/users
https://api.example.com/api/users
ab -n 1000 -c 10 -H "Authorization: Bearer TOKEN"
https://api.example.com/api/users
https://api.example.com/api/users
POST request with JSON
带JSON的POST请求
ab -n 1000 -c 10 -p data.json -T application/json
-H "Authorization: Bearer TOKEN"
https://api.example.com/api/users
-H "Authorization: Bearer TOKEN"
https://api.example.com/api/users
undefinedab -n 1000 -c 10 -p data.json -T application/json
-H "Authorization: Bearer TOKEN"
https://api.example.com/api/users
-H "Authorization: Bearer TOKEN"
https://api.example.com/api/users
undefinedUsing Artillery
使用Artillery
yaml
undefinedyaml
undefinedartillery.yml
artillery.yml
config:
target: 'https://api.example.com'
phases:
- duration: 60
arrivalRate: 10
name: Warm up
- duration: 300
arrivalRate: 50
name: Sustained load
defaults:
headers:
Authorization: 'Bearer YOUR_TOKEN'
scenarios:
- name: "Get users"
flow:
- get: url: "/api/users" expect: - statusCode: 200
- think: 1
- post: url: "/api/users" json: name: "Test User" email: "test@example.com" expect: - statusCode: 201
```bashconfig:
target: 'https://api.example.com'
phases:
- duration: 60
arrivalRate: 10
name: Warm up
- duration: 300
arrivalRate: 50
name: Sustained load
defaults:
headers:
Authorization: 'Bearer YOUR_TOKEN'
scenarios:
- name: "Get users"
flow:
- get: url: "/api/users" expect: - statusCode: 200
- think: 1
- post: url: "/api/users" json: name: "Test User" email: "test@example.com" expect: - statusCode: 201
```bashRun load test
运行负载测试
artillery run artillery.yml
artillery run artillery.yml
Generate HTML report
生成HTML报告
artillery run artillery.yml --output report.json
artillery report report.json --output report.html
undefinedartillery run artillery.yml --output report.json
artillery report report.json --output report.html
undefinedResponse Validation
响应验证
Schema Validation
Schema验证
javascript
const Ajv = require('ajv');
const ajv = new Ajv();
// Define schema
const userSchema = {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
email: { type: 'string', format: 'email' },
role: { type: 'string', enum: ['user', 'admin'] },
createdAt: { type: 'string', format: 'date-time' }
},
required: ['id', 'name', 'email', 'role']
};
const validate = ajv.compile(userSchema);
// Validate response
async function testUserAPI() {
const response = await fetch('https://api.example.com/api/users/123');
const data = await response.json();
const valid = validate(data);
if (!valid) {
console.error('Validation errors:', validate.errors);
} else {
console.log('Response is valid!');
}
}javascript
const Ajv = require('ajv');
const ajv = new Ajv();
// 定义schema
const userSchema = {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
email: { type: 'string', format: 'email' },
role: { type: 'string', enum: ['user', 'admin'] },
createdAt: { type: 'string', format: 'date-time' }
},
required: ['id', 'name', 'email', 'role']
};
const validate = ajv.compile(userSchema);
// 验证响应
async function testUserAPI() {
const response = await fetch('https://api.example.com/api/users/123');
const data = await response.json();
const valid = validate(data);
if (!valid) {
console.error('Validation errors:', validate.errors);
} else {
console.log('Response is valid!');
}
}Best Practices
最佳实践
Request Best Practices
请求最佳实践
- Always set appropriate headers
Content-Type - Use proper HTTP methods (GET for reads, POST for creates, etc.)
- Include authentication tokens securely
- Handle timeouts and retries
- Validate input before sending
- Use HTTPS for production APIs
- 始终设置合适的请求头
Content-Type - 使用正确的HTTP方法(GET用于读取,POST用于创建等)
- 安全地包含认证令牌
- 处理超时和重试
- 发送前验证输入
- 生产环境API使用HTTPS
Response Handling
响应处理
- Check status codes before parsing
- Handle errors gracefully
- Validate response schema
- Log requests and responses for debugging
- Implement exponential backoff for retries
- 解析前检查状态码
- 优雅地处理错误
- 验证响应schema
- 记录请求和响应以用于调试
- 实现指数退避重试机制
Security Testing
安全测试
- Test with invalid tokens
- Test without authentication
- Attempt SQL injection in parameters
- Test XSS in input fields
- Verify CORS settings
- Test rate limiting
- 使用无效令牌测试
- 无认证情况下测试
- 在参数中尝试SQL注入
- 在输入字段中测试XSS
- 验证CORS设置
- 测试速率限制
Error Scenarios to Test
需测试的错误场景
- Invalid authentication
- Missing required fields
- Invalid data types
- Duplicate resources
- Not found (404)
- Server errors (500)
- Rate limit exceeded (429)
- Network timeouts
- 无效认证
- 缺少必填字段
- 无效数据类型
- 重复资源
- 资源不存在(404)
- 服务器错误(500)
- 超出速率限制(429)
- 网络超时
Common HTTP Status Codes
常见HTTP状态码
200 OK - Request successful
201 Created - Resource created
204 No Content - Success, no response body
400 Bad Request - Invalid request
401 Unauthorized - Missing/invalid authentication
403 Forbidden - Not allowed to access
404 Not Found - Resource doesn't exist
409 Conflict - Resource already exists
422 Unprocessable Entity - Validation failed
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error - Server error
502 Bad Gateway - Upstream server error
503 Service Unavailable - Server overloaded200 OK - 请求成功
201 Created - 资源已创建
204 No Content - 请求成功,无响应体
400 Bad Request - 请求无效
401 Unauthorized - 缺少/无效认证
403 Forbidden - 无访问权限
404 Not Found - 资源不存在
409 Conflict - 资源已存在
422 Unprocessable Entity - 验证失败
429 Too Many Requests - 超出速率限制
500 Internal Server Error - 服务器错误
502 Bad Gateway - 上游服务器错误
503 Service Unavailable - 服务器过载Notes
注意事项
- Always test in development/staging before production
- Use environment variables for API URLs and tokens
- Document all test cases and expected results
- Automate testing in CI/CD pipeline
- Monitor API performance and error rates
- Keep Postman collections updated
- Test edge cases and error scenarios
- Validate both success and failure paths
- Use proper authentication methods
- Never commit API keys or tokens to version control
- 始终先在开发/预发布环境测试,再到生产环境
- 使用环境变量存储API地址和令牌
- 记录所有测试用例和预期结果
- 在CI/CD流水线中自动化测试
- 监控API性能和错误率
- 保持Postman集合更新
- 测试边缘情况和错误场景
- 验证成功和失败路径
- 使用合适的认证方法
- 切勿将API密钥或令牌提交到版本控制系统