Testy obciążenia, stresu i benchmarków
Testowanie wydajności mierzy, jak system zachowuje się pod obciążeniem: k6 i Artillery symulują realistyczny ruch, zwiększają liczbę wirtualnych użytkowników do punktu załamania i oblewają przebieg na jawnych progach. AI generuje skrypty, czyta podsumowanie razem z logiem wolnych zapytań, by uszeregować wąskie gardła, i wpina bramkę regresji w CI.
Twoje API obsługuje 500 zapytań na sekundę na stagingu i wszyscy świętują. Potem przychodzi Black Friday, ruch skacze do 3000 rps, a pula połączeń z bazą danych wyczerpuje się w ciągu minut. Latencja p95 skacze ze 120 ms do 4 s, wykres czasu odpowiedzi wygląda jak kij hokejowy i nikt nie potrafi wskazać zmiany, która to spowodowała.
Potrzebujesz testu obciążenia, który odtworzy ten skok, odczytu, która warstwa nasyca się jako pierwsza, oraz bramki regresji w CI, żeby kolejny deploy nie zaskoczył cię o 21:00. Ten przewodnik prowadzi tę pętlę z pomocą AI: wygeneruj realistyczny skrypt, uruchom go, daj modelowi przeczytać wynik i log wolnych zapytań, a potem wepnij bramkę progową do pipeline’u. Te same prompty działają w Cursorze, Claude Code i Codeksie — różni się tylko sposób uruchamiania każdego narzędzia.
Co daje ten przepływ pracy testowania wydajności
Dział zatytułowany „Co daje ten przepływ pracy testowania wydajności”- Oficjalny serwer MCP k6 (
grafana/mcp-k6) wpięty we wszystkie trzy narzędzia, plusk6 x agent initdo bootstrapu jedną komendą - Gotowe prompty generujące uruchamialne skrypty k6: narastanie typu flash sale, test stresu per endpoint znajdujący punkt załamania oraz smoke test poniżej 60 sekund
- Dwa prompty analityczne — jeden czyta tabelę krzywej obciążenia, drugi podsumowanie k6 wraz z logiem wolnych zapytań Postgresa — i produkuje uszeregowaną listę wąskich gardeł „najpierw najważniejsze”
- Prompt Playwright + Lighthouse, który mierzy Core Web Vitals (LCP, INP, CLS) pod równoległym obciążeniem
- Benchmarki bazy danych porównujące zapytanie z indeksem i bez niego, przy produkcyjnej liczbie wierszy
- Dwie bramki CI wyłapujące różne regresje: progi bezwzględne przez kody wyjścia
k6 runoraz porównanie z bazą odniesienia oblewające PR przy zjeździe p95 o 20% - Tryby awarii, które sprawiają, że liczby z testów obciążenia kłamią — i jak je wyłapać, zanim zaufasz dashboardowi
Wpięcie narzędzi
Dział zatytułowany „Wpięcie narzędzi”Na wierzchu warto zainstalować oficjalny serwer MCP k6 od Grafany (grafana/mcp-k6). Pozwala on agentowi walidować skrypty, uruchamiać testy i czytać dokumentację k6 bez przeklejania outputu CLI w tę i z powrotem. Dostarczany jest jako binarka Go lub obraz Dockera — nie jako pakiet npm, więc zignoruj wszelkie „k6 MCP” oparte na npx, które znajdziesz; to nieoficjalne nakładki.
Najszybsza droga to k6 x agent init (wymaga k6 v2.0+ na PATH), które wrzuca odpowiednie pliki skilli do twojego edytora i rejestruje serwer MCP dla narzędzia, którego używasz:
# Bootstrap k6 skills + MCP config for one editor...k6 x agent init claude-code # or cursor, codex
# ...or wire up every supported editor at oncek6 x agent init --allJeśli wolisz wpiąć serwer MCP ręcznie, instalacja jest identyczna we wszystkich narzędziach — różni się tylko komenda rejestracji.
Zainstaluj binarkę, a następnie dodaj ją w Settings → MCP → Add, podając mcp-k6 jako komendę (stdio). Albo wrzuć to do .cursor/mcp.json:
{ "mcpServers": { "k6": { "command": "mcp-k6" } }}Najpierw zainstaluj binarkę: brew tap grafana/grafana && brew install mcp-k6 (lub docker pull grafana/mcp-k6:latest).
brew tap grafana/grafana && brew install mcp-k6claude mcp add --scope user --transport stdio k6 -- mcp-k6
# No local binary? Run it through Docker instead:claude mcp add --scope user --transport stdio k6 -- docker run --rm -i grafana/mcp-k6Dodaj to do ~/.codex/config.toml:
[mcp_servers.k6]command = "mcp-k6"# or run via Docker:# command = "docker"# args = ["run", "--rm", "-i", "grafana/mcp-k6"]Zainstaluj binarkę przez brew install mcp-k6 po brew tap grafana/grafana.
Do wydajności po stronie przeglądarki przyda ci się też Playwright MCP (@playwright/mcp), którego konfiguracja jest taka sama w każdym narzędziu:
claude mcp add playwright -- npx -y @playwright/mcp@latestW Cursorze dodaj go przez Settings → MCP; w Codeksie dodaj blok [mcp_servers.playwright] wskazujący na tę samą komendę npx.
Pętla: wygeneruj, uruchom, przeanalizuj, zabramkuj
Dział zatytułowany „Pętla: wygeneruj, uruchom, przeanalizuj, zabramkuj”Pętla jest taka sama w każdym narzędziu. Zmienia się sposób wywołania.
- Wygeneruj skrypt na podstawie prawdziwego endpointu, docelowej liczby VU, profilu narastania i jawnych progów — a nie „napisz test obciążenia”.
- Uruchom go względem stagingu (
k6 run script.js), gdzie serwer MCP pozwala agentowi bezpośrednio wykonywać go i czytać output. - Przeanalizuj wyniki, przekazując modelowi podsumowanie k6 oraz log wolnych zapytań i prosząc o uszeregowaną listę wąskich gardeł.
- Wepnij bramkę w CI, żeby regresja p95 oblała build, zanim trafi na produkcję.
Oto jak odpalić kroki 1 i 2 w każdym narzędziu:
Otwórz panel agenta (Cmd+I), wklej prompt generujący i pozwól mu napisać tests/load/checkout.js. Z podłączonym serwerem MCP k6 agent może sam uruchomić k6 run i iterować nad oblanymi progami w trybie inline. Użyj checkpointu przed przebiegiem, żeby móc wycofać skrypt, jeśli wygenerowany profil VU jest nierealistyczny.
claude "Generate a k6 load test at tests/load/checkout.js for POST /api/checkout:ramp 0->200 VUs over 2m, hold 5m, ramp down 1m. Add thresholds:http_req_duration p95<300 p99<800, http_req_failed rate<0.01. Then run itagainst $STAGING_URL and summarize threshold pass/fail."Z zarejestrowanym serwerem MCP k6 Claude Code uruchamia test przez serwer i odczytuje podsumowanie bez przeklejania.
Uruchom go jednorazowo z CLI albo odpal w Codex Cloud, żeby długotrwały test wykonał się poza twoją maszyną:
codex --sandbox workspace-write -c approval_policy=on-request \"Generate a k6 load test at tests/load/checkout.js for POST /api/checkout(ramp 0->200 VUs over 2m, hold 5m), add p95<300/p99<800 thresholds, run itagainst $STAGING_URL, and report which thresholds failed."Do zaufanego przebiegu unattended w CI użyj codex exec --sandbox workspace-write -c approval_policy=never i jawnie przyznaj dostęp sieciowy do stagingu w izolowanej konfiguracji CI. never wyłącza monity, ale nie rozszerza sandboxa; używaj poświadczeń staging o minimalnych uprawnieniach i nigdy nie kieruj tego zadania na produkcję.
Generowanie testu obciążenia
Dział zatytułowany „Generowanie testu obciążenia”Po prompt na pojedynczy endpoint sięgasz jako pierwszy: daje skrypt, który przeczytasz w minutę i któremu zaufasz, bo każda liczba w nim jest liczbą, którą sam podałeś.
Wygenerowany skrypt powinien wyjść mniej więcej tak — konkretne etapy VU i progi, a nie szkielet ścieżki happy path:
import http from 'k6/http';import { check, sleep } from 'k6';
export const options = { stages: [ { duration: '2m', target: 200 }, // ramp to peak { duration: '5m', target: 200 }, // hold { duration: '1m', target: 0 }, // ramp down ], thresholds: { http_req_duration: ['p(95)<300', 'p(99)<800'], http_req_failed: ['rate<0.01'], },};
export default function () { const res = http.post(`${__ENV.STAGING_URL}/api/checkout`, JSON.stringify({ cartId: 'c_load_test', paymentMethod: 'pm_test', }), { headers: { 'Content-Type': 'application/json' } });
check(res, { 'status is 200': (r) => r.status === 200 }); sleep(1); // think time so 200 VUs != 200 RPS}k6 run kończy się kodem niezerowym, gdy próg zostaje przekroczony, i to właśnie sprawia, że bramka CI poniżej jest banalnie prosta.
Jeden endpoint to początek; prawdziwy przepływ to kilka, a kształt ruchu ma znaczenie nie mniejsze niż jego wolumen. Te trzy prompty skalują ten sam przepis w górę — wieloetapowa podróż użytkownika ze skokiem, cały zestaw z helperami i skryptami npm oraz przebieg po całym repozytorium, który sam wybiera endpointy.
Generate a k6 load test for our checkout API:
Scenario: Simulate a flash sale with ramping traffic- Ramp from 0 to 100 virtual users over 2 minutes- Hold at 100 VUs for 5 minutes (steady state)- Spike to 500 VUs for 1 minute (flash sale moment)- Return to 100 VUs for 2 minutes (recovery)- Ramp down to 0 over 1 minute
API calls per virtual user iteration:1. POST /api/auth/login (use test credentials from env)2. GET /api/products?category=sale (browse sale items)3. POST /api/cart/items (add random product)4. POST /api/checkout (complete purchase with test payment)
Thresholds:- p95 response time < 500ms during steady state- p99 response time < 2000ms during spike- Error rate < 1% at all times- Checkout success rate > 99%
Save to /tests/performance/checkout-load.k6.jsclaude "Create a comprehensive k6 performance test suite:
1. /tests/performance/checkout-load.k6.js - Checkout flow load test - Ramping traffic pattern: 0 -> 100 -> 500 -> 100 -> 0 VUs - Realistic user journey (login, browse, cart, checkout) - SLA thresholds for response time and error rate
2. /tests/performance/api-stress.k6.js - API endpoint stress test - Test each critical endpoint individually - Find the breaking point (ramp until errors > 5%) - Report max throughput per endpoint
3. /tests/performance/helpers/auth.js - Shared auth helper - Login and cache tokens - Token refresh handling
4. package.json scripts: - test:perf:load - Run load tests - test:perf:stress - Run stress tests - test:perf:smoke - Quick 30-second smoke test
Include realistic test data generation for each scenario."Create a performance testing suite for this project:1. Analyze the API routes to identify critical endpoints2. Generate k6 load tests for the top 5 most important flows3. Create stress tests that find breaking points4. Add performance smoke tests for CI integration5. Create a PR with the test suite and documentation
Include realistic traffic patterns based on typical SaaS usage.Testy stresu: znajdowanie punktu załamania
Dział zatytułowany „Testy stresu: znajdowanie punktu załamania”Test obciążenia pyta „czy wytrzyma przy ruchu, jakiego się spodziewamy?”. Test stresu pyta „przy jakiej liczbie przestaje wytrzymywać?” — a odpowiedź trafia do dokumentu planowania pojemności. Zdefiniuj punkt załamania przed przebiegiem, żeby test raportował liczbę, a nie wrażenie.
Analiza wyników
Dział zatytułowany „Analiza wyników”Czerwony próg mówi, że coś jest wolne. Nie mówi, która warstwa się nasyciła, a to właśnie pytanie warto oddać modelowi. Dwa prompty, zależnie od tego, jakim materiałem dysponujesz.
Gdy masz tylko krzywą obciążenia, samym dowodem jest kształt degradacji — czyste liniowe narastanie wskazuje na coś zupełnie innego niż urwisko:
Gdy możesz dołożyć log wolnych zapytań bazy z tego samego okna, diagnoza przestaje być wnioskowaniem. Ten drugi prompt wymaga dowodu przy każdym twierdzeniu i kończy się jedną priorytetową zmianą, a nie listą możliwości:
Żeby pójść dalej, podłącz Sentry MCP, aby agent mógł skorelować przekroczenia progów z błędami i wolnymi transakcjami, które Sentry zarejestrował podczas przebiegu. Zdalny serwer to najprostsza konfiguracja i jest identyczny we wszystkich narzędziach:
# Official Sentry remote MCP (recommended)claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
# Local stdio alternative, if you need itclaude mcp add sentry -- npx -y @sentry/mcp-serverPotem zapytaj: „Dla okna testu obciążenia 14:00–14:08 UTC wyciągnij najwolniejsze transakcje i wszelkie nowe błędy z Sentry i zestaw je z przekroczeniami progów k6.” To zamienia czerwony przebieg CI w konkretną listę transakcji do naprawy.
Core Web Vitals pod równoległym obciążeniem
Dział zatytułowany „Core Web Vitals pod równoległym obciążeniem”Serwerowe p95 może być zdrowe, a strona i tak sprawiać wrażenie zepsutej, bo przeglądarka wykonuje pracę, której API nigdy nie widzi. Mierz front end, gdy API jest pod obciążeniem, a nie na bezczynnej maszynie.
Benchmarki wydajności bazy danych
Dział zatytułowany „Benchmarki wydajności bazy danych”Większość urwisk w testach obciążenia okazuje się zapytaniem, które było w porządku przy skali danych zaseedowanych. Benchmarkuj zapytania bezpośrednio, przy produkcyjnej liczbie wierszy, z indeksem, o który się spierasz, i bez niego.
Bramkowanie regresji w CI
Dział zatytułowany „Bramkowanie regresji w CI”Dwie bramki wyłapują dwie różne awarie i chcesz mieć obie. Pierwsza jest bezwzględna: thresholds w samym skrypcie definiują „za wolno”, a ponieważ k6 run zwraca niezerowy kod wyjścia, gdy któryś próg zostanie przekroczony, krok CI sprowadza się do uruchomienia skryptu — bez własnej logiki porównań. Użyj oficjalnej grafana/setup-k6-action, a nie ręcznie sklejonej instalacji przez curl:
- uses: actions/checkout@v5- uses: grafana/setup-k6-action@v1- run: k6 run tests/load/checkout.js env: STAGING_URL: ${{ secrets.STAGING_URL }} TOKEN: ${{ secrets.LOAD_TEST_TOKEN }}Druga bramka jest względna i wyłapuje to, czego pierwsza nie potrafi: zmiana, która podwaja p95 z 90 ms do 180 ms, przechodzi próg p(95)<300, po cichu zjadając połowę twojego zapasu. Do tego potrzebujesz zapisanej bazy odniesienia i porównania procentowego.
Uruchomienia testów obciążenia i stresu są długie i głodne CPU, więc to, gdzie je uruchamiasz, ma znaczenie nie mniejsze niż sam skrypt. Każde narzędzie ma naturalne miejsce dla zadań k6:
Pisz i debuguj skrypty k6 lokalnie w trybie Agent na URL stagingowym, a potem zacommituj plik workflow. Cursor to miejsce, gdzie iterujesz nad progami i scenariuszami; nie chcesz, by długie uruchomienia testów stresu blokowały edytor, więc trzymaj uruchomienia w edytorze na poziomie 30-sekundowego smoke testu.
Uruchamiaj benchmark smoke w trybie headless jako bramkę PR: claude -p "run k6 run tests/performance/smoke.k6.js, compare p95 against perf-baseline.json, and fail if it regressed more than 20%" wewnątrz zadania GitHub Actions. Połącz to z hookiem PostToolUse, by komentarz z porównaniem był publikowany automatycznie.
Przerzuć długie uruchomienia testów obciążenia i stresu na Codex Cloud lub zaplanowaną automatyzację, by wykonywały się na sprzęcie w chmurze, a nie na runnerze PR — a następnie niech otworzy PR (lub komentarz) z tabelą wyników. Dzięki temu wielominutowe uruchomienia nie obciążają krytycznej ścieżki CI, a merge nadal jest bramkowany wynikiem z chmury.
Praktyczny podział jest warstwowy: 30-sekundowy smoke test na każdym PR, pełny test obciążenia w nocy, test stresu co tydzień. Smoke test łapie oczywiste regresje; dłuższe przebiegi łapią subtelne, nie wstrzymując merge’a.
Kiedy liczby z testów obciążenia kłamią
Dział zatytułowany „Kiedy liczby z testów obciążenia kłamią”Liczby z testów obciążenia kłamią w przewidywalny sposób. Oto tryby awarii, które wysyłają zespoły w pogoń za niewłaściwą naprawą.
Gdy wynik wygląda na niemożliwy, przekaż swojemu narzędziu AI pełne podsumowanie k6 i metryki zasobów generatora i poproś, żeby odróżniło prawdziwe wąskie gardło serwera od artefaktu testu, zanim eskalujesz.