automacao-core-carga-back
v1.0.3
Published
Core compartilhado de utilitários k6 e Playwright para testes de carga dos módulos erpx_* e erp_*
Downloads
182
Maintainers
Readme
automacao-core-carga-back
Core compartilhado de utilitários k6 e Playwright para os repositórios de teste de carga dos módulos erpx_* e erp_*.
Instalação
npm install automacao-core-carga-backPara usar o lado Playwright, instale também o runner no seu repositório — ele é
peer dependency, para que exista uma única cópia do @playwright/test na árvore
(duas cópias quebram o registro de fixtures):
npm install -D @playwright/testQuem só usa o lado k6 não precisa dele.
⚠️ Dois entry points, um por runtime
O pacote não tem import raiz. Você importa de /k6 ou de /playwright:
import { K6AuthUtils } from 'automacao-core-carga-back/k6';
import { test } from 'automacao-core-carga-back/playwright';Isso não é preferência de estilo. O k6 roda num runtime Go (goja/sobek), não no
Node: não resolve node_modules e não expõe APIs do Node
(doc oficial). O Playwright
roda no Node. Um bundle único que misturasse os dois carregaria, de uma vez,
requires que só existem num dos lados, e o script k6 falhava ao carregar antes
da primeira linha de teste.
Com a separação, dist/k6.* referencia apenas k6/* e dist/playwright.*
apenas Node/Playwright/sharp. Não existe caminho de import que junte os dois.
O k6 continua precisando de bundler
O k6 não resolve pacotes por nome. Então, dentro de um teste k6,
import ... from 'automacao-core-carga-back/k6' só funciona se o seu
repositório tiver um passo de bundle (rollup/webpack) que resolva isso antes do
k6 run. Sem bundler, importe o artefato por caminho relativo:
import { K6AuthUtils } from './node_modules/automacao-core-carga-back/dist/k6.mjs';⚠️ Este core não guarda credenciais
Por decisão de projeto, nenhuma credencial, string de conexão, identificador de tenant ou usuário de teste vive neste pacote. Tudo isso é específico de ambiente e pertence a cada repositório de teste, que passa os valores como parâmetro.
Motivo: o pacote é publicado no npm, e qualquer valor aqui — inclusive dentro de dist/bundled.js — fica legível por quem instalar o pacote.
No seu repositório de teste:
# .env (não versionado) ou secrets do CI
K6_USERNAME=...
K6_PASSWORD=...
DB_USER=...
DB_PASSWORD=...
DB_HOST=...
DB_PORT=...
DB_NAME=...# k6 lê variáveis do sistema por padrão em `k6 run`; para `k6 cloud` ou
# `k6 archive` é preciso passar explicitamente com -e
k6 run -e DB_USER=$DB_USER -e DB_PASSWORD=$DB_PASSWORD test.jsEstrutura do pacote
src/
├── k6.js # Entry point do bundle k6
├── playwright.js # Entry point do bundle Playwright
├── types/
│ ├── k6.d.ts # Tipos de /k6
│ └── playwright.d.ts # Tipos de /playwright
└── lib/
├── k6/
│ ├── k6AuthUtils.js # paramsHeader(), login()
│ ├── k6DataUtils.js # criaSubArrays(), somaValores()
│ ├── k6DbUtils.js # abreConexao(), pesquisa(), converteDado(), etc.
│ ├── k6ReportUtils.js # gerarSummary() para handleSummary
│ └── k6NotificationsUtils.js # pesquisar(), aguardarTotal()
└── playwright/
├── comunsUtils.js # Login APM/Grafana, screenshots, combinarPrints, gerarUrl*
├── apmUtils.js # Serviços, transactions e traces no APM Elastic
├── grafanaUtils.js # Painéis RabbitMQ e Kubernetes no Grafana
└── pwIndex.js # Fixture: injeta page objects no contexto do testO pacote publicado contém apenas dist/ e src/types/ (ver campo files do
package.json). O build gera quatro artefatos:
| Arquivo | Formato | Consumido por |
|---|---|---|
| dist/k6.mjs | ESM | testes k6 (import) |
| dist/k6.cjs | CJS | testes k6 (require) |
| dist/playwright.mjs | ESM | specs Playwright (import) |
| dist/playwright.cjs | CJS | specs Playwright (require) |
As extensões explícitas tornam o formato inequívoco para o Node, e o mapa
exports do package.json roteia cada sintaxe para o arquivo certo.
k6
Autenticação
import { K6AuthUtils } from 'automacao-core-carga-back/k6';
import http from 'k6/http';
// Credenciais vêm do seu repositório, nunca do core.
export async function setup() {
return await K6AuthUtils.login(JSON.stringify({
username: __ENV.K6_USERNAME,
password: __ENV.K6_PASSWORD,
}));
}
export default function (token) {
const params = K6AuthUtils.paramsHeader(token);
http.get(url, params);
}Para múltiplos VUs, monte o SharedArray a partir de um arquivo do seu repositório:
import { SharedArray } from 'k6/data';
const usuarios = new SharedArray('usuarios', () =>
JSON.parse(open('./data/usuarios.json'))
);Banco de dados
import { K6DbUtils } from 'automacao-core-carga-back/k6';
const CONEXAO = `postgres://${__ENV.DB_USER}:${__ENV.DB_PASSWORD}@${__ENV.DB_HOST}:${__ENV.DB_PORT}/${__ENV.DB_NAME}`;
export function setup() {
const db = K6DbUtils.abreConexao(CONEXAO);
const result = K6DbUtils.pesquisa(db, 'SELECT id FROM schema.tabela WHERE id = 1');
const valor = K6DbUtils.converteDado(result, 'id');
K6DbUtils.fechaConexao(db);
}Requer um binário k6 com a extensão xk6-sql e o driver Postgres.
Relatório (handleSummary)
import { K6ReportUtils } from 'automacao-core-carga-back/k6';
export function handleSummary(data) {
return K6ReportUtils.gerarSummary(data, { nome: 'calculaImpostos' });
// gera: k6/imagensIA/calculaImpostos/k6calculaImpostos.json
}Override do destino via -e K6_JSON_DIR=... e -e K6_JSON_FILE=....
Helpers de array
import { K6DataUtils } from 'automacao-core-carga-back/k6';
const lotes = K6DataUtils.criaSubArrays(titulos, 10);
// [[t1..t10], [t11..t20], ...]
const somatorios = K6DataUtils.somaValores(lotes);
// ['123.50', '456.00', ...]Notificações
import { K6NotificationsUtils, K6AuthUtils } from 'automacao-core-carga-back/k6';
const params = K6AuthUtils.paramsHeader(token);
// Pesquisa simples:
const resultado = K6NotificationsUtils.pesquisar(JSON.stringify(input), params);
// Polling até N notificações:
K6NotificationsUtils.aguardarTotal(JSON.stringify(input), params, 5);Playwright
Fixture (injeção dos page objects)
Importe test do pacote em vez do @playwright/test diretamente:
import { test, expect } from 'automacao-core-carga-back/playwright';
// Disponível em cada test via page.*:
// page.comunsUtils → ComunsUtils (login, screenshots, combinarPrints, gerarUrl*)
// page.grafanaUtils → GrafanaUtils (painéis rabbit e kubernetes)
// page.apmUtils → ApmUtils (serviços, transactions, traces)Exemplo de spec APM
import { test } from 'automacao-core-carga-back/playwright';
import { CONTASRECEBER } from './helpers/urls.js';
test.describe('jornada para extração de dados do apm contas a receber', {
tag: ['@APMCONTASRECEBER', '@CONTASRECEBER'],
}, () => {
test.beforeEach(async ({ page }) => {
// Credenciais do APM saem do seu repositório (env/secrets).
await page.comunsUtils.loginApm({
usuario: process.env.APM_USUARIO,
senha: process.env.APM_SENHA,
});
const url = page.comunsUtils.gerarUrlApmComDataAtual(CONTASRECEBER, '10:37:00', '11:11:00');
await page.apmUtils.acessaTelaApm(url);
});
test('01 - bridge', {
tag: '@BRIDGEAPMCONTASRECEBER',
}, async ({ page }) => {
const pasta = 'playwright/resources/imagens/contasReceber';
await page.comunsUtils.tirarPrintTelaInteira('apm', pasta);
await page.apmUtils.acessarDetalhesServico('bridge');
await page.comunsUtils.tirarPrintTelaInteira('bridge', pasta);
await page.apmUtils.acessarDetalhesTransactions('POST /erpx_fin/contas_receber/queries/gerarBaixasCompostasReceber');
await page.comunsUtils.tirarPrintTelaInteira('gerarBaixas', pasta);
await page.comunsUtils.combinarPrints(['bridge', 'gerarBaixas'], 'bridge-completo', pasta, true);
});
});Exemplo de spec Grafana
import { test } from 'automacao-core-carga-back/playwright';
import { CONTASRECEBER } from './helpers/urls.js';
test.describe('jornada para extração de dados do grafana', {
tag: ['@GRAFANACONTASRECEBER'],
}, () => {
test('01 - painel rabbit', async ({ page }) => {
await page.comunsUtils.loginGrafana({
email: process.env.GRAFANA_EMAIL,
senha: process.env.GRAFANA_SENHA,
});
const url = page.comunsUtils.gerarUrlGrafanaComDataAtual(CONTASRECEBER, '10:37:00', '11:11:00');
await page.grafanaUtils.acessaTelaGrafana(url);
await page.grafanaUtils.validarGrafanaCarregado();
await page.grafanaUtils.ordenarMensagensTotal();
await page.grafanaUtils.acessarVisaoCompleta('Total/unacked messages');
await page.comunsUtils.tirarPrintTelaInteira('rabbit', 'playwright/resources/imagens');
await page.grafanaUtils.voltarParaDashboard();
});
});O que fica em cada repositório de módulo
| Artefato | Onde fica |
|---|---|
| Credenciais e config de ambiente (.env, secrets do CI) | Repo do módulo |
| Usuários de teste (data/usuarios.json) | Repo do módulo |
| String de conexão do banco e identificadores de tenant | Repo do módulo |
| playwright/helpers/urls.js — URLs APM/Grafana por cenário | Repo do módulo |
| k6/pages/erpx_*/ — page objects de APIs de negócio | Repo do módulo |
| k6/json/erpx_*/ — payloads de request | Repo do módulo |
| k6/tests/ — scripts de teste | Repo do módulo |
Como adicionar uma nova função ao core
- Crie ou edite o arquivo em
src/lib/k6/ousrc/lib/playwright/ - Exporte via classe estática:
export class MinhaClasse { static meuMetodo() {} } - Use
import(o core é ESM;requirenão é usado em nenhum arquivo) - Registre o export no entry point do lado correspondente:
src/k6.jsousrc/playwright.js - Declare o tipo em
src/types/k6.d.tsousrc/types/playwright.d.ts. Essas declarações são self-contained de propósito: não re-exporte desrc/lib/, que não vai no pacote publicado - Documente com JSDoc (
@param,@returns,@example) - Nunca adicione credencial, host ou usuário — receba por parâmetro
- Execute
npm run buildenpm run eslintantes do MR - Abra o MR usando o template em
.github/pull_request_template.md
Não cruze os runtimes
Um arquivo em src/lib/k6/ não pode importar node:*, @playwright/test,
sharp ou qualquer pacote npm — só k6/*. Um arquivo em src/lib/playwright/
não pode importar k6/*. Se precisar de lógica comum aos dois, ela tem que ser
JavaScript puro, sem import nenhum, e ficar duplicada ou num arquivo sem
dependências.
Para conferir que nada vazou depois do build:
# nenhum dos dois comandos deve retornar resultado
grep -l "k6/" dist/playwright.*
grep -lE "@playwright/test|sharp|node:" dist/k6.*Release
O pipeline de release é disparado manualmente via Actions → Release → Run workflow.
Selecione o tipo de bump:
patch— bug fix ou ajuste internominor— nova função sem quebrar compatibilidademajor— breaking change
O workflow faz o bump de versão, cria a tag e publica no npm no mesmo run.
A separação em dois entry points removeu o import raiz do pacote. Todo repositório consumidor precisa trocar
from 'automacao-core-carga-back'por/k6ou/playwright, então essa mudança exige release major.
