O que você vai aprender
- Como começar a testar um novo projeto com Cypress
- Como são reportados testes com sucesso e falhas
- Testando a navegação web, buscando por elementos no DOM e escrevendo asserções
Assumindo que você tenha instalado e aberto o Cypress Test Runner, chegou a hora de escrever o primeiro teste. Vamos então:
- Criar um arquivo
sample_spec.js
. - Checar que o Cypress atualizou a lista de arquivos de teste.
- Executar o Cypress Test Runner.
Vamos criar um novo arquivo na pasta cypress/integration
, a qual já foi criada:
touch {your_project}/cypress/integration/sample_spec.js
Uma vez que o arquivo tenha sido criado, o Cypress Test Runner deve exibi-lo na lista de testes de integração. O Cypress monitora mudanças em seus arquivos de teste e os exibe imediatamente.
Mesmo que ainda não tenha escrito nenhum teste - tudo bem - clique em sample_spec.js
e veja o
Cypress iniciar o navegador.
O Cypress abre o teste em um navegador previamente instalado em seu sistema operacional. Você pode ler mais sobre como isso é feito em Iniciando Navegadores.
Agora estamos oficialmente no Test Runner. É nele onde vamos gastar a maioria do tempo testando.
Note que o Cypress exibe a mensagem que não pode encontrar nenhum teste. Isso é normal - testes ainda não foram escritos! Você verá essa mensagem também caso exista algum erro ao analisar os arquivos de teste. Você pode abrir o Dev Tools para inspecionar o console e buscar por erros de sintaxe que impediu o Cypress de ler seus arquivos de testes.
Chegou a hora de escrever o nosso primeiro teste. Vamos então:
- Escrever nosso primeiro teste com sucesso.
- Escrever nosso primeiro teste com falha.
- Ver o Cypress recarregar o teste em tempo real.
A medida que salvamos nosso novo teste, veremos que o navegador recarrega automaticamente em tempo real.
Abra sua IDE favorita e adicione o código abaixo no arquivo de teste sample_spec.js
.
describe('My First Test', () => {
it('Does not do much!', () => {
expect(true).to.equal(true)
})
})
Quando salvar esse arquivo você deve ver o navegador recarregar.
Embora não faça nada, esse é nosso primeiro teste com sucesso!
No log de comandos você vai ver que o Cypress exibe a suíte de teste, o teste e a primeira asserção (que deve estar em verde - sucesso).
Observe que o Cypress exibe uma mensagem sobre essa ser a página padrão à direita. Cypress assume que você irá sair e visitar outra página na internet - mas também pode funcionar bem sem isso.
Agora vamos escrever nosso primeiro teste com falha.
describe('My First Test', () => {
it('Does not do much!', () => {
expect(true).to.equal(false)
})
})
Quando você salvar, poderá observar que o Cypress exibe o teste com falha em vermelho, uma vez
que true
não é igual a false
.
Cypress também exibe o log do erro e o pedaço do código onde a asserção falhou (quando disponível). Você pode clicar no link do arquivo em azul para abrir o arquivo em que o erro ocorreu em sua IDE. Para ler mais sobre exibição de erros, leia sobre Debugando Erros.
Cypress fornece um ótimo Test Runner que exibe uma estrutura visual das suítes, testes e asserções. Em breve você verá também comandos, eventos, requisições de rede e mais.
Vídeo do primeiro teste com falha
O que é describe, it e expect? Todas essas funções vem das Bundled Tools que fazem parte do Cypress. Describe e it vem do Mocha. Expect vem do Chai.
Cypress utiliza dessas ferramentas e frameworks populares, os quais é esperado que você já tenha alguma familiaridade e conhecimento prévio. Mas se não tiver, tudo bem.
Um teste sólido geralmente cobre 3 fases:
- Configurar o estado da aplicação
- Realizar uma ação
- Fazer uma asserção sobre o resultado da ação
Também conhecido pela tríade "Given, When, Then", ou "Arrange, Act, Assert". Mas a ideia é: primeiro a aplicação é colocada em um estado específico, então uma ação é realizada na aplicação, o que causa uma mudança, e finalmente o resultado da apicação é checado.
Hoje, vamos ver esses passos de perto e mapeá-los claramente em comandos do Cypress:
- Visitar uma página web.
- Consultar um elemento.
- Interagir com o elemento.
- Verificar o conteúdo da página.
Primeiro, vamos visitar uma página web. Neste exemplo vamos usar a aplicação Kitchen Sink para que você possa experimentar o Cypress sem se preocupar em procurar uma página para testar.
Podemos passar a URL que queremos visitar para o cy.visit()
. Vamos substituir nosso teste
anterior pelo teste abaixo que de fato visita uma página:
describe('My First Test', () => {
it('Visits the Kitchen Sink', () => {
cy.visit('https://example.cypress.io')
})
})
Salve o arquivo e retorne ao Cypress Test Runner. Você vai perceber algumas coisas:
- O Log de Comandos
agora exibe a nova ação
visit
. - A aplicação Kitchen Sink foi carregada no painel de pré visualização da aplicação.
- O teste está verde, mesmo não tendo nenhuma asserção.
- O
visit
exibe um estado pendente em azul até que a página termine de carregar.
Se essa solicitação tivesse retornado com um código de status diferente de 2xx, como 404 ou 500, ou se houvesse um erro de JavaScript no código do aplicativo, o teste teria falhado.
Teste apenas aplicações que você controla
Embora neste guia estamos testando nossa aplicação exemplo, você não deve testar aplicações que você
não controla. Por quê?
1. São passíveis de mudanças a qualquer momento, o que pode quebrar os testes.
2. Podem fazer testes A/B o que torna impossível ter resultados consistentes.
3. Podem detectar que o usuário é um script e bloquear o acesso (como o Google faz).
4. Podem ter funcionalidades de segurança habilitadas que previne o Cypress de funcionar corretamente.
O ponto do Cypress é ser uma ferramente de uso diário para construir e testar suas próprias aplicações.
O Cypress não é uma ferramenta de automação de propósito geral. É pouco adequado para scripts em sites que
estão em produção, e não estão sob seu controle.
Agora que temos a página web carregada, precisamos fazer algo nela. Porque não clicamos em um link?
Parece ser fácil, vamos ver qual deles gostamos... que tal type
?
Para encontrar esse elemento pelo seu conteúdo, usamos cy.contains()
.
Vamos adicionar isso em nosso teste e ver o que acontece:
describe('My First Test', () => {
it('finds the content "type"', () => {
cy.visit('https://example.cypress.io')
cy.contains('type')
})
})
Agora o teste deve exibir o comando CONTAINS
e ainda estar verde.
Mesmo sem adicionar uma asserção, sabemos que está tudo certo! Isso acontece pois muitos dos comandos do Cypress são construídos para falhar caso não encontram o que é esperado. Isso é conhecido como uma Asserção Padrão.
Para confirmar, substitua type
por qualquer palavra que não esteja na página, como hype
.
Perceba que o teste falha, mas só depois de 4 segundos!
Entende o que o Cypress está fazendo? Automaticamente espera e tenta novamente pois é esperado que eventualmente o elemento será encontrado no DOM. O teste não falha imediatamente.
Tomamos o cuidado de escrever centenas de mensagens de erro personalizadas que tentam explicar claramente o que deu errado no Cypress. Nesse caso, o Cypress atingiu o tempo limite tentando encontrar o texto hype em toda a página. Para ler mais sobre a exibição do erro, leia sobre Erros de depuração.
Antes de adicionar outro comando - vamos consertar esse teste. Substitua hype
por type
.
Ok, agora queremos clicar no link que encontramos. Como fazer isso? Adicione o comando .click()
no final do comando anterior, como abaixo:
describe('My First Test', () => {
it('clicks the link "type"', () => {
cy.visit('https://example.cypress.io')
cy.contains('type').click()
})
})
É quase possível ler o teste como uma história! O Cypress chama isso de encadeamento e comandos são encadeados para contruir testes que realmente expressam o que a aplicação faz de forma declarativa.
Note também que o painel da aplicação foi atualizado depois do clique, abrindo o link e mostrando a página de destino.
Agora podemos fazer uma asserção nessa nova página!
Você pode ver o IntelliSense em seus arquivos de teste ao adicionar uma única linha de comentário especial. Leia sobre isso aqui.
Vamos fazer uma asserção sobre algo na nova página em que clicamos. Gostaríamos de ter certeza de que o novo
URL é o URL esperado. Podemos fazer isso procurando a URL e encadeando uma asserção a ela com
.should()
.
Aqui está, algo parecido:
describe('My First Test', () => {
it('clicking "type" navigates to a new url', () => {
cy.visit('https://example.cypress.io')
cy.contains('type').click()
// Should be on a new URL which includes '/commands/actions'
cy.url().should('include', '/commands/actions')
})
})
Não estamos limitados a uma única interação e asserção em um determinado teste. Na verdade, muitas interações em um aplicativo podem exigir várias etapas e provavelmente alterarão o estado do aplicativo em mais de uma maneira.
Podemos continuar as interações e asserções neste teste, adicionando outro encadeamento para interagir e verificar o comportamento dos elementos nesta nova página.
Podemos usar cy.get()
para selecionar um elemento baseado em uma classe CSS.Então, podemos usar o comando
.type()
para inserir texto no campo de entrada de texto selecionado. Por fim, podemos verificar que o valor
do campo de entrada de texto reflete o texto que foi digitado com outro
.should()
.
describe('My First Test', () => {
it('Gets, types and asserts', () => {
cy.visit('https://example.cypress.io')
cy.contains('type').click()
// Should be on a new URL which includes '/commands/actions'
cy.url().should('include', '/commands/actions')
// Get an input, type into it and verify that the value has been updated
cy.get('.action-email')
.type('fake@email.com')
.should('have.value', 'fake@email.com')
})
})
E aí está: um breve teste no Cypress que visita uma página, encontra e clica em um link, verifica a URL e, em seguida, verifica o comportamento de um elemento na nova página. Se lermos em voz alta, pode soar como:
- Visitar:
https://example.cypress.io
- Encontrar o elemento que contém
type
- Clicar no elemento
- Pegar a URL
- Verificar que ela inclui
/commands/actions
- Pegar o campo de entrada de texto com a classe
.action-email
- Digitar
fake@email.com
no campo de entrada de texto - Verificar que o campo de entrada de texto é preenchido com o novo valor
Ou na sintaxe Dado que, Quando, Então:
- Dado que um usuário visita
https://example.cypress.io
- Quando ele clica no link com label
type
- E ele digita
fake@email.com
no campo de entrada de texto com a classe.action-email
- Então o URL deve incluir
/comandos/ações
- E o campo de entrada de texto com a classe
.action-email
temfake@email.com
como valor
E ei, este é um teste muito limpo! Não precisamos dizer nada sobre como as coisas funcionam, apenas que gostaríamos de verificar uma série particular de eventos e resultados.
Transições de página
É importante notar que este teste fez a transição em duas páginas diferentes.
[//]: <> (TODO - Adicionar links cy.visit e .click() quando traduzidos)
1. O [`cy.visit()`](https://docs.cypress.io/api/commands/visit.html)
2. O [`.click()`](https://docs.cypress.io/api/commands/click.html) para nova página
O Cypress detecta automaticamente coisas como um evento de transição de página e interromperá automaticamente
os comandos em execução até que a próxima página termine de carregar.
Se a próxima página não tivesse terminado sua fase de carregamento, Cypress teria encerrado o teste
e apresentado um erro.
Feito automaticamente - isso significa que você não precisa se preocupar com comandos executados
acidentalmente em uma página desatualizada, nem precisa se preocupar com a execução de comandos em
uma página parcialmente carregada.
Mencionamos anteriormente que o Cypress esperou 4 segundos antes de atingir o tempo limite para encontrar
um elemento DOM - mas, neste caso, quando o Cypress detecta um evento de transição de página, ele aumenta
automaticamente o tempo limite para 60 segundos para o único evento CARREGAR PÁGINA.
Em outras palavras, com base nos comandos e nos eventos que acontecem, o Cypress altera automaticamente seus
tempos limite esperados para corresponder ao comportamento do aplicativo da web.
[//]: <> (TODO - Adicionar link Configuração quando traduzido)
Esses vários tempos limite são definidos no arquivo de
[configuração](https://docs.cypress.io/guides/references/configuration.html#Timeouts).