@analizza-ai/testspec 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +189 -0
  4. package/bin/cli.js +42 -0
  5. package/package.json +69 -0
  6. package/src/adapters/agents/claude.js +88 -0
  7. package/src/adapters/agents/copilot.js +39 -0
  8. package/src/adapters/agents/index.js +22 -0
  9. package/src/adapters/sdd/index.js +23 -0
  10. package/src/adapters/sdd/openspec.js +58 -0
  11. package/src/adapters/sdd/speckit.js +19 -0
  12. package/src/commands/generate.js +66 -0
  13. package/src/commands/init.js +112 -0
  14. package/src/commands/report.js +60 -0
  15. package/src/commands/validate.js +68 -0
  16. package/src/core/reporter.js +44 -0
  17. package/src/core/spec-parser.js +141 -0
  18. package/src/core/stub-generator.js +92 -0
  19. package/src/core/testcontainers.js +39 -0
  20. package/src/core/tests-builder.js +120 -0
  21. package/src/index.js +10 -0
  22. package/src/utils/config.js +29 -0
  23. package/src/utils/logger.js +13 -0
  24. package/src/utils/sdd-detector.js +23 -0
  25. package/templates/agent-instructions/AGENTS.md +39 -0
  26. package/templates/agent-instructions/CLAUDE.md +48 -0
  27. package/templates/agent-instructions/copilot.md +52 -0
  28. package/templates/agent-instructions/skills/testspec-apply-qa.md +424 -0
  29. package/templates/agent-instructions/skills/testspec-generate.md +138 -0
  30. package/templates/agent-instructions/skills/testspec-run-qa.md +338 -0
  31. package/templates/agent-instructions/skills/testspec-specify-qa.md +535 -0
  32. package/templates/stubs/jest/unit.template.js +17 -0
  33. package/templates/stubs/junit/unit.template.java +27 -0
  34. package/templates/stubs/pytest/unit.template.py +18 -0
  35. package/templates/stubs/testcontainers/node-pg-kafka.template.js +38 -0
  36. package/templates/stubs/testcontainers/node-pg.template.js +32 -0
  37. package/templates/stubs/testcontainers/spring-pg-kafka.template.java +41 -0
  38. package/templates/stubs/vitest/unit.template.js +19 -0
  39. package/templates/tests-md/default.md +43 -0
@@ -0,0 +1,138 @@
1
+ # testspec-generate
2
+
3
+ Gera o arquivo `tests.md` para uma feature do openspec, consolidando todos os `spec.md` da feature e enriquecendo com critérios de aceite técnicos e genéricos de tecnologia.
4
+
5
+ ## Quando usar
6
+
7
+ Após `/opsx:propose` — quando todos os `spec.md` da feature estiverem criados e o `design.md` existir.
8
+
9
+ ## Instructions
10
+
11
+ ### 1. Identificar a feature
12
+
13
+ - Se um argumento foi passado (nome ou caminho da feature), use-o diretamente.
14
+ - Caso contrário, liste os diretórios em `openspec/changes/` e pergunte ao usuário qual feature processar usando **AskUserQuestion**.
15
+
16
+ ### 2. Ler os arquivos-base
17
+
18
+ Leia **todos** os arquivos nesta ordem:
19
+ 1. `openspec/changes/<feature>/design.md`
20
+ 2. Todos os arquivos `openspec/changes/<feature>/specs/**/spec.md` (pode ser mais de um)
21
+
22
+ ### 3. Gerar o `tests.md`
23
+
24
+ Crie o arquivo em `openspec/changes/<feature>/tests.md` seguindo rigorosamente o **Formato de Saída** abaixo.
25
+
26
+ **Regras de geração:**
27
+ - Escrito inteiramente em **português**
28
+ - **Tecnologia-agnóstico**: use termos universais — `HTTP Method`, `HTTP Status Code`, `URL`, `Content-Type`, campos JSON com tipo explícito (`<String>`, `<Decimal>`, `<Long>`, `<Boolean>`)
29
+ - Para cada `### Requirement` nos spec.md, gere um ou mais casos de teste (`CT-NN`)
30
+ - Para cada `#### Scenario` nos spec.md, gere exatamente um caso de teste
31
+ - Enriqueça cada caso de teste com critérios de aceite além do que o cenário descreve: validações de status HTTP, campos do body da resposta, estado no banco de dados, etc.
32
+ - A seção **Validações de Banco de Dados** só aparece quando o design.md descreve persistência
33
+ - A seção **Fora de Escopo** deve ser derivada dos Non-Goals do `proposal.md` (se disponível) ou do `design.md`
34
+
35
+ ### 4. Confirmar criação
36
+
37
+ Exiba ao usuário:
38
+ ```
39
+ tests.md criado em openspec/changes/<feature>/tests.md
40
+ Casos de teste: <N>
41
+ Specs consolidadas: <lista dos spec.md lidos>
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Formato de Saída (`tests.md`)
47
+
48
+ ```markdown
49
+ # Testes — <Nome Legível da Feature>
50
+
51
+ > Documento de especificação de testes de integração e E2E.
52
+ > Tecnologia-agnóstico: use HTTP padrão para qualquer linguagem ou ferramenta.
53
+
54
+ ---
55
+
56
+ ## Contexto
57
+
58
+ <Resumo do que a feature faz, derivado do design.md. 2-4 linhas.>
59
+
60
+ **Recurso:** `<path>`
61
+ **Método HTTP:** `<METHOD>` ← omitir se não for HTTP
62
+ **Banco de dados:** `<tabela>` ← omitir se não houver persistência
63
+
64
+ ---
65
+
66
+ ## Estrutura da Requisição ← omitir se não for HTTP
67
+
68
+ \`\`\`
69
+ HTTP Method : <METHOD>
70
+ URL : <path>
71
+ Content-Type: application/json
72
+
73
+ Body:
74
+ {
75
+ "<campo>": <Tipo>, -- descrição
76
+ }
77
+ \`\`\`
78
+
79
+ ## Estrutura da Resposta (sucesso) ← omitir se não houver body de resposta
80
+
81
+ \`\`\`
82
+ HTTP Status : <código>
83
+ Content-Type: application/json
84
+
85
+ Body:
86
+ {
87
+ "<campo>": <Tipo>,
88
+ }
89
+ \`\`\`
90
+
91
+ ---
92
+
93
+ ## Casos de Teste
94
+
95
+ ### CT-01 — <Nome do cenário>
96
+
97
+ **Descrição:** <o que este teste valida>
98
+
99
+ **Pré-condição:** <estado necessário antes de executar>
100
+
101
+ **Entrada:**
102
+ \`\`\`
103
+ <representação tecnologia-agnóstica da entrada>
104
+ \`\`\`
105
+
106
+ **Critérios de Aceite:**
107
+ - <critério 1>
108
+ - <critério 2>
109
+ - ...
110
+
111
+ ---
112
+
113
+ ### CT-NN — ...
114
+
115
+ ---
116
+
117
+ ## Validações de Banco de Dados ← incluir somente se houver persistência
118
+
119
+ <tabela com colunas e valores esperados para o cenário de sucesso>
120
+ <instrução de COUNT para cenários de rejeição>
121
+
122
+ ---
123
+
124
+ ## Fora de Escopo
125
+
126
+ - <item 1>
127
+ - <item 2>
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Guardrails
133
+
134
+ - Nunca copiar blocos `<context>` ou `<rules>` do openspec para o arquivo gerado
135
+ - Nunca usar nomes de classes, anotações ou frameworks no `tests.md` (ex: `@SpringBootTest`, `BigDecimal`, `KafkaContainer`)
136
+ - Sempre numerar casos de teste sequencialmente: CT-01, CT-02, ...
137
+ - Se houver múltiplos `spec.md`, consolidar todos no mesmo `tests.md` agrupando por capability
138
+ - Se `tests.md` já existir, perguntar ao usuário se deseja sobrescrever ou atualizar
@@ -0,0 +1,338 @@
1
+ # testspec-run-qa
2
+
3
+ Agente de execução de testes QA. Lê um run plan `.md`, executa o script de teste, coleta logs via MCP (k8s/Splunk), analisa dados do banco via MCP, gera relatório consolidado e publica no Confluence via MCP.
4
+
5
+ ## Quando usar
6
+
7
+ Após `/testspec-apply-qa` ter gerado os scripts e seus run plans `.md`.
8
+
9
+ ---
10
+
11
+ ## Instructions
12
+
13
+ ### 0. Ler arquivos globais do projeto QA (SEMPRE, primeiro passo)
14
+
15
+ Leia **ambos** em paralelo — são obrigatórios:
16
+
17
+ **`./testspec/instructions.md`**
18
+ - Contém: MCPs disponíveis, credenciais de ambiente, URLs base, namespaces k8s, espaço Confluence, padrões do projeto
19
+ - **Esta é a fonte de configuração do agente** — leia com atenção antes de qualquer ação
20
+
21
+ **`./testspec/current-feature.md`**
22
+ - Contém: nome da feature em foco
23
+ - Se preenchido, pule a etapa de seleção de feature (passo 1)
24
+ - Se vazio, execute o passo 1
25
+
26
+ ---
27
+
28
+ ### 1. Identificar a feature
29
+
30
+ **Se argumento passado:** use diretamente como nome da feature.
31
+
32
+ **Se `current-feature.md` preenchido:** use o nome registrado — pule para o passo 2.
33
+
34
+ **Se nenhum dos dois:** liste os diretórios em `./src/test/features/` e pergunte via **AskUserQuestion** (single select):
35
+ > "Qual feature deseja executar os testes?"
36
+
37
+ **Após identificar:** escreva o nome em `./testspec/current-feature.md`.
38
+
39
+ ---
40
+
41
+ ### 2. Listar run plans disponíveis
42
+
43
+ Varra recursivamente `./src/test/features/{feature-name}/` buscando arquivos `.md` (excluindo subdiretórios sem `.md`).
44
+
45
+ Monte a lista agrupada por categoria:
46
+
47
+ ```
48
+ E2E:
49
+ [ ] src/test/features/{feature-name}/e2e/k6-e2e-create-order-success.md
50
+ [ ] src/test/features/{feature-name}/e2e/k6-e2e-create-order-bad-request-zero-value.md
51
+
52
+ Load:
53
+ [ ] src/test/features/{feature-name}/load/k6-load-create-order-success-100-rps-5min.md
54
+ [ ] src/test/features/{feature-name}/load/k6-load-create-order-success-1000-rps-5min.md
55
+
56
+ Chaos:
57
+ [ ] src/test/features/{feature-name}/chaos-engineering/k6-dr-create-order-success-shutdown-pods.md
58
+ ```
59
+
60
+ Se não houver nenhum `.md`, informe e encerre:
61
+ ```
62
+ Nenhum run plan encontrado em src/test/features/{feature-name}/.
63
+ Execute /testspec-apply-qa primeiro.
64
+ ```
65
+
66
+ ---
67
+
68
+ ### 3. Selecionar run plan(s) a executar
69
+
70
+ Use **AskUserQuestion** (multi select) com a lista montada no passo 2:
71
+ > "Quais run plans deseja executar agora?"
72
+
73
+ Opções adicionais fixas (sempre presentes):
74
+ - **Todos os E2E** — executa todos os `.md` da pasta `e2e/`
75
+ - **Todos os Load** — executa todos os `.md` da pasta `load/`
76
+ - **Todos (E2E + Load + Chaos)** — executa tudo
77
+
78
+ Registre a lista final de run plans selecionados — execute-os **em sequência**, um por vez.
79
+
80
+ ---
81
+
82
+ ### 4. Para cada run plan selecionado — ciclo de execução
83
+
84
+ Repita os passos 4a a 4f para cada `.md` selecionado.
85
+
86
+ ---
87
+
88
+ #### 4a. Ler o run plan
89
+
90
+ Leia o arquivo `.md` e extraia:
91
+ - **Script** — caminho do arquivo de teste (`.js`, `.scala`, etc.)
92
+ - **Ferramenta** — k6, Gatling, etc.
93
+ - **Comando** — comando base de execução
94
+ - **Variáveis de ambiente** — lista de `__ENV.*` necessárias
95
+ - **Coleta de Logs** — fonte (k8s e/ou Splunk), namespace, pod selector, query, janela de tempo
96
+ - **Análise de Banco** — tabela e queries SQL
97
+ - **Relatório** — seções esperadas
98
+ - **Publicação** — espaço Confluence, página pai, título
99
+
100
+ ---
101
+
102
+ #### 4b. Validar pré-condições
103
+
104
+ Antes de executar, verifique:
105
+
106
+ - [ ] O arquivo de script existe no caminho indicado pelo run plan
107
+ - [ ] Todas as variáveis de ambiente obrigatórias estão definidas (leia de `instructions.md` ou ambiente)
108
+ - [ ] O MCP de banco está acessível (se o run plan exige análise de banco)
109
+ - [ ] O MCP do Confluence está acessível (se o run plan exige publicação)
110
+
111
+ Se qualquer pré-condição falhar, informe o problema específico e pergunte via **AskUserQuestion**:
112
+ - **Continuar mesmo assim** — executa e documenta a limitação no relatório
113
+ - **Cancelar** — encerra este run plan e passa para o próximo
114
+
115
+ ---
116
+
117
+ #### 4c. Executar o script de teste
118
+
119
+ Execute o script conforme a ferramenta:
120
+
121
+ **k6:**
122
+ ```bash
123
+ BASE_URL={url_base} {outras_env_vars} k6 run {caminho_do_script}
124
+ ```
125
+
126
+ **Gatling:**
127
+ ```bash
128
+ {GATLING_HOME}/bin/gatling.sh -sf {caminho_do_script}
129
+ ```
130
+
131
+ Registre:
132
+ - **Hora de início** (`start_time`)
133
+ - **Hora de fim** (`end_time`)
134
+ - **Duração total**
135
+ - **Saída completa do stdout/stderr** — capture tudo
136
+ - **Métricas extraídas da saída:**
137
+ - k6: `http_req_duration` (p50, p95, p99), `http_req_failed` (rate), `iterations`, `vus_max`
138
+ - Gatling: `response time` (mean, p95, p99), `requests/s`, `errors`
139
+ - **Status final:** `PASSED` se exit code = 0 e thresholds atendidos; `FAILED` caso contrário
140
+
141
+ ---
142
+
143
+ #### 4d. Coletar logs
144
+
145
+ Execute **em paralelo** todas as fontes de log definidas no run plan.
146
+
147
+ **k8s (se configurado em `instructions.md`):**
148
+
149
+ ```bash
150
+ kubectl logs -n {namespace} -l {pod_selector} --since-time={start_time} --until-time={end_time}
151
+ ```
152
+
153
+ - Se kubectl não disponível via Bash, use o MCP de k8s configurado em `instructions.md`
154
+ - Filtre as linhas relevantes: erros, warnings, stack traces, linhas com o request ID ou correlation ID do teste
155
+ - Registre: total de linhas capturadas, linhas de erro encontradas
156
+
157
+ **Splunk (se configurado em `instructions.md`):**
158
+
159
+ - Execute a query definida no run plan com a janela `start_time` a `end_time`
160
+ - Use o MCP do Splunk configurado em `instructions.md`
161
+ - Registre: total de eventos, eventos de erro, sample dos 5 mais relevantes
162
+
163
+ Se uma fonte não estiver disponível: registre `"fonte indisponível"` no relatório — não encerre a execução.
164
+
165
+ ---
166
+
167
+ #### 4e. Analisar banco de dados
168
+
169
+ Execute cada query definida na seção `## Análise de Banco de Dados` do run plan.
170
+
171
+ Use o MCP de banco configurado em `instructions.md` (PostgreSQL, Oracle, etc.).
172
+
173
+ Para cada query:
174
+ - Execute e capture o resultado
175
+ - Compare com o critério esperado definido no run plan
176
+ - Registre: `PASSOU` / `FALHOU` com valor obtido vs esperado
177
+
178
+ Se o MCP de banco não estiver disponível: registre `"banco indisponível"` — não bloqueie o relatório.
179
+
180
+ ---
181
+
182
+ #### 4f. Gerar o relatório
183
+
184
+ Monte o relatório em Markdown com as seguintes seções obrigatórias:
185
+
186
+ ```markdown
187
+ # QA Report — {feature-name} — {script-name} — {YYYY-MM-DD HH:mm}
188
+
189
+ ## Resumo
190
+
191
+ | Campo | Valor |
192
+ |-----------------|--------------------------------|
193
+ | Feature | {feature-name} |
194
+ | Script | {script-name}.js |
195
+ | Ferramenta | {k6 | Gatling} |
196
+ | Início | {start_time} |
197
+ | Fim | {end_time} |
198
+ | Duração | {duração} |
199
+ | Status Final | ✅ PASSED / ❌ FAILED |
200
+
201
+ ## Métricas de Execução
202
+
203
+ {tabela com p50/p95/p99, error rate, RPS, VUs — valores reais da saída do script}
204
+
205
+ ## Critérios de Aceite
206
+
207
+ | # | Critério | Esperado | Obtido | Status |
208
+ |---|-----------------------------------------|----------------|----------------|--------|
209
+ | 1 | {critério do run plan} | {valor esp.} | {valor obt.} | ✅/❌ |
210
+ | N | ... | ... | ... | ... |
211
+
212
+ ## Logs — k8s
213
+
214
+ - **Linhas capturadas:** {N}
215
+ - **Erros encontrados:** {N}
216
+
217
+ ```
218
+ {amostra das linhas mais relevantes — máximo 20 linhas}
219
+ ```
220
+
221
+ ## Logs — Splunk
222
+
223
+ - **Eventos:** {N}
224
+ - **Erros:** {N}
225
+
226
+ ```
227
+ {amostra dos 5 eventos mais relevantes}
228
+ ```
229
+
230
+ ## Análise de Banco de Dados
231
+
232
+ | Query | Esperado | Obtido | Status |
233
+ |-------------------------------|----------|--------|--------|
234
+ | {query resumida} | {val} | {val} | ✅/❌ |
235
+
236
+ ## Saída do Script (stdout)
237
+
238
+ <details>
239
+ <summary>Expandir saída completa</summary>
240
+
241
+ ```
242
+ {stdout completo do script}
243
+ ```
244
+
245
+ </details>
246
+
247
+ ## Conclusão
248
+
249
+ **Resultado:** ✅ APROVADO / ❌ REPROVADO
250
+
251
+ {2-3 linhas explicando o resultado. Se reprovado: qual critério falhou, valor obtido vs esperado, e recomendação de ação.}
252
+ ```
253
+
254
+ ---
255
+
256
+ #### 4g. Publicar no Confluence
257
+
258
+ Use o MCP do Confluence configurado em `instructions.md`.
259
+
260
+ - **Espaço:** conforme run plan
261
+ - **Página pai:** conforme run plan
262
+ - **Título:** `QA Report — {feature-name} — {script-name} — {YYYY-MM-DD}`
263
+ - **Ação:** se já existe página com o mesmo título → atualizar; caso contrário → criar
264
+ - **Conteúdo:** o relatório gerado no passo 4f (converter Markdown para formato Confluence se necessário)
265
+
266
+ Após publicar: exiba a URL da página criada/atualizada.
267
+
268
+ Se Confluence indisponível: salve o relatório localmente em:
269
+ ```
270
+ ./reports/{feature-name}/{script-name}-{YYYY-MM-DD-HHmm}.md
271
+ ```
272
+ E informe o usuário com o caminho do arquivo.
273
+
274
+ ---
275
+
276
+ #### 4h. Reportar progresso do run plan
277
+
278
+ Após concluir cada run plan:
279
+
280
+ ```
281
+ ──────────────────────────────────────────────────
282
+ Run Plan: {script-name}.md
283
+ Status: ✅ PASSED / ❌ FAILED
284
+ Duração: {X}s
285
+ Métricas: p95={X}ms | errors={X}% | RPS={X}
286
+ Banco: ✅ {N}/{N} queries OK / ❌ {N} falha(s)
287
+ Logs: k8s={N} linhas | Splunk={N} eventos
288
+ Confluence: {URL da página} / salvo em {path}
289
+ ──────────────────────────────────────────────────
290
+ ```
291
+
292
+ ---
293
+
294
+ ### 5. Relatório consolidado final
295
+
296
+ Após executar todos os run plans selecionados:
297
+
298
+ ```
299
+ ══════════════════════════════════════════════════
300
+ EXECUÇÃO CONCLUÍDA — {feature-name}
301
+ ══════════════════════════════════════════════════
302
+
303
+ Run plans executados: {N}
304
+ ✅ PASSED: {N}
305
+ ❌ FAILED: {N}
306
+
307
+ Detalhes:
308
+ ✅ k6-e2e-create-order-success p95=120ms errors=0%
309
+ ❌ k6-e2e-create-order-bad-request status=200 (esperado 400)
310
+ ✅ k6-load-create-order-100-rps-5min p95=310ms errors=0.1%
311
+
312
+ Relatórios publicados no Confluence:
313
+ - {URL 1}
314
+ - {URL 2}
315
+
316
+ Relatórios salvos localmente (Confluence indisponível):
317
+ - {path} (se aplicável)
318
+
319
+ Próximos passos:
320
+ - Investigar falhas: {lista de run plans com FAILED}
321
+ - Re-executar: /testspec-run-qa {feature-name}
322
+ ══════════════════════════════════════════════════
323
+ ```
324
+
325
+ ---
326
+
327
+ ## Guardrails
328
+
329
+ - **`instructions.md` é a fonte de configuração de todos os MCPs** — nunca assuma URLs, namespaces, credenciais ou espaços Confluence; leia de lá
330
+ - **`current-feature.md` é escrito sempre** após identificar a feature — passo 1
331
+ - **Execute um run plan por vez, em sequência** — não paralelize execuções de script; logs e métricas se misturariam
332
+ - **Nunca cancele a suite por falha de um run plan** — continue os demais e reporte tudo no consolidado final
333
+ - **Janela de coleta de logs** = `start_time` até `end_time` do script — nunca colete logs fora dessa janela
334
+ - **Confluence indisponível não é erro fatal** — salve localmente e informe; não bloqueie o fluxo
335
+ - **Banco indisponível não é erro fatal** — registre no relatório como `"indisponível"` e prossiga
336
+ - **Nunca execute comandos destrutivos** ao coletar logs ou analisar banco — apenas `SELECT`, `kubectl logs`, queries de leitura
337
+ - **Relatório sempre gerado mesmo se o script falhar** — o relatório de falha é tão importante quanto o de sucesso
338
+ - **Saída completa do script** sempre capturada e incluída no relatório (dentro de `<details>`) — nunca truncar silenciosamente