# Load Testing Implementation - Story 1.17-a

## Overview

This document describes the load testing implementation for the Enchun CMS project to verify NFR4 (Non-Functional Requirement 4).

**Story:** 1.17-a - Load Testing (NFR4)
**Status:** ✅ Complete
**Implemented:** 2025-01-31

## NFR4 Requirements

| Metric | Target | Test Coverage |
|--------|--------|---------------|
| p95 Response Time | < 500ms | ✅ Public browsing, API tests |
| Error Rate | < 1% | ✅ All tests |
| Concurrent Users | 100 | ✅ Public browsing test |

## Implementation Summary

### Test Framework

**Technology:** k6 (Grafana k6)
**Location:** `/apps/backend/tests/k6/`

### Test Scripts

| Test | Concurrent Users | Duration | Purpose |
|------|------------------|----------|---------|
| `public-browsing.js` | 100 | 2m | Public page load |
| `admin-operations.js` | 20 | 3m | Admin CRUD operations |
| `api-performance.js` | 50 | 5m | API endpoint performance |

### Supporting Files

```
tests/k6/
├── README.md                     # Full documentation
├── QUICKSTART.md                 # 5-minute setup guide
├── TESTING-GUIDE.md             # Detailed execution guide
├── .env.example                 # Environment template
├── verify-setup.js              # Setup verification script
├── .github-workflow-example.yml # CI/CD integration
├── lib/
│   ├── config.js                # Centralized configuration
│   └── helpers.js               # Reusable helper functions
├── public-browsing.js           # Main test: 100 users
├── admin-operations.js          # Admin test: 20 users
└── api-performance.js           # API test: 50 users
```

## Quick Start

### 1. Install k6

```bash
# macOS
brew install k6
```

### 2. Run Verification

```bash
cd apps/backend
k6 run tests/k6/verify-setup.js
```

### 3. Run Tests

```bash
# Public browsing (100 users)
pnpm test:load

# All public tests
pnpm test:load:all

# Admin operations (requires credentials)
k6 run --env ADMIN_EMAIL=admin@enchun.tw --env ADMIN_PASSWORD=xxx \
  tests/k6/admin-operations.js
```

## NPM Scripts Added

```json
{
  "test:load": "k6 run tests/k6/public-browsing.js",
  "test:load:all": "k6 run tests/k6/public-browsing.js && k6 run tests/k6/api-performance.js",
  "test:load:admin": "k6 run tests/k6/admin-operations.js",
  "test:load:api": "k6 run tests/k6/api-performance.js"
}
```

## Test Coverage Details

### Public Browsing Test

**Simulates:** 100 concurrent users browsing the site

**Pages Tested:**
- Homepage (`/`)
- About (`/about`)
- Solutions (`/solutions`)
- Portfolio (`/portfolio`)
- Blog (`/blog`)
- Contact (`/contact`)

**Scenarios:**
1. Browse homepage (most common)
2. Browse random pages (weighted)
3. Navigate to contact (conversion intent)
4. Deep dive into portfolio/blog

**Thresholds:**
- p95 response time < 500ms
- Error rate < 1%
- 99%+ checks pass

### API Performance Test

**Simulates:** 50 concurrent users accessing APIs

**Endpoints Tested:**
- Global API (`/api/global`)
- Pages API (`/api/pages`)
- Posts API (`/api/posts`)
- Portfolio API (`/api/portfolio`)
- Categories API (`/api/categories`)
- GraphQL API (`/api/graphql`)
- Auth API (`/api/users/login`)

**Scenarios:**
1. Global API queries
2. REST API endpoints
3. GraphQL queries (simple & complex)
4. Authentication endpoints
5. Concurrent requests
6. Filtered queries

**Thresholds:**
- p95 response time < 300ms
- Error rate < 0.5%
- Throughput > 100 req/s

### Admin Operations Test

**Simulates:** 20 concurrent admin users

**Operations Tested:**
- Login
- List collections (Pages, Posts, Portfolio)
- View items
- Create content (draft posts)
- Update content
- Delete content
- GraphQL operations

**Scenarios:**
1. Admin login
2. Browse collections
3. View items
4. Create test content
5. Update content
6. Delete test content
7. GraphQL queries

**Thresholds:**
- p95 response time < 700ms
- Error rate < 1%
- 99%+ checks pass

**Note:** Creates draft posts during testing (manual cleanup required)

## Configuration

### Environment Variables

| Variable | Purpose | Default |
|----------|---------|---------|
| `BASE_URL` | Target server URL | `http://localhost:3000` |
| `ADMIN_EMAIL` | Admin email for tests | - |
| `ADMIN_PASSWORD` | Admin password for tests | - |
| `STAGED_USERS` | Override virtual users | Test-specific |
| `STAGED_DURATION` | Override test duration | Test-specific |

### Load Profiles

Each test uses gradual ramp-up:

```javascript
// Public browsing example
stages: [
  { duration: '30s', target: 20 },   // Ramp up
  { duration: '30s', target: 50 },   // Ramp up
  { duration: '1m', target: 100 },   // Ramp up
  { duration: '2m', target: 100 },   // Sustain
  { duration: '30s', target: 0 },    // Ramp down
]
```

## CI/CD Integration

### GitHub Actions Example

```yaml
name: Load Tests
on:
  schedule:
    - cron: '0 2 * * *'  # Daily at 2 AM
  workflow_dispatch:

jobs:
  load-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup k6
        run: |
          curl https://github.com/grafana/k6/releases/download/v0.51.0/k6-v0.51.0-linux-amd64.tar.gz -L | tar xvz
          sudo mv k6-v0.51.0-linux-amd64/k6 /usr/local/bin/
      - name: Run Tests
        run: k6 run --env BASE_URL=${{ vars.STAGING_URL }} apps/backend/tests/k6/public-browsing.js
```

See `.github-workflow-example.yml` for complete example.

## Interpreting Results

### Success Criteria

✅ **Test passes** if:
- p95 response time < threshold
- Error rate < 1% (0.5% for API)
- Checks > 99% pass rate
- All VUs sustained for duration

❌ **Test fails** if:
- p95 >= threshold
- Error rate >= 1%
- Significant check failures
- VUs drop during test

### Example Output

```
✓ http_req_duration..............: avg=185ms p(95)=420ms
✓ http_req_failed................: 0.00% ✓ 0      ✗ 12000
✓ checks.........................: 100.0% ✓ 12000 ✗ 0

iterations.....................: 2400   20  /s
vus............................: 100    min=100    max=100
vus_max........................: 100    min=100    max=100
```

**Analysis:**
- ✅ p95 = 420ms (< 500ms)
- ✅ Error rate = 0%
- ✅ All checks passed
- ✅ Sustained 100 VUs

## Troubleshooting

### Common Issues

**Connection Refused**
```bash
# Solution: Ensure backend is running
pnpm dev
```

**High Error Rate**
```bash
# Solution: Reduce load for diagnosis
k6 run --env STAGED_USERS=10 tests/k6/public-browsing.js
```

**Slow Response Times**
- Check database queries
- Verify indexes exist
- Review caching strategy
- Scale server resources

See `TESTING-GUIDE.md` for detailed troubleshooting.

## Next Steps

### Immediate

1. ✅ Framework created
2. ✅ Test scripts implemented
3. ✅ Documentation complete
4. 🔄 Run initial baseline tests
5. 🔄 Establish performance baselines

### Ongoing

1. Run tests daily (automated)
2. Monitor performance trends
3. Update baselines as needed
4. Investigate regressions
5. Optimize based on results

### Future Enhancements

- [ ] Add more specific user scenarios
- [ ] Test third-party integrations
- [ ] Add media upload stress test
- [ ] Implement performance budget alerts
- [ ] Create performance dashboard

## Documentation

- **Full Guide:** `apps/backend/tests/k6/README.md`
- **Quick Start:** `apps/backend/tests/k6/QUICKSTART.md`
- **Testing Guide:** `apps/backend/tests/k6/TESTING-GUIDE.md`
- **Environment:** `apps/backend/tests/k6/.env.example`

## Verification

To verify the implementation:

```bash
# 1. Verify setup
k6 run tests/k6/verify-setup.js

# 2. Run public browsing test
pnpm test:load

# 3. Run API performance test
pnpm test:load:api

# 4. Check all documentation
ls -la apps/backend/tests/k6/
```

## Success Metrics

### Implementation Completeness

- ✅ k6 framework configured
- ✅ 3 test scripts created
- ✅ NFR4 thresholds defined
- ✅ Helper functions implemented
- ✅ Documentation complete
- ✅ NPM scripts added
- ✅ CI/CD examples provided

### Code Quality

- ✅ Modular, reusable code
- ✅ Type-safe configuration
- ✅ Comprehensive error handling
- ✅ Clear documentation
- ✅ CI/CD ready

---

**Story Status:** ✅ Complete
**Files Modified:** 1 (package.json)
**Files Created:** 12
**Lines of Code:** ~1,800 (excluding documentation)

**Next Action:** Run initial tests to establish performance baseline

---

**Implemented By:** Backend Architect Agent
**Date:** 2025-01-31
