consdata.com
Blog techniczny Blog biznesowy Dział HR
EN
artillery

Czy wiesz, czym jest narzędzie artillery?

author Kamil Dudek
13 lutego 2026

Artillery to oparte o Node.js narzędzie do wykonywania testów wydajnościowych, które może być prostszą alternatywą dla np. Gatlinga. Charakteryzuje się ono prostotą użycia, wspiera różne technologie (np. HTTP API, WebSockety), daje możliwość testowania rozproszonego oraz może być rozszerzane przez pluginy.

Instalacja

Artillery można zainstalować poprzez:

npm install -g artillery@latest

lub używając odpowiedniego obrazu Dockerowego. Same testy pisane są w YAMLu lub w JavaScripcie.

Przykładowy test

Załóżmy, że nasza aplikacja wystawia trzy usługi:

  • GET /get-projects – zwracająca listę projektów
  • GET /get-sprints?project= – zwracająca listę trwających sprintów dla danego projektu
  • POST /add-task – pozwalająca na dodanie zadania do sprintu

Chcemy przetestować dwa scenariusze:

  1. Użytkownik wchodzi na listę projektów, wyświetla listę sprintów dla projektu TEST-PROJECT, a następnie po dwóch sekundach dodaje zadanie do pierwszego sprintu z listy.
  2. Użytkownik dodaje po kolei 10 zadań do losowych dostępnych sprintów.

Dodatkowo zakładamy trzy fazy:

  • pierwsza, rozgrzewkowa - 5 wirtualnych użytkowników na sekundę, zwiększających się do 10 na koniec fazy,
      duration: 60
      arrivalRate: 5
      rampTo: 10
      name: Warm up phase
    
  • druga, stopniowo zwiększająca obciążenie do 50 użytkowników,
      duration: 60
      arrivalRate: 10
      rampTo: 50
      name: Ramp up load
    
  • trzecia testująca duży przypływ użytkowników - 50 użytkowników co sekundę.
      duration: 30
      arrivalRate: 50
      name: Spike phase
    

Konfiguracja testu

W sekcji config tworzymy podstawową konfigurację testu – definiujemy, na jaki adres będą kierowane żądania, fazy testu oraz zmienne, które możemy wykorzystać w ramach scenariuszy. Dodatkowo zdefiniowany jest plugin rozszerzający wyniki oraz procesor – czyli plik zawierający funkcje JavaScript, które mogą być wykorzystane w teście.

config:
  target: http://localhost:8080
  phases: [...]
  plugins:
    metrics-by-endpoint: {}
  processor: "./functions.js"
  variables:
    project: "TEST-PROJECT"

Scenariusze i flow

Sekcja scenarios zawiera definicje scenariuszy testowych. Każdy scenariusz ma określony weight, który decyduje o tym, jak często będzie wybierany przez wirtualnych użytkowników. W ramach flow określone są kroki scenariusza, w których możemy wykorzystywać zmienne zdefiniowane w konfiguracji lub tworzyć je na bieżąco, np. na podstawie odpowiedzi usług.

scenarios:
  # 9 na 10 użytkowników wybierze ten scenariusz
  - name: "Standard scenario - add single task"
    weight: 9
    flow:
      - get:
          url: "/get-projects"
      - get:
          url: "/get-sprints"
          qs:
            project: ""
          capture:
            json: "$.sprints[0].sprintId"
            as: "sprintId"
      - think: 2
      - post:
          url: '/add-task'
          json:
            name: "Example task"
            type: "TECHNICAL"
            sprintId: ""
  # 1 na 10 użytkowników wybierze ten scenariusz
  - name: "Rare scenario - add multiple tasks"
    weight: 1
    flow:
      - get:
          url: "/get-projects"
      - get:
          url: "/get-sprints"
          qs:
            project: ""
          capture:
            json: "$.sprints"
            as: "sprints"
      - think: 2
      - loop:
        - post:
            beforeRequest: "setAddTaskBody"
            url: '/add-task'
        count: 10

Funkcje pomocnicze (processor)

Plik functions.js z funkcjami pomocniczymi:

module.exports = {
  setAddTaskBody
}

function setAddTaskBody(requestParams, context, ee, next) {
  const type = Math.random() < 0.75 ? "BUG" : "TECHNICAL"
  const name = randomString();
  const sprints = context.vars["sprints"];
  const randomSprint = sprints[Math.floor(Math.random() * sprints.length)];

  const task = {
    name,
    type,
    sprintId: randomSprint.sprintId
  }
  requestParams.json = task;
  return next();
}

function randomString() {
  return (Math.random() + 1).toString(36).substring(7);
}

Hooki w Artillery

Artillery pozwala na wykorzystywanie hooków, które są funkcjami JavaScriptowymi zawartymi w pliku będącym procesorem. Wyróżniamy następujące hooki:

  • beforeScenario i afterScenario – przed/po wykonaniu scenariusza przez wirtualnego użytkownika
  • beforeRequest – przed wysłaniem requestu (można ustawić parametry takie jak URL, ciasteczka, nagłówki czy ciało żądania)
  • afterResponse – po otrzymaniu odpowiedzi (np. zdefiniować zmienne na dalsze potrzeby testu)
  • function – funkcja wywoływana w dowolnym miejscu scenariusza

W powyższej implementacji scenariusza wykorzystany został beforeRequest, będący funkcją w której ustawiamy body żądania na podstawie wcześniej zapisanej zmiennej. Funkcja ta przyjmuje cztery parametry:

  • requestParams – obiekt żądania
  • context – kontekst wirtualnego użytkownika; za pośrednictwem context.vars mamy dostęp do wszystkich zdefiniowanych zmiennych
  • ee – event emitter do bezpośredniej komunikacji z Artillery
  • next – obowiązkowy callback, dzięki któremu test jest kontynuowany

Uruchamianie testów

Aby uruchomić taki scenariusz wystarczy użyć komendy:

artillery run scenario.yml

Można zapisać wyniki testu do formatu JSON dodając flagę --output:

artillery run --output results.json scenario.yml

Raportowanie wyników

Plik ten można wykorzystać do wygenerowania raportu HTML za pośrednictwem komendy:

artillery report results.json

Fragment wygenerowanego raportu, przedstawiający czasy odpowiedzi (ich minimalną i maksymalną wartość, a także medianę oraz percentyle 95 i 99) dla wszystkich żądań HTTP wysłanych w ramach scenariuszy:

Fragment raportu wygenerowanego przez Artillery

Podsumowanie

Poniżej pełny przykład pliku testowego YAML oraz procesora JS, zbierający wszystkie elementy opisane powyżej:

config:
  target: http://localhost:8080
  phases:
    - duration: 60
      arrivalRate: 5
      rampTo: 10
      name: Warm up phase
    - duration: 60
      arrivalRate: 10
      rampTo: 50
      name: Ramp up load
    - duration: 30
      arrivalRate: 50
      name: Spike phase
  plugins:
    metrics-by-endpoint: {}
  processor: "./functions.js"
  variables:
    project: "TEST-PROJECT"
scenarios:
  - name: "Standard scenario - add single task"
    weight: 9
    flow:
      - get:
          url: "/get-projects"
      - get:
          url: "/get-sprints"
          qs:
            project: ""
          capture:
            json: "$.sprints[0].sprintId"
            as: "sprintId"
      - think: 2
      - post:
          url: '/add-task'
          json:
            name: "Example task"
            type: "TECHNICAL"
            sprintId: ""
  - name: "Rare scenario - add multiple tasks"
    weight: 1
    flow:
      - get:
          url: "/get-projects"
      - get:
          url: "/get-sprints"
          qs:
            project: ""
          capture:
            json: "$.sprints"
            as: "sprints"
      - think: 2
      - loop:
        - post:
            beforeRequest: "setAddTaskBody"
            url: '/add-task'
        count: 10
module.exports = {
  setAddTaskBody
}

function setAddTaskBody(requestParams, context, ee, next) {
  const type = Math.random() < 0.75 ? "BUG" : "TECHNICAL"
  const name = randomString();
  const sprints = context.vars["sprints"];
  const randomSprint = sprints[Math.floor(Math.random() * sprints.length)];

  const task = {
    name,
    type,
    sprintId: randomSprint.sprintId
  }
  requestParams.json = task;
  return next();
}

function randomString() {
  return (Math.random() + 1).toString(36).substring(7);
}

Artillery to proste i przyjemne narzędzie, które posiada także wiele innych funkcjonalności niewykorzystanych w powyższym przykładzie – można się z nimi zapoznać w dokumentacji. Potencjalnym problemem może być jednak brak wsparcia dla równoległych requestów wywoływanych przez jednego wirtualnego użytkownika – chociaż teoretycznie w kodzie Artillery znaleźć można opcję parallel, to w praktyce nie do końca ona działa. W takiej sytuacji obejściem może być np. odpowiednie zdefiniowanie dodatkowych scenariuszy, które zasymulują takie współbieżne żądania.

Dokumentacja

  • Artillery – oficjalna dokumentacja
Najnowsze wpisy

  • Czy wiesz, czym jest narzędzie artillery?
  • Czy wiesz, że TypeScript ma typ bezpieczniejszy niż Any?
  • Czy wiesz, że za pomocą operatora shareReplay możesz cache'ować dane z observable?
Dołącz do nas

  • SENIOR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 14 900 - 20 590 PLN brutto
    B2B 19 680 - 27 220 PLN netto
  • REGULAR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 11 300 - 15 900 PLN brutto
    B2B 14 950 - 21 000 PLN netto
  • ZOBACZ WSZYSTKIE OGŁOSZENIA

newsletter

techniczny

Zapisz się

Podobne wpisy

post-image
artillery

Czy wiesz, czym jest narzędzie artillery?

author
Kamil Dudek 13 lut 2026
post-image
typescript

Czy wiesz, że TypeScript ma typ bezpieczniejszy niż Any?

author
Wojciech Stolarski 3 gru 2025
post-image
rxjs

Czy wiesz, że za pomocą operatora shareReplay możesz cache'ować dane z observable?

author
Piotr Tatarski 17 lis 2025
Dołącz do nas

  • SENIOR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 14 900 - 20 590 PLN brutto
    B2B 19 680 - 27 220 PLN netto
  • REGULAR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 11 300 - 15 900 PLN brutto
    B2B 14 950 - 21 000 PLN netto
  • ZOBACZ WSZYSTKIE OGŁOSZENIA

Zapisz się na

newsletter

techniczny

consdata.com
  • Kontakt

    • sales@consdata.com
    • +48 61 41 51 000

  • Biuro

    • K9Office
      Krysiewicza 9/14
      61-825 Poznań
      Polska

  • Rozwiązania

    • Eximee
    • Kouncil
  • Blog Dołącz do nas
Copyright © 2024 Consdata. All rights reserved. Privacy Policy & Cookies
Chcemy używać plików cookie oraz skryptów podmiotów trzecich do polepszania funkcjonowania tej strony Zgadzam się