feat: 完成API测试、生产环境配置和文档编写

## 🧪 API测试系统完善
- 创建完整的单元测试套件 (tests/unit_test.go)
  - 认证流程、CRUD操作、文件上传测试
  - 中间件、错误处理、性能测试
- 创建集成测试套件 (tests/integration_test.go)
  - 业务流程、数据一致性、并发测试
- 创建综合API测试 (test_api_comprehensive.http)
  - 92个测试场景,覆盖所有API端点
- 更新Makefile添加测试命令
  - test-unit, test-integration, test-api, test-cover, test-bench

## 🗄️ 生产环境数据库配置
- Docker Compose生产环境配置 (configs/docker/docker-compose.prod.yml)
  - PostgreSQL 16 + Redis 7 + Nginx + 监控栈
- 数据库初始化脚本 (configs/docker/init-db.sql)
  - 完整表结构、索引优化、触发器、视图
- 生产环境配置脚本 (scripts/production-db-setup.sh)
  - 自动化配置、连接池、备份策略、监控

## 📚 API文档完善
- 完整的API文档 (docs/API_DOCUMENTATION.md)
  - 详细接口说明、请求响应示例
  - 认证流程、错误处理、性能优化
  - SDK支持、部署指南、安全考虑
- 包含cURL示例和Postman Collection支持

## 📊 项目进度
- 总进度: 50.0% → 57.5%
- 中优先级任务: 55% → 70%
- 并行完成3个重要任务,显著提升项目完成度

## 🎯 技术成果
- 测试覆盖率大幅提升,支持自动化测试
- 生产环境就绪,支持Docker部署
- 完整的API文档,便于前后端协作
- 性能优化和监控配置,确保生产稳定性
This commit is contained in:
xujiang
2025-07-11 14:10:43 +08:00
parent 5b3fc9bf9c
commit 0ddde92a3c
10 changed files with 4199 additions and 31 deletions

View File

@ -0,0 +1,723 @@
### Photography Portfolio API 综合测试套件
### 包含所有接口的完整测试用例
@baseUrl = http://localhost:8080/api/v1
@token =
### ===============================================
### 健康检查接口测试
### ===============================================
### 1. 健康检查 - 基础测试
GET {{baseUrl}}/health
Content-Type: application/json
### ===============================================
### 认证接口测试
### ===============================================
### 2. 用户注册 - 正常场景
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "testuser_{{$timestamp}}",
"email": "test{{$timestamp}}@example.com",
"password": "testpass123"
}
### 3. 用户注册 - 重复用户名
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "admin",
"email": "admin2@example.com",
"password": "testpass123"
}
### 4. 用户注册 - 无效邮箱
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "testuser2",
"email": "invalid-email",
"password": "testpass123"
}
### 5. 用户注册 - 密码过短
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "testuser3",
"email": "test3@example.com",
"password": "123"
}
### 6. 用户登录 - 正常场景
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "admin123"
}
### 7. 用户登录 - 使用邮箱
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "admin@photography.com",
"password": "admin123"
}
### 8. 用户登录 - 错误密码
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "wrongpassword"
}
### 9. 用户登录 - 不存在的用户
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "nonexistent",
"password": "password123"
}
### ===============================================
### 用户管理接口测试 (需要认证)
### ===============================================
### 10. 获取用户列表 - 无认证
GET {{baseUrl}}/users
Content-Type: application/json
### 11. 获取用户列表 - 有认证
GET {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
### 12. 获取用户列表 - 分页参数
GET {{baseUrl}}/users?page=1&limit=5&status=1
Content-Type: application/json
Authorization: Bearer {{token}}
### 13. 获取用户列表 - 搜索关键词
GET {{baseUrl}}/users?keyword=admin
Content-Type: application/json
Authorization: Bearer {{token}}
### 14. 获取用户详情 - 存在的用户
GET {{baseUrl}}/users/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 15. 获取用户详情 - 不存在的用户
GET {{baseUrl}}/users/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### 16. 创建用户 - 正常场景
POST {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "newuser_{{$timestamp}}",
"email": "newuser{{$timestamp}}@example.com",
"password": "newpass123",
"status": 1
}
### 17. 创建用户 - 重复用户名
POST {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "admin",
"email": "admin3@example.com",
"password": "newpass123"
}
### 18. 创建用户 - 缺少必填字段
POST {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "incompleteuser",
"password": "newpass123"
}
### 19. 更新用户 - 正常场景
PUT {{baseUrl}}/users/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "admin_updated",
"email": "admin_updated@photography.com"
}
### 20. 更新用户 - 不存在的用户
PUT {{baseUrl}}/users/99999
Content-Type: application/json
Authorization: Bearer {{token}}
{
"username": "nonexistent_user",
"email": "nonexistent@example.com"
}
### 21. 删除用户 - 存在的用户
DELETE {{baseUrl}}/users/2
Content-Type: application/json
Authorization: Bearer {{token}}
### 22. 删除用户 - 不存在的用户
DELETE {{baseUrl}}/users/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### 23. 用户头像上传 - 正常场景
POST {{baseUrl}}/users/1/avatar
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="avatar.jpg"
Content-Type: image/jpeg
< ./test_images/avatar.jpg
--boundary--
### 24. 用户头像上传 - 无文件
POST {{baseUrl}}/users/1/avatar
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="title"
Test Avatar
--boundary--
### 25. 用户头像上传 - 非图片文件
POST {{baseUrl}}/users/1/avatar
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="document.txt"
Content-Type: text/plain
This is not an image file
--boundary--
### ===============================================
### 分类管理接口测试
### ===============================================
### 26. 获取分类列表 - 基础查询
GET {{baseUrl}}/categories
Content-Type: application/json
### 27. 获取分类列表 - 包含统计
GET {{baseUrl}}/categories?with_count=true
Content-Type: application/json
### 28. 获取分类列表 - 按状态筛选
GET {{baseUrl}}/categories?is_active=1
Content-Type: application/json
### 29. 获取分类详情 - 存在的分类
GET {{baseUrl}}/categories/1
Content-Type: application/json
### 30. 获取分类详情 - 不存在的分类
GET {{baseUrl}}/categories/99999
Content-Type: application/json
### 31. 创建分类 - 正常场景
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "测试分类_{{$timestamp}}",
"description": "这是一个测试分类",
"sort_order": 1,
"is_active": 1
}
### 32. 创建分类 - 缺少名称
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"description": "没有名称的分类",
"sort_order": 1
}
### 33. 创建子分类 - 正常场景
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "子分类_{{$timestamp}}",
"description": "这是一个子分类",
"parent_id": 1,
"sort_order": 1,
"is_active": 1
}
### 34. 创建子分类 - 父分类不存在
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "子分类2",
"description": "父分类不存在的子分类",
"parent_id": 99999,
"sort_order": 1
}
### 35. 更新分类 - 正常场景
PUT {{baseUrl}}/categories/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "更新的风景分类",
"description": "更新后的自然风光和城市景观",
"sort_order": 2
}
### 36. 更新分类 - 不存在的分类
PUT {{baseUrl}}/categories/99999
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "不存在的分类",
"description": "这个分类不存在"
}
### 37. 删除分类 - 存在的分类
DELETE {{baseUrl}}/categories/3
Content-Type: application/json
Authorization: Bearer {{token}}
### 38. 删除分类 - 不存在的分类
DELETE {{baseUrl}}/categories/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### ===============================================
### 照片管理接口测试
### ===============================================
### 39. 获取照片列表 - 基础查询
GET {{baseUrl}}/photos
Content-Type: application/json
### 40. 获取照片列表 - 分页参数
GET {{baseUrl}}/photos?page=1&limit=5
Content-Type: application/json
### 41. 获取照片列表 - 按分类筛选
GET {{baseUrl}}/photos?category_id=1
Content-Type: application/json
### 42. 获取照片列表 - 按用户筛选
GET {{baseUrl}}/photos?user_id=1
Content-Type: application/json
### 43. 获取照片列表 - 按状态筛选
GET {{baseUrl}}/photos?status=1
Content-Type: application/json
### 44. 获取照片列表 - 关键词搜索
GET {{baseUrl}}/photos?keyword=日落
Content-Type: application/json
### 45. 获取照片列表 - 排序
GET {{baseUrl}}/photos?sort=created_at_desc
Content-Type: application/json
### 46. 获取照片列表 - 复合条件
GET {{baseUrl}}/photos?category_id=1&status=1&sort=title_asc&page=1&limit=10
Content-Type: application/json
### 47. 获取照片详情 - 存在的照片
GET {{baseUrl}}/photos/1
Content-Type: application/json
### 48. 获取照片详情 - 不存在的照片
GET {{baseUrl}}/photos/99999
Content-Type: application/json
### 49. 上传照片 - 正常场景
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="test_photo.jpg"
Content-Type: image/jpeg
< ./test_images/test_photo.jpg
--boundary
Content-Disposition: form-data; name="title"
测试照片_{{$timestamp}}
--boundary
Content-Disposition: form-data; name="description"
这是一个测试照片的描述
--boundary
Content-Disposition: form-data; name="category_id"
1
--boundary--
### 50. 上传照片 - 无文件
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="title"
无文件的照片
--boundary
Content-Disposition: form-data; name="description"
这个请求没有文件
--boundary--
### 51. 上传照片 - 非图片文件
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="document.pdf"
Content-Type: application/pdf
This is not an image
--boundary
Content-Disposition: form-data; name="title"
PDF文件测试
--boundary--
### 52. 上传照片 - 文件过大
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="large_image.jpg"
Content-Type: image/jpeg
< ./test_images/large_image.jpg
--boundary
Content-Disposition: form-data; name="title"
大文件测试
--boundary--
### 53. 更新照片 - 正常场景
PUT {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "更新的照片标题",
"description": "更新的照片描述",
"category_id": 2,
"status": 1
}
### 54. 更新照片 - 不存在的照片
PUT {{baseUrl}}/photos/99999
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "不存在的照片",
"description": "这个照片不存在"
}
### 55. 更新照片 - 权限不足(尝试更新其他用户的照片)
PUT {{baseUrl}}/photos/2
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "试图更新他人照片",
"description": "应该被拒绝"
}
### 56. 删除照片 - 存在的照片
DELETE {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 57. 删除照片 - 不存在的照片
DELETE {{baseUrl}}/photos/99999
Content-Type: application/json
Authorization: Bearer {{token}}
### 58. 删除照片 - 权限不足
DELETE {{baseUrl}}/photos/3
Content-Type: application/json
Authorization: Bearer {{token}}
### ===============================================
### 静态文件访问测试
### ===============================================
### 59. 访问照片原图
GET {{baseUrl}}/../../uploads/photos/test_image_1752197561_34895178.jpg
### 60. 访问照片缩略图
GET {{baseUrl}}/../../uploads/photos/thumbs/test_image_1752197561_34895178_thumb.jpg
### 61. 访问用户头像
GET {{baseUrl}}/../../uploads/avatars/1.jpg
### 62. 访问不存在的文件
GET {{baseUrl}}/../../uploads/photos/nonexistent.jpg
### ===============================================
### 错误处理测试
### ===============================================
### 63. 访问不存在的端点
GET {{baseUrl}}/nonexistent
Content-Type: application/json
### 64. 使用错误的HTTP方法
POST {{baseUrl}}/health
Content-Type: application/json
### 65. 发送无效JSON
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "test",
"password": "test"
// 这是无效的JSON注释
}
### 66. 发送超大请求体
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "test",
"password": "{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}{{$randomWords}}"
}
### 67. 使用无效Token
GET {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer invalid_token_here
### 68. 使用过期Token
GET {{baseUrl}}/users
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
### ===============================================
### 性能测试
### ===============================================
### 69. 大量数据查询
GET {{baseUrl}}/photos?limit=1000
Content-Type: application/json
### 70. 并发请求测试 (运行多次)
GET {{baseUrl}}/health
Content-Type: application/json
### 71. 复杂查询
GET {{baseUrl}}/photos?category_id=1&status=1&keyword=测试&sort=created_at_desc&page=1&limit=50
Content-Type: application/json
### ===============================================
### 中间件测试
### ===============================================
### 72. CORS预检请求
OPTIONS {{baseUrl}}/photos
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
### 73. CORS实际请求
GET {{baseUrl}}/photos
Origin: http://localhost:3000
### 74. 非法来源CORS
GET {{baseUrl}}/photos
Origin: http://malicious-site.com
### 75. 请求ID跟踪
GET {{baseUrl}}/health
X-Request-ID: test-request-123
### ===============================================
### 边界条件测试
### ===============================================
### 76. 空字符串参数
GET {{baseUrl}}/photos?keyword=
Content-Type: application/json
### 77. 负数页码
GET {{baseUrl}}/photos?page=-1
Content-Type: application/json
### 78. 零页码
GET {{baseUrl}}/photos?page=0
Content-Type: application/json
### 79. 超大页码
GET {{baseUrl}}/photos?page=999999
Content-Type: application/json
### 80. 超大limit
GET {{baseUrl}}/photos?limit=10000
Content-Type: application/json
### 81. SQL注入尝试
GET {{baseUrl}}/photos?keyword=' OR 1=1 --
Content-Type: application/json
### 82. XSS尝试
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "<script>alert('xss')</script>",
"description": "XSS测试分类"
}
### ===============================================
### 综合业务流程测试
### ===============================================
### 83. 完整用户注册登录流程
POST {{baseUrl}}/auth/register
Content-Type: application/json
{
"username": "workflow_user",
"email": "workflow@example.com",
"password": "workflow123"
}
### 84. 登录获取Token
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "workflow_user",
"password": "workflow123"
}
### 85. 创建分类
POST {{baseUrl}}/categories
Content-Type: application/json
Authorization: Bearer {{token}}
{
"name": "工作流测试分类",
"description": "用于测试完整工作流的分类"
}
### 86. 上传照片到分类
POST {{baseUrl}}/photos
Authorization: Bearer {{token}}
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="workflow_photo.jpg"
Content-Type: image/jpeg
< ./test_images/workflow_photo.jpg
--boundary
Content-Disposition: form-data; name="title"
工作流测试照片
--boundary
Content-Disposition: form-data; name="description"
这是工作流测试上传的照片
--boundary
Content-Disposition: form-data; name="category_id"
1
--boundary--
### 87. 查看上传的照片
GET {{baseUrl}}/photos?user_id=1&keyword=工作流
Content-Type: application/json
### 88. 更新照片信息
PUT {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"title": "更新的工作流测试照片",
"description": "已更新的照片描述"
}
### 89. 最终验证
GET {{baseUrl}}/photos/1
Content-Type: application/json
### ===============================================
### 清理测试数据 (可选)
### ===============================================
### 90. 删除测试照片
DELETE {{baseUrl}}/photos/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 91. 删除测试分类
DELETE {{baseUrl}}/categories/1
Content-Type: application/json
Authorization: Bearer {{token}}
### 92. 删除测试用户
DELETE {{baseUrl}}/users/2
Content-Type: application/json
Authorization: Bearer {{token}}
### ===============================================
### 测试完成
### ===============================================
### 测试完成 - 健康检查
GET {{baseUrl}}/health
Content-Type: application/json