TL;DR
- k6 — современный, дружественный к разработчикам инструмент для нагрузочного тестирования — пишешь тесты на JavaScript
- Установка через brew/apt/docker, пишешь скрипты, запускаешь из CLI
- Определяй thresholds для критериев pass/fail: время ответа, процент ошибок
- Встроенные метрики: http_req_duration, http_reqs, iterations, vus
- Интеграция с CI/CD, Grafana Cloud, InfluxDB для дашбордов
Идеально для: Разработчиков, DevOps, команд, которые хотят performance-тесты как код Пропусти, если: Нужен GUI для дизайна тестов или экзотические протоколы (используй JMeter)
k6 — это современный open-source инструмент нагрузочного тестирования с более чем 20,000 звёздами на GitHub, созданный для разработчиков и интеграции с CI/CD. По данным State of DevOps Report 2024, 34% организаций теперь рассматривают тестирование производительности как обязательный этап CI-пайплайна. В отличие от XML-конфигураций JMeter, k6 использует JavaScript — тесты читаемы, хранятся в системе контроля версий и проверяются в pull request-ах. Один инстанс k6 может генерировать тысячи виртуальных пользователей с минимальным потреблением памяти. Этот туториал охватывает k6 от установки до продвинутой интеграции с CI/CD: написание скриптов на JavaScript, определение порогов производительности, параметризацию через переменные окружения и визуализацию результатов в Grafana Cloud.
Твоя команда хочет performance-тесты в CI/CD. XML-файлы JMeter сложно ревьюить в PR. Тесты должны запускаться headless в контейнерах.
k6 решает эту проблему. Тесты — это JavaScript-код — читаемый, версионируемый, ревьюируемый. Запускается из CLI, интегрируется со всем, отчёты в реальном времени.
Этот туториал научит k6 от установки до интеграции с CI/CD — всё, что нужно для поиска узких мест производительности.
Что такое k6?
k6 — это open-source инструмент для нагрузочного тестирования, созданный для современных рабочих процессов разработки. Тесты на JavaScript, выполнение на Go (быстро), результаты интегрируются с инструментами наблюдаемости.
Почему k6:
- JavaScript-тесты — используй настоящий язык, не XML
- Developer experience — отличный CLI, понятный вывод
- Высокая производительность — одна машина обрабатывает тысячи VUs
- Нативная CI/CD интеграция — запускается в контейнерах
- Расширяемый — JavaScript APIs, расширения, протоколы
Установка
# macOS
brew install k6
# Ubuntu/Debian
sudo apt update && sudo apt install k6
# Docker
docker run --rm -i grafana/k6 run - <script.js
# Windows
choco install k6
Твой первый k6-тест
Создай script.js:
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
vus: 10, // 10 виртуальных пользователей
duration: '30s', // запуск на 30 секунд
};
export default function () {
const res = http.get('https://test.k6.io');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
Запуск:
k6 run script.js
Концепции k6
Virtual Users (VUs)
VUs — это параллельные исполнители, запускающие твою тестовую функцию.
export const options = {
vus: 100, // одновременные пользователи
duration: '5m', // продолжительность теста
};
Stages (Ramp-up/down)
Постепенное увеличение и уменьшение нагрузки.
export const options = {
stages: [
{ duration: '2m', target: 100 }, // ramp до 100 пользователей
{ duration: '5m', target: 100 }, // держим 100
{ duration: '2m', target: 200 }, // ramp до 200
{ duration: '5m', target: 200 }, // держим 200
{ duration: '2m', target: 0 }, // ramp down
],
};
Thresholds
Определяй критерии pass/fail.
export const options = {
thresholds: {
http_req_duration: ['p(95)<500'], // 95% запросов < 500ms
http_req_failed: ['rate<0.01'], // процент ошибок < 1%
checks: ['rate>0.99'], // 99% проверок проходят
http_reqs: ['rate>100'], // минимум 100 RPS
},
};
HTTP-запросы
GET-запрос
import http from 'k6/http';
export default function () {
// Простой GET
const res = http.get('https://api.example.com/users');
// GET с headers
const res2 = http.get('https://api.example.com/users', {
headers: {
'Authorization': 'Bearer token123',
'Accept': 'application/json',
},
});
}
POST-запрос
import http from 'k6/http';
export default function () {
const payload = JSON.stringify({
name: 'John Doe',
email: 'john@example.com',
});
const params = {
headers: {
'Content-Type': 'application/json',
},
};
const res = http.post('https://api.example.com/users', payload, params);
}
Другие методы
// PUT
http.put(url, payload, params);
// PATCH
http.patch(url, payload, params);
// DELETE
http.del(url, params);
// Batch-запросы (параллельно)
const responses = http.batch([
['GET', 'https://api.example.com/users'],
['GET', 'https://api.example.com/products'],
['GET', 'https://api.example.com/orders'],
]);
Проверки и Assertions
import { check } from 'k6';
export default function () {
const res = http.get('https://api.example.com/users');
check(res, {
'status is 200': (r) => r.status === 200,
'response has users': (r) => r.json().length > 0,
'response time OK': (r) => r.timings.duration < 500,
'content-type is JSON': (r) =>
r.headers['Content-Type'].includes('application/json'),
});
}
Тестовые данные
Переменные окружения
const baseUrl = __ENV.BASE_URL || 'https://test.k6.io';
export default function () {
http.get(`${baseUrl}/api/users`);
}
k6 run -e BASE_URL=https://staging.example.com script.js
JSON-файл
import { SharedArray } from 'k6/data';
const users = new SharedArray('users', function () {
return JSON.parse(open('./data.json'));
});
export default function () {
const user = users[Math.floor(Math.random() * users.length)];
// использовать user.username, user.password
}
CSV-данные
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
import { SharedArray } from 'k6/data';
const csvData = new SharedArray('users', function () {
return papaparse.parse(open('./users.csv'), { header: true }).data;
});
SharedArray гарантирует, что данные загружаются один раз и разделяются между всеми VUs, что экономит память при большом количестве виртуальных пользователей.
Scenarios
Продвинутые паттерны выполнения.
export const options = {
scenarios: {
// Постоянная нагрузка
constant_load: {
executor: 'constant-vus',
vus: 50,
duration: '5m',
},
// Нагрузка с ramp
ramping_load: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 100 },
{ duration: '5m', target: 100 },
{ duration: '2m', target: 0 },
],
},
// Постоянный arrival rate
constant_rate: {
executor: 'constant-arrival-rate',
rate: 100,
timeUnit: '1s',
duration: '5m',
preAllocatedVUs: 50,
},
},
};
Метрики и Output
Встроенные метрики
| Метрика | Описание |
|---|---|
| http_reqs | Общее количество HTTP-запросов |
| http_req_duration | Продолжительность запроса |
| http_req_failed | Процент неудачных запросов |
| iterations | Завершённые итерации |
| vus | Текущие виртуальные пользователи |
| data_received | Полученные данные |
| data_sent | Отправленные данные |
Кастомные метрики
import { Counter, Trend, Rate, Gauge } from 'k6/metrics';
const orderCounter = new Counter('orders_created');
const orderDuration = new Trend('order_duration');
const orderSuccess = new Rate('order_success_rate');
export default function () {
const start = Date.now();
const res = http.post('https://api.example.com/orders', orderPayload);
orderCounter.add(1);
orderDuration.add(Date.now() - start);
orderSuccess.add(res.status === 201);
}
Output в InfluxDB + Grafana
# Output в JSON
k6 run --out json=results.json script.js
# Output в InfluxDB
k6 run --out influxdb=http://localhost:8086/k6 script.js
Интеграция с CI/CD
GitHub Actions
name: Load Test
on:
push:
branches: [main]
jobs:
k6-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run k6 test
uses: grafana/k6-action@v0.3.1
with:
filename: tests/load-test.js
flags: --out json=results.json
- name: Upload results
uses: actions/upload-artifact@v4
with:
name: k6-results
path: results.json
Docker
FROM grafana/k6
COPY ./tests /tests
ENTRYPOINT ["k6", "run", "/tests/script.js"]
docker build -t my-k6-tests .
docker run my-k6-tests
Thresholds в k6 автоматически определяют exit code. Если threshold не пройден, k6 возвращает exit code 99 — CI/CD пайплайн блокирует деплой автоматически, без дополнительных скриптов проверки.
ИИ в k6-тестировании
ИИ-инструменты могут помочь писать и оптимизировать k6-тесты.
Что ИИ делает хорошо:
- Генерация тестовых скриптов из API-спецификаций
- Создание реалистичных тестовых данных
- Предложение значений thresholds
- Объяснение метрик и результатов
Что всё ещё требует людей:
- Понимание архитектуры системы
- Установка реалистичных целей нагрузки
- Интерпретация результатов в контексте
- Отладка проблем производительности
Полезный промпт:
Сгенерируй k6 скрипт для нагрузочного тестирования REST API с эндпоинтами: GET /users, POST /users, GET /users/{id}. Включи stages для ramp-up до 100 VUs, thresholds для p(95) response time менее 500ms и error rate ниже 1%, checks для status codes и валидацию JSON-ответов.
“k6 изменил наш подход к нагрузочному тестированию. Когда тесты — это JavaScript-код, разработчики их пишут и поддерживают. Мы перешли от «кто-то должен запустить нагрузочный тест» к автоматическим проверкам производительности в каждом PR.” — Yuri Kan, Senior QA Lead
References: Документация k6 | Grafana Cloud k6
FAQ
Что такое k6?
k6 — это современный open-source инструмент для нагрузочного тестирования, созданный для разработчиков. Ты пишешь тесты на JavaScript, запускаешь их из командной строки и получаешь детальные метрики производительности. Созданный Grafana Labs, k6 фокусируется на developer experience, интеграции с CI/CD и высокой производительности.
k6 бесплатный?
Да, k6 open-source (k6 OSS) полностью бесплатен. Grafana Cloud k6 предлагает облачное выполнение тестов, облачное хранилище и дополнительные функции с бесплатным и платными тарифами. Для большинства случаев open-source версия предоставляет всё необходимое.
k6 или JMeter — что лучше?
k6 лучше для разработчиков и CI/CD — тесты как код (JavaScript), быстрое выполнение, хорошая интеграция с современными инструментами. JMeter лучше для GUI-дизайна тестов и поддерживает больше протоколов из коробки. k6 обычно легче изучить и поддерживать командам, знакомым с JavaScript.
Может ли k6 тестировать браузерные взаимодействия?
Да, у k6 есть экспериментальный browser module, который позволяет тестировать в реальном браузере с Chromium. Однако сила k6 — в протокольном тестировании (HTTP, WebSocket, gRPC), которое намного эффективнее для нагрузочного тестирования. Используй browser module, когда нужно тестировать страницы с JavaScript-рендерингом или сложные браузерные взаимодействия.
Как запустить k6 в Docker?
Используй официальный образ Grafana k6: docker run --rm -i grafana/k6 run - <script.js. Для локальных скриптов монтируй директорию с тестами: docker run --rm -v $(pwd):/scripts grafana/k6 run /scripts/test.js. Docker — самый простой способ запускать k6 в CI/CD пайплайнах без установки на хост-машину.
Какие метрики k6 отслеживает по умолчанию?
k6 автоматически отслеживает http_reqs (общее количество запросов), http_req_duration (время ответа), http_req_failed (процент ошибок), iterations (завершённые итерации), vus (активные виртуальные пользователи), data_received и data_sent. Можно создавать кастомные метрики с помощью типов Counter, Trend, Rate и Gauge для бизнес-специфичных измерений вроде созданных заказов или процента успешных логинов.
Смотрите также
- JMeter Tutorial - Традиционное GUI-based нагрузочное тестирование
- Gatling Load Testing - Высокопроизводительное тестирование на Scala
- Locust Python Load Testing - Нагрузочное тестирование на Python
- Performance Testing Guide - Основы performance тестирования
- Туториал по API Testing - Полное руководство по тестированию API
- API Testing Архитектура - Тестирование API в микросервисах
- Туториал по автоматизации тестирования - Основы автоматизации
- Selenium Tutorial - Автоматизация браузера
- Cypress Tutorial - E2E тестирование для веб-приложений
- Playwright vs Cypress - Сравнение E2E фреймворков
