Guia Completo — Setup e Comandos

Do zero ao load testing em produção: instale o k6, execute gates smoke contra o qaschool/testflow, ajuste thresholds SLO, publique relatórios HTML e integre Grafana.

Smoke · Load · Stress · Spike · Soak · Journey · Browser

O que é k6?

O Grafana k6 é uma ferramenta open-source de teste de carga para API, microsserviços e performance de browser. Os scripts são escritos em JavaScript (ES modules) e executados por um runtime Go que gera tráfego HTTP real em escala.

Developer-first

Scripts JS versionados, npm scripts e gates em CI — mesmo fluxo do Cypress e Playwright.

Métricas nativas

http_req_duration, http_req_failed, checks, VUs e Trend/Rate/Counter customizados.

Thresholds SLO

Falha a execução quando latência, taxa de erro ou checks violam limites — não só quando a app cai.

Saída extensível

Summary JSON, dashboard HTML, streaming InfluxDB, Grafana Cloud e export do web dashboard k6.

Por que usar k6 no testflow-k6?

O repositório testflow-k6 complementa a automação funcional em testflow-cypress, testflow-playwright e testflow-pytest. Valida Service Level Objectives (SLOs) do sandbox TestFlow na porta 5050 em padrões smoke, load, stress, spike e soak.

  • Mesmos endpoints — /health, /api/auth/login, /api/users, /web/*.html
  • SLOs alinhados — p95 por endpoint espelha timeouts dos testes funcionais
  • Gate smoke em CI — cada push executa perfil leve contra TestFlow em Docker
  • Relatório GitHub Pages — dashboard HTML com 7 cenários a cada push em main
  • Credenciais compartilhadas — demo@automation.io / variável DEMO_PASSWORD
Diferente de ferramentas só de browser, o k6 brilha em throughput HTTP e concorrência. Use test:browser:login para Chromium sob carga; use cenários de API para testes de capacidade.

Pré-requisitos

Antes de clonar o repositório, confirme que sua máquina atende aos requisitos abaixo.

Node.js 20+

Necessário para scripts npm, geração de relatório e servidor local de docs.

TestFlow na 5050

App alvo: qaschool/testflow:latest — health em http://localhost:5050/health.

k6 v1.0+

Binário nativo recomendado. Fallback Docker via scripts/run-k6.sh sem k6 instalado.

Docker (opcional)

TestFlow, imagem k6-influx, stack Grafana + InfluxDB ou compose completo.

$ node --version
v20.x.x

$ curl -sf http://localhost:5050/health
{"status":"ok"}

$ k6 version
k6 v1.x.x (...)

Setup do projeto

git clone https://github.com/lflucasferreira/testflow-k6.git
cd testflow-k6
npm install
cp .env.example .env   # opcional — BASE_URL, DEMO_PASSWORD, tokens InfluxDB

Setup do ambiente por plataforma

Instale Node.js 20+, Git e Docker (para TestFlow na porta 5050). Os passos do projeto (npm install, execuções k6) são idênticos em todo SO.

macOS

# Homebrew — https://brew.sh
brew install node@20 git
brew link --overwrite node@20
brew install --cask docker

node --version   # v20+
git --version

Homebrew · Docker Desktop

Windows

winget install OpenJS.NodeJS.LTS
winget install Git.Git
winget install Docker.DockerDesktop

node --version

winget · PowerShell · Git Bash

Linux (Debian / Ubuntu)

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs git docker.io
sudo usermod -aG docker $USER

node --version

NodeSource · Docker · faça logout após usermod para o grupo docker.

Subir TestFlow — igual em todo SO

docker run --rm -p 5050:5050 qaschool/testflow:latest
# ou
npm run docker:up

Instalação do k6

O k6 nativo é mais rápido no dia a dia e obrigatório para cenários browser (test:browser:login). Sem k6 instalado, os scripts npm usam a imagem grafana/k6 via scripts/run-k6.sh.

macOS — Homebrew

brew install k6
k6 version

Linux — apt (Debian/Ubuntu)

curl -fsSL https://dl.k6.io/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/k6-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install -y k6
k6 version

Windows — winget

winget install k6 --source winget
k6 version

Verificar instalação

$ k6 version
k6 v1.0.0 (go1.22.0, darwin/arm64)

$ npm run test:smoke
# usa k6 local quando disponível
Proxy corporativo (Zscaler / SSL): se brew install k6 ou apt falhar com erro de certificado, use o fallback Docker (npm run docker:smoke) ou configure CA do sistema — mesma abordagem do testflow-playwright.

Estrutura do projeto

testflow-k6/
├── config/              # environments.js, profiles.js, thresholds.js
├── lib/                 # auth.js, http.js, endpoints.js, summary.js
├── scenarios/
│   ├── smoke/           # gate CI — api-health.js
│   ├── load/            # api-auth, api-users, mixed-traffic
│   ├── stress/          # api-breakpoint.js
│   ├── spike/           # api-spike.js
│   ├── soak/            # api-endurance.js
│   └── browser/         # login-page.js (k6 browser)
├── journeys/            # login-flow.js, authenticated-user.js
├── docs/                # hub GitHub Pages, slides, este guia
├── monitoring/          # provisionamento Grafana + InfluxDB
│   ├── grafana/         # datasource + dashboard JSON k6
│   └── influxdb/        # template YAML + dashboard JSON
├── scripts/             # run-k6.sh, generate-report.mjs, grafana-up.sh
├── results/             # summary JSON, relatório HTML, REPORT.md
├── docker/              # k6-influx.Dockerfile (xk6-output-influxdb)
├── docker-compose.yml
└── .github/workflows/
    └── k6.yml           # gate smoke, load manual, GitHub Pages

config/

environments.js — BASE_URL, credenciais. profiles.js — stages de VU. thresholds.js — gates SLO.

lib/

Helpers HTTP reutilizáveis com check() embutido. Nunca duplique lógica de endpoint nos cenários.

scenarios/

Testes de carga por tipo: smoke, load, stress, spike, soak, browser.

journeys/

Fluxos multi-etapa com group() para timing por passo nos relatórios.

monitoring/

Dashboards Grafana e templates InfluxDB para stack local e cloud.

docs/

Landing page, slides Reveal.js, walkthroughs EN/PT, estratégia de thresholds, guias completos.

Primeiro cenário — smoke api-health.js

O gate smoke é a forma mais rápida de validar que o TestFlow responde sob carga mínima. Execute com npm run test:smoke.

  1. Suba o TestFlow
    docker run --rm -p 5050:5050 qaschool/testflow:latest
  2. Execute o cenário smoke
    npm run test:smoke
  3. Inspecione o script — arquivo: scenarios/smoke/api-health.js
import { sleep } from 'k6';
import { getProfile } from '../../config/profiles.js';
import { getThresholds } from '../../config/thresholds.js';
import { TAGS } from '../../config/environments.js';
import { login } from '../../lib/auth.js';
import { getHealth, getUsers } from '../../lib/http.js';
import { handleSummary } from '../../lib/summary.js';

export { handleSummary };

const profile = getProfile('smoke');

export const options = {
  scenarios: {
    smoke_api: {
      executor: 'ramping-vus',
      ...profile,
      tags: { test_type: TAGS.smoke, suite: 'api-health' },
    },
  },
  thresholds: getThresholds('smoke'),
};

export default function smokeApiHealth() {
  getHealth();
  sleep(0.5);
  getUsers();
  sleep(0.5);
  login();
  sleep(1);
}

Cada iteração exercita três endpoints críticos:

  • GET /health — probe de disponibilidade
  • GET /api/users — lista read-heavy com validação JSON
  • POST /api/auth/login — autenticação e extração de token

Walkthrough: docs/pt/scenarios/smoke/api-health.md

Perfis de carga

Perfis em config/profiles.js definem stages para o executor ramping-vus. Selecione com K6_PROFILE ou passe o nome para getProfile().

Perfil Stages (resumo) Uso típico
smoke 2 VUs · ~35 s Gate local, suite test:report
ci 3→5 VUs · ~55 s GitHub Actions com CI=true e perfil smoke
load 10→25 VUs · 7 min Tráfego sustentado tipo produção
stress 20→100 VUs · 12 min Degradação sob carga alta
spike 5→100 VUs burst · ~2,5 min Pico súbito e recuperação
soak 15 VUs · 30+ min steady Endurance / detecção de vazamentos
breakpoint Escalonado 10→125 VUs Ramp estendido (K6_PROFILE=breakpoint)
// config/profiles.js — trecho
export const profiles = {
  smoke: {
    stages: [
      { duration: '10s', target: 2 },
      { duration: '20s', target: 2 },
      { duration: '5s', target: 0 },
    ],
    gracefulRampDown: '5s',
  },
  load: {
    stages: [
      { duration: '1m', target: 10 },
      { duration: '3m', target: 25 },
      { duration: '2m', target: 25 },
      { duration: '1m', target: 0 },
    ],
    gracefulRampDown: '30s',
  },
  // stress, spike, soak, breakpoint, ci …
};

export function getProfile(name) {
  const key = name || __ENV.K6_PROFILE || 'smoke';
  if (__ENV.CI === 'true' && key === 'smoke') return profiles.ci;
  return profiles[key] || profiles.smoke;
}
K6_PROFILE=load npm run test:load:mixed K6_PROFILE=spike npm run test:spike CI=true npm run test:smoke

Thresholds e checks

O k6 usa dois mecanismos complementares. A execução falha se qualquer um violar limites. Veja threshold-strategy.md para a matriz SLO completa.

Mecanismo Propósito Exemplo
check() Correção funcional por request health status 200, login has token
thresholds SLO agregado na execução inteira http_req_duration: p(95)<1500, checks: rate>0.99

Tags por endpoint

Marque cada chamada HTTP com endpoint para thresholds filtrados:

http.get(url, {
  tags: { endpoint: 'health', name: 'GET /health' },
});

// config/thresholds.js
export const smokeThresholds = {
  http_req_failed: ['rate<0.005'],
  http_req_duration: ['p(95)<1500', 'avg<800'],
  'http_req_duration{endpoint:health}': ['p(95)<500'],
  'http_req_duration{endpoint:users}': ['p(95)<1500'],
  'http_req_duration{endpoint:auth_login}': ['p(95)<2000'],
  checks: ['rate>0.99'],
};

Checks em lib/http.js

Helper Checks aplicados
getHealth() status 200; resposta < 1 s
getUsers(token?) status 200; users[] não vazio; resposta < 2 s
getStaticPage(path) status 200; Content-Type inclui text/html
login() em lib/auth.js status 200; JSON token é string

Helpers HTTP

Helpers centralizados em lib/http.js e lib/auth.js mantêm cenários enxutos e garantem checks consistentes em todo tipo de teste.

getHealth()

export function getHealth(params = {}) {
  const res = http.get(`${BASE_URL}${endpoints.health}`, {
    tags: { endpoint: 'health', name: 'GET /health' },
    ...params,
  });
  check(res, {
    'health status 200': (r) => r.status === 200,
    'health responds quickly': (r) => r.timings.duration < 1000,
  });
  return res;
}

getUsers(token?)

export function getUsers(token = null, params = {}) {
  const headers = token ? authHeaders(token) : { 'Content-Type': 'application/json' };
  const res = http.get(`${BASE_URL}${endpoints.users.list}`, {
    headers,
    tags: { endpoint: 'users', name: 'GET /api/users' },
    ...params,
  });
  check(res, {
    'users status 200': (r) => r.status === 200,
    'users has array': (r) => Array.isArray(r.json('users')) && r.json('users').length > 0,
    'users responds within 2s': (r) => r.timings.duration < 2000,
  });
  return res;
}

login()

export function login(params = {}) {
  const res = http.post(`${BASE_URL}${endpoints.auth.login}`, payload, {
    headers: { 'Content-Type': 'application/json' },
    tags: { endpoint: 'auth_login', name: 'POST /api/auth/login' },
    ...params,
  });
  check(res, {
    'login status 200': (r) => r.status === 200,
    'login has token': (r) => typeof r.json('token') === 'string',
  });
  return res.json('token');
}

getStaticPage(path)

export function getStaticPage(path, params = {}) {
  const res = http.get(`${BASE_URL}${path}`, {
    tags: { endpoint: 'static', name: `GET ${path}` },
    ...params,
  });
  check(res, {
    'static page status 200': (r) => r.status === 200,
    'static page has html': (r) => (r.headers['Content-Type'] || '').includes('text/html'),
  });
  return res;
}

Utilitários extras: weightedPick(), thinkTime(), getErrorSimulation().

Tipos de teste

Cada tipo mapeia para pasta, perfil de carga e conjunto de thresholds.

Tipo Script Script npm O que valida
Smoke
Smoke scenarios/smoke/api-health.js test:smoke Disponibilidade + latência baseline (health, users, login)
Load
Load — auth scenarios/load/api-auth.js test:load:auth Throughput de login; login_duration, login_errors
Load — users scenarios/load/api-users.js test:load:users Lista users read-heavy com token via setup()
Load — mixed scenarios/load/mixed-traffic.js test:load:mixed Tráfego ponderado: 35% health, 30% users, 15% static, 20% users anônimo
Stress · Spike · Soak
Stress scenarios/stress/api-breakpoint.js test:stress Ramp até 100 VUs; conta degraded_responses
Spike scenarios/spike/api-spike.js test:spike Burst 5→100 VUs; métrica spike_failures
Soak scenarios/soak/api-endurance.js test:soak 15 VUs steady por K6_SOAK_MINUTES (padrão 30 min)
Journey · Browser
Journey journeys/login-flow.js test:journey:login Login page → API login → dashboard (passos agrupados)
Journey journeys/authenticated-user.js test:journey:auth Login → users → dashboard → team
Browser scenarios/browser/login-page.js test:browser:login Chromium: preenche login via data-testid; mede browser_page_load

Métricas customizadas

Importe Trend, Rate e Counter de k6/metrics para rastrear comportamento específico além das métricas HTTP nativas.

Trend

Distribuições de tempo — p95, avg. Ex.: login_duration, journey_duration, browser_page_load.

Rate

Percentual de valores não-zero. Ex.: login_errors, spike_failures.

Counter

Contagem monotônica crescente. Ex.: degraded_responses no cenário stress.

import { Trend, Rate, Counter } from 'k6/metrics';

const loginDuration = new Trend('login_duration', true);
const loginErrors = new Rate('login_errors');
const degradedResponses = new Counter('degraded_responses');

// Registrar valores durante o teste
loginDuration.add(res.timings.duration);
loginErrors.add(!ok);
degradedResponses.add(1);

// Adicionar thresholds em options
export const options = {
  thresholds: {
    ...getThresholds('load'),
    login_duration: ['p(95)<2000'],
    login_errors: ['rate<0.01'],
  },
};
Métrica Tipo Cenário Threshold
login_durationTrendapi-auth.jsp(95)<2000
login_errorsRateapi-auth.jsrate<0.01
users_list_durationTrendapi-users.jsp(95)<2000
login_flow_durationTrendlogin-flow.jsp(95)<4000
spike_failuresRateapi-spike.jsrate<0.10
degraded_responsesCounterapi-breakpoint.jsinformativo
browser_page_loadTrendlogin-page.jsp(95)<5000

group() em journeys

Use group() do k6 para rotular passos em fluxos multi-etapa. Grupos aparecem separados no summary e no relatório HTML, facilitando identificar passos lentos.

import { sleep, group } from 'k6';
import { Trend } from 'k6/metrics';

const loginFlowDuration = new Trend('login_flow_duration', true);

export default function loginFlow() {
  const start = Date.now();

  group('01_load_login_page', () => {
    getStaticPage(endpoints.web.login);
    sleep(0.5);
  });

  group('02_api_login', () => {
    const res = http.post(`${BASE_URL}${endpoints.auth.login}`, payload, { /* … */ });
    check(res, { 'login succeeds': (r) => r.status === 200 });
    sleep(0.3);
  });

  group('03_post_login_navigation', () => {
    getStaticPage(endpoints.web.dashboard);
    sleep(0.5);
  });

  loginFlowDuration.add(Date.now() - start);
}

Scripts journey: journeys/login-flow.js (3 grupos) e journeys/authenticated-user.js (4 grupos: login → users → dashboard → team).

Fase setup()

A função setup() roda uma vez antes dos VUs iniciarem. Use para trabalho caro único — ex.: obter token de auth — e passe o resultado para a função default.

// lib/auth.js
export function setupAuth() {
  const token = login();
  return { token };
}

// scenarios/load/api-users.js
export function setup() {
  return setupAuth();
}

export default function usersLoad(data) {
  const res = getUsers(data.token);
  usersListDuration.add(res.timings.duration);
  sleep(0.5 + Math.random());
}
setup() vs login por iteração: smoke e mixed-traffic chamam login() a cada iteração para simular carga real de auth. Users list usa setup() para focar em throughput de leitura sem overhead de login.

Relatórios

O testflow-k6 produz vários formatos de relatório para debug local e publicação em CI.

npm run test:report

Executa 7 cenários com K6_PROFILE=smoke (~4 min total):

  1. smoke · 2. load-auth · 3. load-users · 4. mixed-traffic
  2. login-flow · 6. authenticated-user · 7. spike

Gera:

  • results/REPORT.md — resumo Markdown
  • results/report/index.html — dashboard HTML com PASS/FAIL, gráficos, checks, thresholds
  • results/summary-latest.json — summary legível por máquina
  • results/runs/<run-id>-*.json — exports brutos k6
npm run test:report
npm run report:open    # abre results/report/index.html localmente

Relatório live: lflucasferreira.github.io/testflow-k6/report/

handleSummary

// lib/summary.js — exportado de todo cenário
export function handleSummary(data) {
  return {
    stdout: 'texto do summary k6…',
    'results/summary-latest.json': JSON.stringify(data, null, 2),
    [`results/summary-${scenario}-${profile}-${timestamp}.json`]: JSON.stringify(data, null, 2),
  };
}

Web Dashboard k6 (live + export HTML)

npm run test:smoke:ui          # K6_DASHBOARD=true — live em http://localhost:5665
npm run test:load:mixed:ui
K6_DASHBOARD=true K6_SCENARIO=spike npm run test:spike

GitHub Pages

A cada push em main, o job publish-pages em .github/workflows/k6.yml monta o hub de docs, executa a suite de relatório e publica no GitHub Pages.

Grafana + InfluxDB

Stream métricas k6 em tempo real para InfluxDB e visualize no Grafana — local ou na cloud.

Stack local

npm run grafana:up              # TestFlow + InfluxDB + Grafana (Docker)
npm run test:smoke:grafana      # smoke com métricas live
npm run test:load:mixed:grafana # load com dashboard
npm run grafana:down
Serviço URL Notas
Grafana http://localhost:3000 Dashboard: K6 Test Results
InfluxDB http://localhost:8086 org testflow, bucket k6
TestFlow http://localhost:5050 Mesmo sandbox das outras suites

Cloud (InfluxDB Cloud + Grafana Cloud)

cp .env.influx.cloud.example .env.influx.cloud   # adicionar tokens
npm run test:smoke:influx:cloud
npm run test:load:mixed:influx:cloud

Guia completo: grafana-cloud-setup.md · influxdb-cloud-dashboard.md · embed via docs/grafana/

GitHub Pages não hospeda InfluxDB nem Grafana. Apenas uma URL pública do Grafana Cloud pode ser embutida no site estático.

CI — GitHub Actions

Workflow: .github/workflows/k6.yml

Gate smoke

Cada push/PR executa api-health.js com CI=true e perfil ci mais leve.

Service container

qaschool/testflow:latest na porta 5050 com health checks.

GitHub Pages

Job publish-pages no push em main — hub docs + relatório HTML com 7 cenários.

Load manual

workflow_dispatch — escolha perfil smoke, load, stress ou spike para mixed-traffic.

# k6.yml — job smoke (trecho)
services:
  testflow:
    image: qaschool/testflow:latest
    ports: ['5050:5050']
env:
  CI: "true"
  BASE_URL: http://localhost:5050
  K6_PROFILE: smoke
  DEMO_PASSWORD: ${{ secrets.DEMO_PASSWORD }}
run: k6 run --summary-export=results/summary.json scenarios/smoke/api-health.js

Badge: workflow k6 CI

O deploy GitHub Pages (anteriormente em pages.yml) está integrado ao job publish-pages neste workflow.

Referência de scripts npm

Script Descrição
Smoke e CI
test:smokeGate smoke — api-health.js
test:smoke:uiSmoke com web dashboard k6 + export HTML
test:ciExecução estilo CI com export de summary
Load
test:load:authThroughput sustentado de login
test:load:auth:uiLoad auth com web dashboard
test:load:usersLista users read-heavy (token via setup)
test:load:mixedTráfego misto ponderado
test:load:mixed:uiMixed traffic com web dashboard
Stress · Spike · Soak
test:stressRamp stress / breakpoint
test:spikeBurst spike
test:soakEndurance soak (30+ min)
Journey · Browser
test:journey:authJourney usuário autenticado
test:journey:loginJourney fluxo de login
test:browser:loginLogin page browser (Chromium)
Relatórios
test:reportSuite 7 cenários + relatório HTML
report:openAbrir último relatório HTML no browser
Docker
docker:upSubir TestFlow via compose
docker:downParar stack compose
docker:smokeSmoke no container k6
docker:smoke:hostContainer k6 → TestFlow no host na 5050
docker:loadLoad mixed-traffic no container
docker:stressStress no container
Grafana / InfluxDB
grafana:upSubir stack de monitoring
grafana:downParar stack de monitoring
grafana:buildBuild imagem Docker k6-influx
test:smoke:grafanaSmoke → InfluxDB local + Grafana
test:smoke:influx:localSmoke → InfluxDB Docker
test:smoke:influx:cloudSmoke → InfluxDB Cloud
test:load:mixed:grafanaLoad → Grafana local
test:load:mixed:influx:localLoad → InfluxDB local
test:load:mixed:influx:cloudLoad → InfluxDB Cloud
Docs
slidesServir docs na porta 3337
slides:openServir + abrir slides no browser
docs:openServir hub docs na porta 3338
slides:pdfExportar slides para PDF

Documentação de treinamento

Walkthroughs bloco a bloco para cada script de cenário — ideal para alunos aprendendo k6 e testes orientados a SLO.

docs/en/README.md

Índice em inglês — walkthroughs smoke, load, stress, spike, soak, journeys, browser.

docs/pt/README.md

Índice em português — mesma cobertura de cenários.

threshold-strategy.md

Checks vs thresholds, tags por endpoint, alinhamento de perfis, métricas customizadas.

slides/

Apresentação Reveal.js — fundamentos k6, tipos de teste, Grafana, CI/CD.

Walkthroughs por cenário

Cenário Doc PT Script
API healthapi-health.mdscenarios/smoke/api-health.js
Auth loadapi-auth.mdscenarios/load/api-auth.js
Users loadapi-users.mdscenarios/load/api-users.js
Mixed trafficmixed-traffic.mdscenarios/load/mixed-traffic.js
Spikeapi-spike.mdscenarios/spike/api-spike.js
Stressapi-breakpoint.mdscenarios/stress/api-breakpoint.js
Soakapi-endurance.mdscenarios/soak/api-endurance.js
Login journeylogin-flow.mdjourneys/login-flow.js
Auth journeyauthenticated-user.mdjourneys/authenticated-user.js
Browser loginlogin-page.mdscenarios/browser/login-page.js

Boas práticas

  • Reutilize helpers da lib — nunca duplique chamadas HTTP ou checks nos cenários
  • Marque todo request — defina endpoint para thresholds SLO por rota
  • Escolha o perfil certo — smoke para gates, load para tráfego sustentado, spike para bursts
  • Separe checks de thresholds — checks validam correção; thresholds validam SLO
  • Exporte handleSummary — todo cenário deve exportar handleSummary de lib/summary.js
  • Use group() em journeys — timing por passo torna relatórios acionáveis
  • setup() para auth cara — quando o foco é read/write, não throughput de login
  • Métricas custom com thresholds — adicione Trend/Rate só quando métricas nativas não bastam
  • Registre novos cenários — atualize scripts/scenario-catalog.mjs e adicione walkthroughs EN/PT
  • Alinhe com suites funcionais — budgets SLO espelham timeouts Cypress/Playwright
  • CI rápido — só perfil smoke no gate de PR; load/stress manual ou via workflow_dispatch
  • Leia threshold-strategy.md antes de afrouxar limites
  • Testes browser precisam k6 nativo — fallback Docker não suporta --browser
  • Think time entre requests — use sleep() e thinkTime() para pacing realista

Próximos passos

Slides interativos

Apresentação Reveal.js com animações, visão geral de tipos de teste, setup Grafana e padrões CI/CD.

Documentação oficial

grafana.com/docs/k6 — executors, métricas, módulo browser, extensions e cloud.

Relatório live

GitHub Pages report — dashboard com 7 cenários atualizado a cada push em main.

Aplicação alvo

qaschool/testflow — sandbox que todas as suites TestFlow exercitam.