Talking About TestingATT</>
Testes Agênticos com Cypress Tap

Acerte 100% do quiz para continuar

Aula
Prévia gratuita

O Cypress Tap, à mão

Conduza o Cypress Tap você mesmo: execute uma spec, espere um veredito novo, leia a aplicação e viaje no tempo.

Antes de entregar o Cypress Tap a um agente, você vai conduzi-lo você mesmo, uma vez, à mão. Tudo o que o seu agente faz neste curso, ele faz com os comandos desta aula. Conhecê-los é o que permite conferir as afirmações dele em vez de acreditar nelas.

O que é o Cypress Tap

O Cypress Tap é um conjunto de comandos, npx cypress tap <comando>, que conduzem uma sessão do cypress open já em execução a partir do terminal. Ele vem dentro do Cypress App (Cypress 15.21.0 em diante), então não há nada a mais para instalar. É gratuito, não precisa de conta no Cypress Cloud e roda só na sua máquina.

Três coisas para saber antes do primeiro comando:

  • Ele se conecta ao cypress open, nunca ao cypress run. O Tap lê o mesmo Command Log e os mesmos snapshots do DOM que você vê na janela do Cypress, então a janela precisa estar aberta. Execuções headless, como as da CI, não são alcançáveis.
  • Ele só funciona em navegadores baseados no Chromium: Chrome, Chromium, Edge e Electron. É por isso que o script cy:open que você escreveu na aula de configuração passa --browser chrome.
  • O terminal e a janela do Cypress compartilham um único frame do navegador, sem trava entre eles. Se você clicar pela aplicação na janela do Cypress enquanto o Tap (ou o seu agente) a está lendo, cada um vê as mudanças do outro. Observe a janela; não mexa nela.
👨‍🏫 O Cypress Tap está em beta. Os seus comandos e a sua saída ainda podem mudar em qualquer release, o que é mais um motivo para a aula de configuração ter fixado o Cypress em uma versão exata.

O fluxo de trabalho

Todo teste deste curso é escrito do mesmo jeito, seja por você, seja pelo seu agente. Estes seis passos vêm do guia do Tap do projeto, o docs/cypress/07-cypress-tap.md:

  1. Preparar o estado da página com uma spec mínima. O Tap só consegue ler a aplicação depois que uma spec a levou a algum lugar.
  2. Ler a aplicação real com aria, dom e inspect para escolher seletores e textos esperados.
  3. Escrever o teste: agir e verificar.
  4. Esperar um veredito novo.
  5. Ler os resultados e o Command Log.
  6. Refinar as asserções usando o que a aplicação realmente mostra.

O passo 4 é o que as pessoas erram, então ele ganha uma seção própria logo abaixo.

Esperando um veredito novo

O run retorna antes de a spec ter começado. E, até a nova execução começar, o status continua mostrando o veredito da execução anterior. Então um passed logo depois de um run pode estar descrevendo a execução de antes.

A única forma segura de esperar é comparar o startedAt:

  1. Antes de executar (ou salvar) a spec, anote o startedAt atual do npx cypress tap status --json. Não depois: àquela altura a nova execução pode já ter começado, e você esperaria para sempre por uma execução que já aconteceu.
  2. Consulte o npx cypress tap status --json a cada dois segundos, mais ou menos, uma chamada por vez.
  3. Aceite só passed ou failed, para a spec que você espera, com um startedAt diferente do que você anotou.
  4. Desista depois de um número limitado de tentativas, e pare na hora se o status terminar com 1.

Aqui está esse ciclo como um script Bash, que usa o Node.js para ler o JSON. Execute-o em um terminal na raiz do seu projeto: no macOS e no Linux, o terminal padrão serve; no Windows, use o Git Bash, como recomendado nos pré-requisitos. Troque o valor de base pelo startedAt que você anotou (ou deixe como null antes da primeira execução):

base="null"
for i in $(seq 1 60); do
  out=$(npx cypress tap status --json 2>/dev/null) || { echo "status failed"; break; }
  s=$(echo "$out" | node -e 'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>{try{const j=JSON.parse(d);console.log(j.status+"|"+j.startedAt)}catch{console.log("?|?")}})')
  st=${s%%|*}; sa=${s#*|}
  if { [ "$st" = passed ] || [ "$st" = failed ]; } && [ "$sa" != null ] && [ "$sa" != undefined ] && [ "$sa" != "?" ] && [ "$sa" != "$base" ]; then
    echo "$st $sa"; break
  fi
  sleep 2
done

Você raramente vai digitá-lo: é o que o seu agente executa, e o guia do Tap do projeto o traz. Mas você precisa saber lê-lo, porque quando um agente diz "o teste passou", é assim que ele deveria saber.

Salvar uma spec a executa

Depois que uma spec está selecionada (a que o status mostra), o Cypress a observa: salvá-la inicia uma nova execução sozinha, exatamente como quando você trabalha na janela do Cypress. Então, depois de editar a spec selecionada, não chame o run também, ou você coloca duas execuções em andamento ao mesmo tempo. Anote o startedAt, salve e espere.

👨‍🏫 O observador só executa de novo a spec selecionada. Salvar outra spec não a executa; para isso, use npx cypress tap run <spec>.

Visão geral dos comandos 📖

Todo comando aceita estas opções compartilhadas:

  • --json imprime uma saída legível por máquina em vez de uma tabela.
  • --session <pid> (ou -s) escolhe uma sessão quando há mais de um cypress open em execução.
  • --timeout <ms> define quanto tempo o Tap espera a sessão responder (padrão 30000).
  • --help (ou -h) imprime como usar o comando.

Todo comando termina com 0 em caso de sucesso e 1 em caso de falha, para que um agente (ou um script) saiba a diferença sem ler a saída.

sessions

Lista as sessões do cypress open em execução: id do processo (PID), pasta do projeto, tipo de teste e navegador.

Sintaxe:

npx cypress tap sessions

Exemplo:

npx cypress tap sessions --json

status

Informa em que ponto do seu ciclo de vida a sessão está, qual spec está selecionada e as contagens da última execução. Os estágios são not connected, browser not selected, spec not selected, loading, running, passed e failed. Só passed e failed são vereditos; todo o resto significa "não terminou".

Sintaxe:

npx cypress tap status [--json]

Exemplo:

npx cypress tap status --json

Com --json, procure status, spec, startedAt (quando a execução atual começou, null até uma execução começar), totalTests e results (as contagens de passed, failed, pending e skipped).

specs

Lista as specs que a sessão consegue executar, das modificadas mais recentemente para as mais antigas.

Sintaxe:

npx cypress tap specs

Exemplo:

npx cypress tap specs

run

Inicia uma spec e retorna imediatamente, antes de um único teste ter rodado. Ele não espera pelo veredito, nem o imprime.

Sintaxe:

npx cypress tap run <caminho-da-spec>

Exemplo:

npx cypress tap run cypress/e2e/explore.cy.js

reporter

Sem --test-id, imprime a visão geral da spec, como o painel do reporter da janela do Cypress: cada teste com o seu resultado e um id de teste (como r2). Com --test-id, imprime o Command Log completo daquele teste: hooks, cada comando, as requisições de rede e o erro, se houver. --attempt escolhe uma nova tentativa (começando em 1).

Sintaxe:

npx cypress tap reporter [--test-id <id>] [--attempt <n>]

Exemplo:

npx cypress tap reporter --test-id r2
👨‍🏫 Copie os ids de teste da saída do reporter. Nunca os deduza da ordem dos testes na spec.

command

Imprime em detalhe uma linha do Command Log de um teste: os seus snapshots e as suas propriedades de console. --command-id é o número da linha no reporter --test-id.

Sintaxe:

npx cypress tap command --test-id <id> --command-id <linha> [--depth <n|all>]

Exemplo:

npx cypress tap command --test-id r2 --command-id 3

pin

Viagem no tempo. Ele carrega o snapshot do DOM de um comando no frame da aplicação, para que o próximo aria, dom ou inspect leia a página como ela estava naquele momento. --at escolhe o snapshot: before, after ou um índice começando em 1. --clear libera o pin e volta para a aplicação ao vivo.

Sintaxe:

npx cypress tap pin --test-id <id> --command-id <linha> [--at <before|after|n>]
npx cypress tap pin --clear

Exemplo:

npx cypress tap pin --test-id r2 --command-id 1
👨‍🏫 Sempre execute pin --clear quando terminar de ler um snapshot fixado. Até fazer isso, toda leitura mostra o passado.

aria

Imprime a árvore de acessibilidade da página: o papel (role), o nome acessível e o estado de cada elemento, do jeito que um leitor de tela os vê. É o melhor primeiro olhar sobre uma página: mostra o que existe e como está rotulado, em poucas linhas. Ele lê até 200 nós por padrão (--max-nodes, ou -m).

Sintaxe:

npx cypress tap aria [--selector <css>] [--at <índice>]

Exemplo:

npx cypress tap aria

dom

Imprime o markup da página inteira, ou do elemento que um seletor CSS encontra. Use-o para textos e atributos exatos, como data-testid, id, type e placeholder. Ele imprime até 30000 caracteres por padrão (--max-chars, ou -m).

Sintaxe:

npx cypress tap dom [--selector <css>] [--at <índice>]

Exemplo:

npx cypress tap dom --selector '[data-testid="emoji-card"]' --at 1

inspect

Imprime a tag, os atributos, o nó de acessibilidade, o box model e os estilos computados mais relevantes de um elemento. --selector é obrigatório.

Sintaxe:

npx cypress tap inspect --selector <css> [--at <índice>]

Exemplo:

npx cypress tap inspect --selector '[data-testid="emoji-card"]' --at 1
👨‍🏫 Quando um seletor encontra mais de um elemento, dom, aria e inspect se recusam a adivinhar. Eles terminam com 1 e listam os candidatos com um índice, e você escolhe um com --at <índice>, que aqui começa em 0. O pin --at é diferente: ali, um número começa em 1, porque ele conta os snapshots de um comando, e não elementos. Um seletor propositalmente amplo é uma boa forma de descobrir o que há na página.

Telemetria

O Cypress Tap registra qual comando você executou, com quais opções, e se ele falhou. A referência do Cypress documenta como desativar com a variável de ambiente CYPRESS_DISABLE_GUEST_TELEMETRY=0. Sim, um 0 que desativa alguma coisa: confira a referência antes de confiar nisso, já que o Tap está em beta.

Conteúdo sugerido 📚 e links da documentação 🔗

Exercício 🎯

Você vai conduzir o Cypress Tap à mão, de um primeiro cy.visit até um teste que abre um produto, lendo a aplicação a cada passo.

  • 1. Em um terminal, na raiz do seu projeto, execute npm run cy:open. Quando o navegador abrir na lista de specs, deixe-o ali: não selecione nada. Mantenha esse terminal rodando durante todo o curso; o Tap precisa dele.
  • 2. Em um segundo terminal, execute npx cypress tap sessions (uma linha, o seu projeto), depois npx cypress tap status e npx cypress tap status --json. O estágio é spec not selected, e o startedAt está ausente ou é null. Execute npx cypress tap specs: ainda não há nenhuma.
  • 3. Crie o arquivo cypress/e2e/explore.cy.js. A única tarefa dele, por enquanto, é o passo 1 do fluxo, preparar o estado:
describe('Exploring Emoji Mart', () => {
  it('opens the store', () => {
    cy.visit('/')
  })
})
  • 4. Execute npx cypress tap specs de novo e encontre a sua spec. Anote o startedAt do npx cypress tap status --json. Depois execute npx cypress tap run cypress/e2e/explore.cy.js e consulte o status --json (ou rode o script Bash da seção "Esperando um veredito novo") até ter um veredito novo. Observe a janela do Cypress enquanto ela roda, sem mexer nela.
  • 5. Execute npx cypress tap reporter e copie o id do teste. Depois execute npx cypress tap reporter --test-id <id> e leia o seu Command Log. Procure linhas de rede (requisições que a aplicação fez enquanto o teste rodava): não há nenhuma. O Emoji Mart carrega tudo de que precisa junto com a página e não faz requisições depois disso, então não haverá nada para interceptar neste curso.
  • 6. Agora leia a aplicação. Execute npx cypress tap aria e encontre os botões da loja. Alguns têm um nome que você consegue ler; outros não têm nome nenhum. Anote quais. Depois execute npx cypress tap dom --selector '[data-testid="emoji-card"]': ele se recusa, porque seis cards correspondem, e os lista. Execute de novo com --at 1 para ler o segundo card, e npx cypress tap inspect --selector '[data-testid="emoji-card"]' --at 1 para ver os seus atributos e a sua caixa.
  • 7. Procure, naquela saída do aria, um controle que leve de volta da página de um produto. Não há nenhum, porque nenhuma página de produto está aberta: o teste parou na loja. É o passo 1 de novo: para ler um estado, um teste precisa chegar até ele. Anote o startedAt atual, mude o teste para que ele abra o Rocket e verifique que a página dele está aparecendo, e salve:
describe('Exploring Emoji Mart', () => {
  it('opens the Rocket', () => {
    cy.visit('/')

    cy.contains('[data-testid="emoji-card"]', 'Rocket').click()

    cy.contains('button', '← Back to all emojis').should('be.visible')
  })
})
👨‍🏫 Salvar a spec selecionada a executa, então desta vez não chame o run: espere o veredito novo. Depois execute npx cypress tap aria e confirme o papel e o texto exato do controle de voltar. Eu escrevi button porque esse é o papel que o aria me mostrou. Se o seu mostrar outra coisa, a asserção segue a aplicação, e não o meu exemplo.
  • 8. Viagem no tempo: execute npx cypress tap reporter --test-id <id> (o id pode ter mudado, então copie de novo), encontre o número da linha do visit e execute npx cypress tap pin --test-id <id> --command-id <linha>. A janela do Cypress mostra a loja de novo, antes do clique. Execute npx cypress tap aria e veja os seis produtos, mesmo que a página ao vivo mostre o Rocket. Depois execute npx cypress tap pin --clear.
  • 9. Faça o commit de cypress/e2e/explore.cy.js e o push.
🙊 A solução do instrutor será adicionada aqui em breve.

Mostre ao mundo o que você aprendeu 🌎

Para mostrar à sua rede profissional o que você aprendeu nesta aula, publique o seguinte no LinkedIn.

Estou fazendo o curso "Testes Agênticos com Cypress Tap" com @Walmyr Lima e Silva Filho na @Talking About Testing School, e acabei de conduzir o Cypress Tap à mão: executei uma spec pelo terminal, esperei um veredito novo em vez de confiar em um antigo, li o Command Log, a árvore de acessibilidade e o DOM, e viajei no tempo até um snapshot anterior. #TalkingAboutTesting #TATSchool #AgenticTestingWithCypressTap #CypressTap #AgenticTesting

👨‍🏫 Lembre-se de me marcar na sua publicação. Aqui está o meu perfil no LinkedIn.

Quiz

Pergunta 1 de 2
Pontuação: 0

Você executa uma spec com npx cypress tap run e logo em seguida lê o status --json. Ele diz passed. Antes de confiar nisso, o que você precisa verificar, e por quê?

Acerte 100% do quiz para continuar