Розроблення нагрузочних тестів для сайтів (Artillery)
Artillery — Node.js-інструмент нагрузочного тестування з YAML/JSON-конфігурацією. Підтримує HTTP та WebSocket, легко інтегрується в CI/CD, має розширення для користувацьких сценаріїв на JS.
Встановлення
npm install -g artillery
Базовий сценарій
# tests/load/basic.yml
config:
target: "https://staging.example.com"
phases:
- duration: 60
arrivalRate: 5 # 5 нових користувачів на секунду
name: Warm up
- duration: 120
arrivalRate: 20
name: Ramp up load
- duration: 300
arrivalRate: 50
name: Sustained load
- duration: 60
arrivalRate: 100
name: Stress test
defaults:
headers:
Accept: "application/json"
Content-Type: "application/json"
ensure:
p99: 1000 # 99-й перцентиль < 1000мс
p95: 500
maxErrorRate: 1 # менше 1% помилок
scenarios:
- name: Browse catalog
weight: 60 # 60% трафіку
flow:
- get:
url: "/api/products"
expect:
- statusCode: 200
- hasProperty: "data"
- think: 2
- get:
url: "/api/products/{{ $randomNumber(1, 100) }}"
- name: Search
weight: 30
flow:
- get:
url: "/api/search?q={{ $randomString() }}"
expect:
- statusCode: [200, 404]
- name: Contact form
weight: 10
flow:
- post:
url: "/api/contact"
json:
name: "Test User"
email: "[email protected]"
message: "Load test message"
expect:
- statusCode: 201
Сценарій з авторизацією
# tests/load/authenticated.yml
config:
target: "https://staging.example.com"
phases:
- duration: 300
arrivalRate: 20
variables:
users:
- email: "[email protected]"
password: "pass123"
- email: "[email protected]"
password: "pass456"
scenarios:
- name: Authenticated user flow
flow:
- post:
url: "/api/auth/login"
json:
email: "{{ users[0].email }}"
password: "{{ users[0].password }}"
capture:
- json: "$.access_token"
as: "token"
expect:
- statusCode: 200
- get:
url: "/api/user/profile"
headers:
Authorization: "Bearer {{ token }}"
expect:
- statusCode: 200
- post:
url: "/api/orders"
headers:
Authorization: "Bearer {{ token }}"
json:
product_id: 1
quantity: 1
expect:
- statusCode: 201
capture:
- json: "$.id"
as: "orderId"
- get:
url: "/api/orders/{{ orderId }}"
headers:
Authorization: "Bearer {{ token }}"
expect:
- statusCode: 200
Користувацький JS-процесор
# tests/load/custom.yml
config:
processor: "./processor.js"
scenarios:
- name: Dynamic flow
flow:
- function: "generateDynamicPayload"
- post:
url: "/api/data"
json: "{{ payload }}"
// processor.js
module.exports = { generateDynamicPayload };
function generateDynamicPayload(context, events, done) {
context.vars.payload = {
id: Math.floor(Math.random() * 10000),
timestamp: new Date().toISOString(),
data: Array.from({ length: 10 }, (_, i) => ({ key: `item_${i}`, value: Math.random() })),
};
return done();
}
Запуск та звіти
# Базовий запуск
artillery run tests/load/basic.yml
# JSON-звіт
artillery run --output report.json tests/load/basic.yml
artillery report report.json # генерує HTML
# Запуск зі змінними окруження
artillery run \
--target https://staging.example.com \
--overrides '{"config": {"phases": [{"duration": 60, "arrivalRate": 10}]}}' \
tests/load/basic.yml
GitHub Actions
- name: Load Test
run: |
artillery run --output results.json tests/load/basic.yml
artillery report --output load-report.html results.json
- name: Check SLA
run: |
ERRORS=$(cat results.json | jq '.aggregate.counters["http.codes.5xx"] // 0')
P99=$(cat results.json | jq '.aggregate.latency.p99')
if [ "$ERRORS" -gt "10" ] || [ "$(echo "$P99 > 2000" | bc)" = "1" ]; then
echo "Load test failed: too many errors or high latency"
exit 1
fi
Строк реалізації
Написання 3–5 нагрузочних сценаріїв з Artillery: 2–3 дня.







