Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,49 @@ jobs:
path: dist/
retention-days: 1

load-test:
name: Load Testing
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install k6
run: |
sudo apt-get update
sudo apt-get install -y gnupg2 software-properties-common
sudo wget -q -O - https://dl.k6.io/key.gpg | sudo apt-key add -
echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install -y k6

- name: Start API in background
run: |
npm run start &
sleep 10

- name: Run load tests
run: npm run loadtest:ci
env:
API_URL: http://localhost:3000
NODE_ENV: test

- name: Upload k6 results
uses: actions/upload-artifact@v4
with:
name: k6-results
path: artifacts/k6-results.json

deploy-staging:
name: Deploy to Staging
needs: [build, test-integration, test-e2e, test-security]
Expand Down
44 changes: 44 additions & 0 deletions docs/LOAD_TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Load Testing Guide

This repository now includes a dedicated load testing suite to satisfy #140.

## Tools
- k6 (https://k6.io)

## Location
- `loadtests/propchain-loadtest.js`

## Running locally
1. Install dependencies:
```bash
npm ci
npm install --save-dev k6
```
2. Set env vars:
```bash
export API_URL=http://localhost:3000
export TEST_USER_EMAIL=loadtest@propchain.local
export TEST_USER_PASSWORD=Password123!
```
3. Start the backend in a separate terminal:
```bash
npm run start
```
4. Run load test:
```bash
npm run loadtest
```

## CI integration
- Workflow: `.github/workflows/ci.yml`
- Job: `load-test`
- Command: `npm run loadtest:ci`
- Results are saved as artifact `k6-results` in JSON format.

## Performance criteria
- http_req_failed: < 1%
- 95th percentile response time: < 600ms

## To add scenarios
- Edit `loadtests/propchain-loadtest.js` with more groups/endpoints.
- Add custom thresholds for endpoint-level behavior.
62 changes: 62 additions & 0 deletions loadtests/propchain-loadtest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import http from 'k6/http';
import { check, group, sleep } from 'k6';

export const options = {
vus: Number(__ENV.LOAD_VUS || 40),
duration: __ENV.LOAD_DURATION || '3m',
thresholds: {
http_req_failed: ['rate<0.01'],
http_req_duration: ['p(95)<600'],
},
};

const API_URL = __ENV.API_URL || 'http://localhost:3000';
const TEST_EMAIL = __ENV.TEST_USER_EMAIL || 'loadtest@propchain.local';
const TEST_PASSWORD = __ENV.TEST_USER_PASSWORD || 'Password123!';

function login() {
const payload = JSON.stringify({
email: TEST_EMAIL,
password: TEST_PASSWORD,
});

const headers = {
'Content-Type': 'application/json',
};

const res = http.post(`${API_URL}/auth/login`, payload, { headers });

check(res, {
'login status is 200': (r) => r.status === 200,
'login returns access token': (r) => r.json('accessToken') !== undefined,
});

return res.json('accessToken');
}

export default () => {
group('Auth + Basic API traffic', () => {
const token = login();
const authHeaders = {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
};

const props = http.get(`${API_URL}/properties`, { headers: authHeaders });
check(props, {
'properties status is 200': (r) => r.status === 200,
});

const docs = http.get(`${API_URL}/documents`, { headers: authHeaders });
check(docs, {
'documents status is 200': (r) => r.status === 200,
});

const health = http.get(`${API_URL}/health`);
check(health, {
'health status is 200': (r) => r.status === 200,
});

sleep(1);
});
};
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
"db:backup": "bash scripts/backup.sh",
"db:restore": "bash scripts/restore.sh",
"db:benchmark": "ts-node test/database/performance.benchmark.ts",
"loadtest": "npx k6 run loadtests/propchain-loadtest.js",
"loadtest:ci": "npx k6 run --out json=artifacts/k6-results.json loadtests/propchain-loadtest.js",
"docs:generate": "typedoc --skipErrorChecking"
},
"dependencies": {
Expand Down
Loading