test: add comprehensive test suite for server
- Add load testing with Artillery (smoke, standard, peak, stress) - Add functional tests: voting, lottery, admin (18 tests) - Add fault tolerance tests (14 tests) - Add network tests for WebSocket (7 tests) - Add compatibility tests (15 tests) - Add security tests: anti-fraud, auth, data integrity (10 tests) - Fix optional callback handling in socket handlers - Total: 64 test cases, all passing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
184
packages/server/load-test/vote-load-test.yaml
Normal file
184
packages/server/load-test/vote-load-test.yaml
Normal file
@@ -0,0 +1,184 @@
|
||||
# ============================================================================
|
||||
# 年会互动大屏系统 - 投票压力测试配置 (100人场景)
|
||||
# ============================================================================
|
||||
#
|
||||
# 运行方式:
|
||||
# pnpm test:load # 标准测试 (30并发)
|
||||
# pnpm test:load:smoke # 冒烟测试 (5并发, 10秒)
|
||||
# pnpm test:load:peak # 峰值测试 (80并发)
|
||||
# pnpm test:load:stress # 压力测试 (120并发)
|
||||
#
|
||||
# ============================================================================
|
||||
|
||||
config:
|
||||
target: "http://localhost:3000"
|
||||
|
||||
# 性能阈值
|
||||
ensure:
|
||||
p95: 500
|
||||
maxErrorRate: 1
|
||||
|
||||
# Socket.IO 配置
|
||||
socketio:
|
||||
transports: ["websocket"]
|
||||
path: "/socket.io"
|
||||
|
||||
# 默认 phases (被环境配置覆盖)
|
||||
phases:
|
||||
- duration: 1
|
||||
arrivalRate: 1
|
||||
|
||||
# 环境变量
|
||||
variables:
|
||||
programIds:
|
||||
- "program_1"
|
||||
- "program_2"
|
||||
- "program_3"
|
||||
- "program_4"
|
||||
- "program_5"
|
||||
- "program_6"
|
||||
- "program_7"
|
||||
ticketTypes:
|
||||
- "creative"
|
||||
- "visual"
|
||||
- "atmosphere"
|
||||
- "performance"
|
||||
- "teamwork"
|
||||
- "popularity"
|
||||
- "potential"
|
||||
|
||||
# 处理器脚本
|
||||
processor: "./vote-processor.cjs"
|
||||
|
||||
# 环境配置
|
||||
environments:
|
||||
# 冒烟测试 - 快速验证 (10秒, 5并发)
|
||||
smoke:
|
||||
target: "http://localhost:3000"
|
||||
phases:
|
||||
- name: "冒烟测试"
|
||||
duration: 10
|
||||
arrivalRate: 5
|
||||
|
||||
# 标准测试 - 正常负载 (30秒, 30并发)
|
||||
standard:
|
||||
target: "http://localhost:3000"
|
||||
phases:
|
||||
- name: "预热"
|
||||
duration: 5
|
||||
arrivalRate: 5
|
||||
- name: "正常负载"
|
||||
duration: 20
|
||||
arrivalRate: 30
|
||||
- name: "冷却"
|
||||
duration: 5
|
||||
arrivalRate: 5
|
||||
|
||||
# 峰值测试 - 投票开始瞬间 (80并发)
|
||||
peak:
|
||||
target: "http://localhost:3000"
|
||||
phases:
|
||||
- name: "预热"
|
||||
duration: 3
|
||||
arrivalRate: 10
|
||||
- name: "峰值爬升"
|
||||
duration: 5
|
||||
arrivalRate: 20
|
||||
rampTo: 80
|
||||
- name: "峰值维持"
|
||||
duration: 15
|
||||
arrivalRate: 80
|
||||
- name: "冷却"
|
||||
duration: 5
|
||||
arrivalRate: 10
|
||||
|
||||
# 压力测试 - 1.5倍余量 (120并发)
|
||||
stress:
|
||||
target: "http://localhost:3000"
|
||||
phases:
|
||||
- name: "预热"
|
||||
duration: 5
|
||||
arrivalRate: 20
|
||||
- name: "压力爬升"
|
||||
duration: 10
|
||||
arrivalRate: 40
|
||||
rampTo: 120
|
||||
- name: "压力维持"
|
||||
duration: 15
|
||||
arrivalRate: 120
|
||||
- name: "冷却"
|
||||
duration: 5
|
||||
arrivalRate: 20
|
||||
|
||||
# ============================================================================
|
||||
# 测试场景定义
|
||||
# ============================================================================
|
||||
|
||||
scenarios:
|
||||
# 场景 1: 完整投票流程 (权重70%)
|
||||
- name: "完整投票流程"
|
||||
weight: 7
|
||||
engine: socketio
|
||||
flow:
|
||||
- function: "generateUserId"
|
||||
- emit:
|
||||
channel: "connection:join"
|
||||
data:
|
||||
userId: "{{ userId }}"
|
||||
userName: "压测用户-{{ userId }}"
|
||||
role: "user"
|
||||
department: "测试部门"
|
||||
- think: 0.5
|
||||
- loop:
|
||||
- function: "selectRandomProgram"
|
||||
- function: "selectRandomTicketType"
|
||||
- emit:
|
||||
channel: "vote:submit"
|
||||
data:
|
||||
candidateId: "{{ selectedProgram }}"
|
||||
category: "{{ selectedTicket }}"
|
||||
localId: "{{ $uuid }}"
|
||||
- think: 0.3
|
||||
count: 5
|
||||
- think: 1
|
||||
|
||||
# 场景 2: 快速连投 (权重20%)
|
||||
- name: "快速连投压力"
|
||||
weight: 2
|
||||
engine: socketio
|
||||
flow:
|
||||
- function: "generateUserId"
|
||||
- emit:
|
||||
channel: "connection:join"
|
||||
data:
|
||||
userId: "{{ userId }}"
|
||||
userName: "速投用户-{{ userId }}"
|
||||
role: "user"
|
||||
department: "压力测试"
|
||||
- loop:
|
||||
- function: "selectRandomProgram"
|
||||
- function: "selectRandomTicketType"
|
||||
- emit:
|
||||
channel: "vote:submit"
|
||||
data:
|
||||
candidateId: "{{ selectedProgram }}"
|
||||
category: "{{ selectedTicket }}"
|
||||
localId: "{{ $uuid }}"
|
||||
- think: 0.1
|
||||
count: 7
|
||||
- think: 0.5
|
||||
|
||||
# 场景 3: 观望用户 (权重10%)
|
||||
- name: "观望用户"
|
||||
weight: 1
|
||||
engine: socketio
|
||||
flow:
|
||||
- function: "generateUserId"
|
||||
- emit:
|
||||
channel: "connection:join"
|
||||
data:
|
||||
userId: "{{ userId }}"
|
||||
userName: "观望用户-{{ userId }}"
|
||||
role: "user"
|
||||
department: "观望组"
|
||||
- think: 5
|
||||
Reference in New Issue
Block a user