Faça assert do formato e timing da response
Uma seção # expect: transforma um bloco de “me mostra o que
voltou” em “falhe o runbook se qualquer um desses não for
verdade”. Útil pra smoke tests commitados no git e rodados como
step de CI, ou pro check local “será que staging derivou desde
ontem?”.
Sintaxe
Seção intitulada “Sintaxe”Dentro de qualquer bloco (HTTP ou DB), adicione uma seção começando
com # expect: em uma linha própria. Cada linha embaixo é uma
assertion: <campo> <operador> <valor>.
```httpGET {{BASE_URL}}/health
# expect:# status == 200# time < 500ms# body.status == "ok"# body.version matches /^v\\d+\\.\\d+\\.\\d+$/```Tudo depois de # expect: até o fence de fechamento (ou uma linha
em branco seguida de conteúdo não-#) é parseado como assertions.
Campos em que você pode dar assert
Seção intitulada “Campos em que você pode dar assert”Os mesmos campos das referências entre blocos, mais dois só-HTTP:
| Campo | Notas |
|---|---|
status | status HTTP numérico |
time | tempo total (em ms / s) |
size | bytes do body da response |
body.<path> | JSON path |
headers.<name> | header de response (case-insensitive) |
cookies.<name> | valor de set-cookie |
affected | só DB — contagem de linhas de INSERT/UPDATE/DELETE |
row[N].<col> | só DB — coluna da n-ésima linha de resultado |
rows.length | só DB — número de linhas retornadas |
Operadores
Seção intitulada “Operadores”| Operador | Significado | Funciona em |
|---|---|---|
== | igualdade estrita | strings, numbers, booleans, null |
!= | diferente | mesmo |
< <= > >= | comparação numérica | numbers (incl. time, size) |
contains | substring ou membership de array | strings, arrays |
not contains | inverso de contains | strings, arrays |
matches | match regex | strings (regex entre /.../) |
exists | path resolve (sem RHS) | qualquer campo |
not exists | inverso | qualquer campo |
is | check de tipo (number, string, array, object, null) | qualquer campo |
Unidades de tempo
Seção intitulada “Unidades de tempo”time e size aceitam sufixos:
time < 500mstime < 1.5stime < 1msize < 10kbsize < 100mb| Sufixo | Significado |
|---|---|
ms | milissegundos |
s | segundos |
m | minutos (raro) |
b / kb / mb / gb | bytes (potências de 1024) |
Sem sufixo significa integer puro (time < 500 é < 500ms por
default, já que time está em ms; size < 100 é bytes).
Assertions cross-block com referências
Seção intitulada “Assertions cross-block com referências”Referências funcionam dentro de # expect: como em qualquer outro
lugar:
```http alias=cutoffGET {{BASE_URL}}/last-sync```
```httpGET {{BASE_URL}}/changes
# expect:# status == 200# body.since == {{cutoff.body.timestamp}}# body.changes.length > 0```Útil pra checks “a API concordou com o que pegamos da última vez?”.
Comportamento em falha
Seção intitulada “Comportamento em falha”Quando qualquer assertion falha:
- A toolbar do bloco fica vermelha.
- O painel de resultado mostra expected vs actual lado a lado:
✗ status == 200expected: 200actual: 503✓ time < 500ms (143ms)✗ body.status == "ok"expected: "ok"actual: "degraded"
- Blocos downstream não rodam num Run-all — o httui curto-circuita na primeira falha.
- A contagem pass/fail da status bar atualiza:
2 passed · 1 failed.
Run-all e CI
Seção intitulada “Run-all e CI”Aperte Cmd+Shift+Enter (ou clique em Run all na status
bar) pra rodar todo bloco de cima pra baixo. O sumário mostra
total pass/fail entre todas as seções # expect:.
Pra CI, o binário httui-tui pega o mesmo vault e consegue rodar
runbooks específicos:
httui-tui run runbooks/smoke-staging.md --env staging# sai 0 se todos os expects passam, não-zero se algum falhouEncadeie no seu step de CI como qualquer outro comando de teste.
Pular uma assertion temporariamente
Seção intitulada “Pular uma assertion temporariamente”Comente com um # extra:
# expect:# status == 200## time < 500ms ← pulado (instável em cache frio)# body.status == "ok"O ## duplo é a convenção do httui pra “ignore essa linha de
expect”. Melhor que deletar porque a intenção fica preservada.
Múltiplas seções expect
Seção intitulada “Múltiplas seções expect”Você pode ter mais de uma — elas são agregadas:
GET {{BASE_URL}}/users
# expect:# status == 200
GET {{BASE_URL}}/users/admin
# expect:# status == 200# body.role == "admin"Cada # expect: aplica ao bloco mais recente. Útil quando o bloco
tem sub-passos lógicos que você quer assertar separadamente.
Gotchas comuns
Seção intitulada “Gotchas comuns”| Sintoma | Causa | Correção |
|---|---|---|
Check body.X exists falha em null | exists retorna false pra campos de body null | Use body.X is null pra distinguir |
| Regex não matcha | Esqueceu de escapar / dentro do regex | matches /^v\\d+\\/release$/ (escape / como \\/) |
| Assertion de time sempre falha na primeira run | Conexão fria / lookup DNS | Primeira run baseline é mais lenta; considere time < <p99-de-runs-típicas> |
| Mismatch de case em assertion de header | Headers HTTP são case-insensitive — o httui normaliza | headers.content-type e headers.Content-Type são iguais |
Relacionado
Seção intitulada “Relacionado”- Monte um teste de API encadeado —
veja
# expect:num fluxo real. - Referencie valores entre blocos — use refs dentro de assertions pra checks cross-block.