Files
website-enchun-mgr/apps/backend/tests/k6/README.md
pkupuk 7fd73e0e3d Implement Sprint 1 stories: collections, RBAC, audit logging, load testing
Complete 6 Sprint 1 stories for Epic 1 web migration infrastructure.

Portfolio Collection:
- Add 7 fields: title, slug, url, image, description, websiteType, tags
- Configure R2 storage and authenticated access control

Categories Collection:
- Add nameEn, order, textColor, backgroundColor fields
- Add color picker UI configuration

Posts Collection:
- Add excerpt with 200 char limit and ogImage for social sharing
- Add showInFooter checkbox and status select (draft/review/published)

Role-Based Access Control:
- Add role field to Users collection (admin/editor)
- Create adminOnly and authenticated access functions
- Apply access rules to Portfolio, Categories, Posts, Users collections

Audit Logging System (NFR9):
- Create Audit collection with timestamps for 90-day retention
- Add auditLogger utility for login/logout/content change tracking
- Add auditChange and auditGlobalChange hooks to all collections and globals
- Add cleanupAuditLogs job with 90-day retention policy

Load Testing Framework (NFR4):
- Add k6 load testing with 3 scripts: public-browsing, admin-operations, api-performance
- Configure targets: p95 < 500ms, error rate < 1%, 100 concurrent users
- Add verification script and comprehensive documentation

Other Changes:
- Remove unused Form blocks
- Add Header/Footer audit hooks
- Regenerate Payload TypeScript types
2026-01-31 17:20:35 +08:00

295 lines
6.9 KiB
Markdown

# K6 Load Testing Framework
## Overview
This directory contains load testing scripts for the Enchun CMS backend using k6. The tests are designed to validate the non-functional requirement NFR4:
- **Target:** p95 response time < 500ms
- **Error rate:** < 1%
- **Concurrent users:** 100
## Prerequisites
1. **Install k6:**
```bash
# macOS
brew install k6
# Linux
sudo apt-get install k6
# Windows (using Chocolatey)
choco install k6
```
2. **Set up environment:**
```bash
cp .env.example .env.k6
# Edit .env.k6 with your test environment credentials
```
## Test Scripts
### 1. Public Browsing Test (`public-browsing.js`)
Simulates 100 concurrent users browsing public pages:
- Homepage
- About page
- Solutions page
- Portfolio list
- Blog list
- Contact page
**Run:**
```bash
k6 run --env BASE_URL=http://localhost:3000 tests/k6/public-browsing.js
```
**Expected Results:**
- p95 response time < 500ms
- Error rate < 1%
- 100 concurrent users sustained for 2 minutes
### 2. Admin Operations Test (`admin-operations.js`)
Simulates 20 concurrent admin users performing:
- Login
- List pages/posts
- Create/edit content
- Delete content
**Run:**
```bash
k6 run --env BASE_URL=http://localhost:3000 \
--env ADMIN_EMAIL=admin@example.com \
--env ADMIN_PASSWORD=password123 \
tests/k6/admin-operations.js
```
**Expected Results:**
- p95 response time < 500ms
- Error rate < 1%
- 20 concurrent users sustained for 3 minutes
### 3. API Performance Test (`api-performance.js`)
Tests specific API endpoints:
- GraphQL API queries
- REST API endpoints
- Global API endpoint
**Run:**
```bash
k6 run --env BASE_URL=http://localhost:3000 tests/k6/api-performance.js
```
**Expected Results:**
- p95 response time < 300ms (faster for API)
- Error rate < 0.5%
- Throughput > 100 requests/second
## Configuration
### Environment Variables
| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `BASE_URL` | Target server URL | `http://localhost:3000` | Yes |
| `ADMIN_EMAIL` | Admin user email | - | For admin tests |
| `ADMIN_PASSWORD` | Admin user password | - | For admin tests |
| `VUS` | Number of virtual users | Varies per test | No |
| `DURATION` | Test duration | Varies per test | No |
### Load Profiles
Each test uses different load profiles:
| Test | Virtual Users | Duration | Ramp Up |
|------|--------------|----------|---------|
| Public Browsing | 100 | 2m | 30s |
| Admin Operations | 20 | 3m | 30s |
| API Performance | 50 | 5m | 1m |
## Running Tests
### Run Single Test
```bash
# Basic run
k6 run tests/k6/public-browsing.js
# With custom environment
k6 run --env BASE_URL=https://staging.enchun.tw tests/k6/public-browsing.js
# With custom stages
k6 run --env STAGED_USERS=200 --env STAGED_DURATION=10m tests/k6/public-browsing.js
```
### Run All Tests
```bash
# Using the npm script
pnpm test:load
# Or manually
k6 run tests/k6/public-browsing.js
k6 run tests/k6/admin-operations.js
k6 run tests/k6/api-performance.js
```
### Run with Output Options
```bash
# Generate JSON report
k6 run --out json=results.json tests/k6/public-browsing.js
# Generate HTML report (requires k6-reporter)
k6 run --out json=results.json tests/k6/public-browsing.js
k6-reporter results.json --output results.html
```
## Interpreting Results
### Key Metrics
1. **Response Time (p95):** 95th percentile response time
- ✅ Pass: < 500ms
- ❌ Fail: >= 500ms
2. **Error Rate:** Percentage of failed requests
- ✅ Pass: < 1%
- ❌ Fail: >= 1%
3. **Throughput:** Requests per second
- ✅ Pass: > 100 req/s for API, > 50 req/s for pages
- ❌ Fail: Below threshold
4. **Virtual Users (VUs):** Active concurrent users
- Should sustain target VUs for the full duration
### Example Output
```
✓ Status is 200
✓ Response time < 500ms
✓ Page content loaded
checks.........................: 100.0% ✓ 12000 ✗ 0
data_received..................: 15 MB 125 kB/s
data_sent......................: 2.1 MB 18 kB/s
http_req_blocked...............: avg=1.2ms min=0.5µs med=1µs max=125ms
http_req_connecting............: avg=500µs min=0s med=0s max=45ms
http_req_duration..............: avg=185.3ms min=45ms med=150ms max=850ms p(95)=420ms
http_req_failed................: 0.00% ✓ 0 ✗ 12000
http_req_receiving.............: avg=15ms min=10µs med=50µs max=250ms
http_req_sending...............: avg=50µs min=5µs med=20µs max=5ms
http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s
http_req_waiting...............: avg=170ms min=40ms med=140ms max=800ms
http_reqs......................: 12000 100 req/s
iteration_duration.............: avg=5.2s min=1.2s med=5s max=12s
iterations.....................: 2400 20 /s
vus............................: 100 min=100 max=100
vus_max........................: 100 min=100 max=100
```
## CI/CD Integration
### GitHub Actions
```yaml
name: Load Tests
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
workflow_dispatch:
jobs:
k6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: grafana/k6-action@v0.3.1
with:
filename: tests/k6/public-browsing.js
env:
BASE_URL: ${{ secrets.STAGING_URL }}
```
## Troubleshooting
### Connection Refused
**Error:** `connect attempt failed`
**Solution:**
- Ensure the backend server is running
- Check `BASE_URL` is correct
- Verify firewall settings
### High Error Rate
**Error:** `http_req_failed > 1%`
**Possible Causes:**
1. Server overload (reduce VUs)
2. Database connection issues
3. Authentication failures
4. Network issues
**Debug:**
```bash
# Run with fewer users
k6 run --env STAGED_USERS=10 tests/k6/public-browsing.js
# Check server logs
pnpm dev
# In another terminal, watch logs while tests run
```
### Slow Response Times
**Error:** `p(95) >= 500ms`
**Possible Causes:**
1. Unoptimized database queries
2. Missing indexes
3. Large payloads
4. Server resource constraints
**Next Steps:**
1. Review database queries
2. Check caching strategies
3. Optimize images/assets
4. Scale server resources
## Performance Baseline
Initial baseline (to be established):
| Test | p95 (ms) | Error Rate | Throughput |
|------|----------|------------|------------|
| Public Browsing | TBD | TBD | TBD |
| Admin Operations | TBD | TBD | TBD |
| API Performance | TBD | TBD | TBD |
Update this table after first test run to establish baseline.
## Resources
- [k6 Documentation](https://k6.io/docs/)
- [k6 Metrics](https://k6.io/docs/using-k6/metrics/)
- [Payload CMS Performance](https://payloadcms.com/docs/admin/configuration)
- [Web Vitals](https://web.dev/vitals/)
## Maintenance
- Review and update test scenarios quarterly
- Adjust load profiles based on real traffic patterns
- Update thresholds based on business requirements
- Add new tests for new features
---
**Last Updated:** 2025-01-31
**Owner:** QA Team