Created
October 7, 2025 17:58
-
-
Save GlauberF/10b1b55970990bb47b02f669cb440fe3 to your computer and use it in GitHub Desktop.
exemplo de uso do K6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* K6 | |
* Documentação completa | |
* https://grafana.com/docs/k6/latest/ | |
* | |
* Como instalar | |
* https://grafana.com/docs/k6/latest/set-up/install-k6/ | |
* | |
**/ | |
import http, { head } from 'k6/http'; | |
import { check, sleep } from 'k6'; | |
import exec from 'k6/execution'; | |
import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; | |
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.0.2/index.js'; | |
const baseUrl = "http://tech-lab-app:8080"; | |
const user1Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyMUBleGFtcGxlLmNvbSJ9.5DK2w70WyEtf4HzBPXqsHfO8xoY30CG8rO0QQ5BQGZg"; | |
const user2Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyMkBleGFtcGxlLmNvbSJ9.20lKVN-pzmT8teJwCjH07Ebm2r-tkoY5POxkioy7Ie0"; | |
const user3Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyM0BleGFtcGxlLmNvbSJ9.pv5Y7HIqjloZtlMfVKwTMXv1IWQ7JA0Cl6iMLVmzvDQ"; | |
const user4Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyNEBleGFtcGxlLmNvbSJ9.XWTnHFbUZtTT5azD7ByadrLs42dM4vbsrQFvVZcq6m4"; | |
const user5Token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyNUBleGFtcGxlLmNvbSJ9.G7UAkWKqtHOUxvW7zvqpMA9kjYk0uNZuEVMGkKHpBK8"; | |
export const options = { | |
scenarios: { | |
failedAuthorization: { | |
executor: 'shared-iterations', | |
exec: 'failedAuthorization', | |
iterations: 1, | |
maxDuration: '10s' | |
}, | |
successfullyAuthorization: { | |
executor: 'shared-iterations', | |
exec: 'successfullyAuthorization', | |
iterations: 1, | |
maxDuration: '10s' | |
}, | |
rateLimiting1: { // Rate limit na criacao de cobranca, 20 requisicoes. | |
executor: 'shared-iterations', | |
vus: 1, | |
exec: 'rateLimiting', | |
iterations: 20, | |
maxDuration: '10s', | |
env: { REMOTE_IP: randomIp() }, | |
}, | |
rateLimiting2: { // Rate limit na criacao de cobranca, 20 requisicoes, com 4 usuarios (concorrencia). | |
executor: 'shared-iterations', | |
vus: 4, | |
exec: 'rateLimiting', | |
iterations: 20, | |
maxDuration: '10s', | |
env: { REMOTE_IP: randomIp(), multithreading: 'true' }, | |
}, | |
rateLimitingGetPayment: { // Rate limit para Busca de cobrança | |
executor: 'per-vu-iterations', | |
vus: 5, | |
exec: 'rateLimitingGetPayment', | |
iterations: 4, | |
maxDuration: '10s', | |
env: { REMOTE_IP: randomIp() }, | |
startTime: '5s', | |
}, | |
burstLimit: { // Burst de 10 requisicoes | |
executor: 'constant-arrival-rate', | |
preAllocatedVUs: 10, | |
rate: 10, | |
timeUnit: '1s', | |
duration: '1s', | |
exec: 'burst', | |
env: { REMOTE_IP: randomIp(), exceeded: 'false' }, | |
}, | |
exceedBurstLimit: { // Burst de 20 requisicoes | |
executor: 'constant-arrival-rate', | |
preAllocatedVUs: 20, | |
rate: 20, | |
timeUnit: '1s', | |
duration: '1s', | |
exec: 'burst', | |
env: { REMOTE_IP: randomIp(), exceeded: 'true' }, | |
}, | |
quota: { // Limite diário, 100 requisicoes. | |
executor: 'shared-iterations', | |
vus: 1, | |
exec: 'quota', | |
iterations: 100, | |
maxDuration: '2m', | |
env: { USER: user5Token }, | |
}, | |
quotaExceeded: { // Limite diario, 200 requisicoes. | |
executor: 'shared-iterations', | |
vus: 5, | |
exec: 'quota', | |
iterations: 200, | |
maxDuration: '2m', | |
env: { USER: user4Token, exceeded: 'true' }, | |
}, | |
idempotency: { // Idempotencia na criacao de cobranca. | |
executor: 'shared-iterations', | |
exec: 'idempotency', | |
iterations: 1, | |
maxDuration: '10s' | |
} | |
}, | |
}; | |
function randomIp() { | |
return Array(4).fill(0).map(() => Math.floor(Math.random() * 256)).join('.'); | |
} | |
export function rateLimiting() { | |
const url = `${baseUrl}/payments`; | |
const headers = { | |
'Authorization': user1Token, | |
'Content-Type': 'application/json', | |
'remote-ip': __ENV.REMOTE_IP | |
}; | |
const response = http.get(url, { headers: headers }); | |
const limit = 10; | |
const expectedStatus = exec.scenario.iterationInTest < limit ? 200 : 429; | |
const title = `Rate Limit ${__ENV.multithreading === 'true' ? '(Multithreading) ' : ''}${__ENV.REMOTE_IP}`; | |
if (response.status !== expectedStatus) { | |
console.log(`Inconsistência no Rate Limit detectado. O status ${response.status} foi retornado na execução ${exec.scenario.iterationInTest}`); | |
} | |
check(response, { | |
[title]: (r) => r.status === expectedStatus | |
}); | |
} | |
export function rateLimitingGetPayment(data) { | |
const title = `Rate Limit Get Payment ${__ENV.REMOTE_IP}`; | |
const fakePaymentId = "pay_123"; | |
const url = `${baseUrl}/payments/${fakePaymentId}`; | |
const headers = { | |
'Authorization': user1Token, | |
'Content-Type': 'application/json', | |
'remote-ip': __ENV.REMOTE_IP | |
}; | |
const response = http.get(url, { headers: headers }); | |
const limit = 10; | |
const expectedStatus = exec.scenario.iterationInTest < limit ? 404 : 429; | |
check(response, { | |
[title]: (r) => r.status === expectedStatus | |
}); | |
} | |
export function burst() { | |
const url = `${baseUrl}/payments`; | |
const headers = { | |
'Authorization': user1Token, | |
'Content-Type': 'application/json', | |
'remote-ip': __ENV.REMOTE_IP | |
}; | |
const response = http.post(url, buildPaymentPayloadRequest(), { headers: headers }); | |
const limit = 10; | |
const expectedStatus = exec.scenario.iterationInTest < limit ? 200 : 429; | |
const title = `Burst ${__ENV.exceeded === 'true' ? 'Excedido' : ''} ${__ENV.REMOTE_IP}`; | |
check(response, { | |
[title]: (r) => r.status === expectedStatus | |
}); | |
} | |
export function failedAuthorization() { | |
const token = "aleatorio"; | |
const url = `${baseUrl}/payments`; | |
const headers = { | |
'Authorization': token, | |
'Content-Type': 'application/json', | |
'remote-ip': randomIp() | |
}; | |
const response = http.post(url, buildPaymentPayloadRequest(), { headers: headers }); | |
check(response, { | |
"Token de autenticão incorreto": (r) => r.status === 401 | |
}); | |
} | |
export function successfullyAuthorization() { | |
const url = `${baseUrl}/payments`; | |
const headers = { | |
'Authorization': user3Token, | |
'Content-Type': 'application/json', | |
'remote-ip': randomIp() | |
}; | |
const response = http.post(url, buildPaymentPayloadRequest(), { headers: headers }); | |
check(response, { | |
'Acesso concedido a partir de token valido': (r) => r.status === 200 | |
}); | |
} | |
export function idempotency() { | |
const url = `${baseUrl}/payments`; | |
const headers = { | |
'Authorization': user2Token, | |
'Content-Type': 'application/json', | |
'Idempotency-Key': uuidv4(), | |
'remote-ip': randomIp() | |
}; | |
const response = http.post(url, buildPaymentPayloadRequest(), { headers: headers }); | |
const response2 = http.post(url, buildPaymentPayloadRequest(), { headers: headers }); | |
headers['Idempotency-Key'] = uuidv4() | |
const response3 = http.post(url, buildPaymentPayloadRequest(), { headers: headers }); | |
const anyFailed = response.status !== 200 || response2.status !== 200 || response3.status !== 200; | |
if (anyFailed) { | |
check(response, { | |
'Criação de cobrança com chave de idempotência duplicada': false, | |
'Criação de cobrança com chave de idempotência sem uso': false | |
}) | |
return; | |
} | |
const paymentId1 = response.json().id; | |
const paymentId2 = response2.json().id; | |
const paymentId3 = response3.json().id; | |
check(response, { | |
'Criação de cobrança com chave de idempotência duplicada': paymentId1 === paymentId2, | |
'Criação de cobrança com chave de idempotência sem uso': paymentId1 !== paymentId3 | |
}); | |
} | |
export function quota() { | |
const url = `${baseUrl}/payments`; | |
const headers = { | |
'Authorization': __ENV.USER, | |
'Content-Type': 'application/json', | |
'Idempotency-Key': uuidv4(), | |
'remote-ip': randomIp() | |
}; | |
const response = http.post(url, buildPaymentPayloadRequest(), { headers: headers }); | |
const dailyLimit = 100; | |
const expectedStatus = exec.scenario.iterationInTest < dailyLimit ? 200 : 429; | |
const title = `Limite de requisições diárias ${__ENV.exceeded === 'true' ? 'Excedido' : ''}`; | |
check(response, { | |
[title]: (r) => r.status === expectedStatus | |
}) | |
} | |
function buildPaymentPayloadRequest() { | |
return JSON.stringify({ | |
"dueDate": "2024-11-09", | |
"value": 30.00, | |
"description": "Oi", | |
"customer": { | |
"name": "Joao Silva Costa", | |
"cpfCnpj": "39105420008" | |
}, | |
"billingType": "PIX" | |
}); | |
} | |
export function setup() { | |
return {paymentId: 1}; | |
} | |
export function handleSummary(data) { | |
return { | |
stdout: textSummary(data, { indent: '→', enableColors: true }), | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment