Skip to main content
Back to course
k6: нагрузочное тестирование как система
8 / 1747%

Продвинутая разработка сценариев на JavaScript в k6

25 минут

Модульность и архитектура директории

  • Организуйте проект как код:
/tests
  /scenarios
    reader.js
    buyer.js
    admin.js
  /lib
    auth.js
    http-client.js
  /data
    users.json
    products.json
  main.js
  k6.config.js
  • Сценарии — в /scenarios, общие утилиты — в /lib, фикстуры — в /data. Главный файл только склеивает сценарии, опции и метрики.
  • Общие константы и данные — в config.js и SharedArray (после сериализации!).
// flows/buyer.js
import http from "k6/http";
import { check, sleep } from "k6";
 
export function buyer(baseUrl, user) {
  const login = http.post(`${baseUrl}/api/login`, user);
  check(login, { login: (r) => r.status === 200 });
  const add = http.post(`${baseUrl}/api/cart`, { sku: "SKU-1", qty: 1 });
  check(add, { cart: (r) => r.status === 200 });
  sleep(1 + Math.random());
}
// main.js
import { SharedArray } from "k6/data";
import { buyer } from "./flows/buyer.js";
 
const users = new SharedArray("users", () =>
  JSON.parse(open("./fixtures/users.json"))
);
export default function () {
  const user = users[__ITER % users.length];
  buyer(__ENV.BASE_URL, user);
}

Внешние зависимости

  • Используйте open() + bundler (esbuild/webpack) для локальных JS/JSON. K6 не поддерживает dynamic import с сети.
  • Для хелперов на TypeScript — собирайте в JS перед запуском.
  • Проверяйте размер бандла: лишние библиотеки (lodash целиком) увеличивают потребление памяти VU.

Синхронный API и отсутствие async/await

  • k6 исполняет JS синхронно; «параллельность» достигается через VU и http.batch().
  • async/await нет: промисы не ждутся. Параллельность — через batch или несколько VU.
  • sleep() — моделирует think time, а не «зло». Но избегайте long sleep внутри VU, если цель — удерживать RPS; лучше больше VU и небольшой sleep (реалистичный тайминг).
  • Никогда не держите долгие синхронные вычисления внутри VU (JSON.stringify мегаструктур) — это съест CPU генератора. Тяжелые препроцессы вынесите в setup.

Отладка и трассировка

  • console.log с префиксами VU/ITER: console.log('[vu=' + __VU + ' iter=' + __ITER + ']', res.status);.
  • --http-debug=full или --http-debug=tracing для сети (только на малом VU).
  • Структурированные логи: создайте объект с vu, iter, status и передайте в JSON.stringify() → потом парс в Loki/ELK.
  • Локально: уменьшайте vus до 1–2 и включайте throw в checks (handleSummary может выводить детали).
  • Для сложных сценариев добавляйте флаги __ENV.DEBUG и условные логи.

Работа с данными

  • SharedArray загружается один раз в init-контексте — избегайте обращения к файлам внутри VU.
  • Генерация уникальных id: Date.now() + '-' + __VU + '-' + __ITER; пулы данных — через циклы по SharedArray.
  • Очистка: teardown, отдельные cleanup-скрипты, метки test-run-id на сущностях для массового удаления.

Классы и сложные структуры

  • Можно использовать классы для моделей, но держите их сериализуемыми:
class Cart {
  constructor(baseUrl) {
    this.baseUrl = baseUrl;
  }
  add(sku, qty = 1) {
    return http.post(`${this.baseUrl}/api/cart`, { sku, qty });
  }
}
export default function () {
  const cart = new Cart(__ENV.BASE_URL);
  const res = cart.add("SKU-1");
  check(res, { added: (r) => r.status === 200 });
}
  • Избегайте хранения больших массивов в свойствах экземпляров — каждая VU копирует их.

Инструменты качества

  • ESLint/Prettier для тестов — уменьшает количество «битых» сценариев.
  • TypeScript типы из k6 для автодополнения (npm i -D @types/k6).
  • Юнит-тесты утилит (функции построения данных) — можно гонять vitest/jest отдельно от k6.

✅ Чек-лист завершения урока

После этого урока вы должны уметь:

Модульная архитектура:

  • Организовать тесты в папки: /scenarios, /lib, /data
  • Вынести общие функции в /lib (auth.js, http-client.js)
  • Создать переиспользуемые сценарии в /scenarios
  • Главный файл (main.js) только склеивает сценарии и опции

Работа с данными:

  • Использовать SharedArray для загрузки данных один раз
  • Знать, что open() работает только в init-контексте
  • Избегать обращений к файлам внутри VU-кода

Особенности JavaScript в k6:

  • Понимать, что нет async/await — только синхронный код
  • Использовать http.batch() для параллельных запросов в VU
  • Знать, что sleep() — это нормально, а не зло
  • Избегать тяжелых вычислений в VU (вынести в setup)

Отладка:

  • Использовать console.log с префиксами VU/ITER
  • Знать флаг --http-debug=full для сетевой диагностики
  • Уменьшать VU до 1-2 для локальной отладки
  • Добавлять условные логи через __ENV.DEBUG

Качество кода:

  • Использовать классы для моделей (Cart, User, etc.)
  • Настроить ESLint/Prettier для тестов
  • Добавить TypeScript типы для автодополнения (@types/k6)

Практическое задание:

  • Рефакторите ваши тесты в модульную структуру
  • Вынесите общие функции (login, addToCart) в /lib
  • Создайте SharedArray для users.json и products.json
  • Убедитесь, что тесты запускаются без изменения результатов

Если чек-лист пройден — переходите к уроку 09: привяжем метрики и thresholds к реальным SLO.

Продвинутая разработка сценариев на JavaScript в k6 — k6: нагрузочное тестирование как система — Potapov.me