Por Victor Oliveira - QA Senior com mais de 13 anos de experiencia

O Cypress e uma ferramenta de automacao de testes open-source para testes de ponta a ponta (E2E), testes de componentes e testes de API. Diferente do Selenium, que executa fora do navegador, o Cypress roda dentro do mesmo processo do navegador, o que permite um controle total sobre a aplicacao. Neste tutorial, voce vai aprender como configurar um projeto do zero, desde a instalacao ate a execucao do primeiro teste.

1. O que e Cypress?

Cypress foi lancado em 2017 por Brian Mann e rapidamente se tornou uma das ferramentas mais populares para automacao de testes E2E. Sua arquitetura unica — rodando dentro do mesmo loop de eventos do navegador — elimina muitos problemas classicos de automacao, como races conditions e flaky tests.

Principais vantagens:

  • Arquitetura no mesmo processo — acesso direto ao DOM, localStorage, sessionStorage e rede
  • Time Travel — veja screenshots de cada passo do teste ao passar o mouse no Command Log
  • Auto-wait inteligente — nunca use sleep() ou wait() manuais
  • Debugging excepcional — erros com stack traces legiveis e screenshots automaticas
  • Interceptacao de rede — stub e mock de requisicoes HTTP sem ferramentas externas
  • Real-time reload — alterou o teste? O Cypress recarrega automaticamente
  • Screenshots e videos — gravacao automatica em execucao headless
  • Dashboard service — gravacao de resultados, analise de flaky, paralelizacao

2. Pre-requisitos

Antes de comecar, voce precisa ter instalado:

  • Node.js 18+ — nodejs.org
  • npm — ja vem com Node.js
  • Git (opcional, mas recomendado) — para versionamento
  • VS Code (ou qualquer editor de sua preferencia)

Verifique se o Node.js esta instalado corretamente:

node --version
npm --version

3. Instalacao do Cypress

Crie uma pasta para o projeto e instale o Cypress:

mkdir meu-projeto-cypress
cd meu-projeto-cypress
npm init -y
npm install cypress --save-dev

Apos a instalacao, abra o Cypress pela primeira vez:

npx cypress open

Na primeira execucao, o Cypress cria automaticamente a estrutura de pastas recomendada e arquivos de exemplo. Voce vera uma interface grafica com os testes de exemplo prontos para executar.

Verifique a instalacao:

npx cypress --version

4. Estrutura de Diretorios

Apos abrir o Cypress, a estrutura gerada e:

meu-projeto-cypress/
├── cypress/
│   ├── e2e/
│   │   ├── exemplo.cy.js
│   │   └── login.cy.js
│   ├── fixtures/
│   │   └── example.json
│   ├── support/
│   │   ├── commands.js
│   │   └── e2e.js
│   └── downloads/
├── cypress.config.js
├── package.json
└── node_modules/
  • cypress/e2e/ — arquivos de teste com extensao .cy.js
  • cypress/fixtures/ — dados estaticos para mock (JSON, imagens, etc.)
  • cypress/support/commands.js — custom commands reutilizaveis
  • cypress/support/e2e.js — configuracao global executada antes de cada teste
  • cypress.config.js — configuracao central do Cypress

5. Criando o Primeiro Teste

Crie o arquivo cypress/e2e/primeiro_teste.cy.js:

describe('Meu primeiro teste', () => {
    it('deve acessar o Google e verificar o titulo', () => {
        cy.visit('https://google.com');
        cy.title().should('eq', 'Google');
    });
});

Vamos entender cada parte:

  • describe() — agrupa testes relacionados (suite)
  • it() — define um caso de teste individual
  • cy.visit() — navega para uma URL
  • cy.title() — obtem o titulo da pagina
  • .should() — assertiva do Cypress (BDD-style, encadeavel)

5.1. Teste com interacao

Vamos criar um teste mais completo que interage com elementos na pagina:

describe('Login', () => {
    it('deve fazer login com sucesso', () => {
        cy.visit('https://example.com/login');

        cy.get('#username').type('admin');
        cy.get('#password').type('senha123');

        cy.get('button[type="submit"]').click();

        cy.get('.welcome-message').should('have.text', 'Bem-vindo, admin!');
    });
});

6. Localizadores e Interacoes

O Cypress usa seletores CSS para localizar elementos. Recomenda-se usar atributos data-cy ou data-testid para maior resiliencia:

cy.get('[data-cy="submit-button"]').click();
cy.get('[data-testid="user-email"]').should('be.visible');
cy.contains('Bem-vindo').click();
cy.get('button').contains('Enviar').click();
cy.get('.form').find('input').first().type('texto');

6.1. Interacoes principais

cy.get('.botao').click();
cy.get('.botao').dblclick();
cy.get('input').type('texto', { delay: 100 });
cy.get('input').clear();
cy.get('select').select('opcao-1');
cy.get('input[type="checkbox"]').check();
cy.get('.dropdown').trigger('mouseover');
cy.get('.footer').scrollIntoView();
cy.get('input[type="file"]').selectFile('caminho/arquivo.pdf');

7. Assertivas (Assertions)

O Cypress usa chai como biblioteca de assertivas, com sintaxe encadeavel e auto-retry:

cy.get('.mensagem').should('be.visible');
cy.get('.spinner').should('not.be.visible');
cy.get('input').should('be.disabled');
cy.get('.checkbox').should('be.checked');

cy.get('.titulo').should('have.text', 'Bem-vindo');
cy.get('.titulo').should('contain', 'Bem');
cy.get('input').should('have.value', 'admin');

cy.get('.erro').should('have.css', 'color', 'rgb(255, 0, 0)');
cy.get('.item').should('have.length', 5);

cy.url().should('include', '/dashboard');
cy.get('.erro').should('not.exist');

cy.get('.card')
    .should('be.visible')
    .and('have.class', 'active')
    .and('contain', 'Bem-vindo');

8. Testando APIs com cy.request e cy.intercept

8.1. Testando APIs diretamente

describe('API Testing', () => {
    it('deve listar usuarios', () => {
        cy.request('GET', 'https://api.example.com/users')
            .then((response) => {
                expect(response.status).to.eq(200);
                expect(response.body).to.have.length(10);
            });
    });

    it('deve criar um novo usuario', () => {
        cy.request({
            method: 'POST',
            url: 'https://api.example.com/users',
            body: { name: 'Victor', email: 'victor@email.com' }
        }).then((response) => {
            expect(response.status).to.eq(201);
            expect(response.body).to.have.property('id');
        });
    });
});

8.2. Interceptacao de rede

describe('Interceptacao', () => {
    it('deve mostrar dados mockados', () => {
        cy.intercept('GET', '/api/users', {
            statusCode: 200,
            body: [{ id: 1, name: 'Usuario Mock' }]
        }).as('getUsers');

        cy.visit('/usuarios');
        cy.wait('@getUsers');
        cy.get('.usuario').should('have.length', 1);
    });

    it('deve testar erro de rede', () => {
        cy.intercept('GET', '/api/users', {
            statusCode: 500,
            body: { error: 'Erro interno' }
        }).as('getUsersError');

        cy.visit('/usuarios');
        cy.wait('@getUsersError');
        cy.get('.erro-api').should('be.visible');
    });
});

9. Custom Commands

Custom commands permitem reutilizar acoes comuns em todos os testes. Defina em cypress/support/commands.js:

Cypress.Commands.add('login', (email, senha) => {
    cy.visit('/login');
    cy.get('[data-cy="email"]').type(email);
    cy.get('[data-cy="senha"]').type(senha);
    cy.get('[data-cy="submit"]').click();
    cy.url().should('include', '/dashboard');
});

Cypress.Commands.add('criarUsuario', (dados) => {
    cy.request({
        method: 'POST',
        url: '/api/users',
        body: dados
    }).then((response) => {
        expect(response.status).to.eq(201);
        cy.wrap(response.body).as('novoUsuario');
    });
});

E nos testes, use os custom commands diretamente:

describe('Com custom commands', () => {
    it('deve fazer login', () => {
        cy.login('victor@email.com', 'senha123');
        cy.get('.boas-vindas').should('contain', 'Victor');
    });
});

10. Executando os Testes

10.1. Modo Interativo

npx cypress open

Abre o Cypress Test Runner com interface grafica: selecione testes, veja o Command Log com Time Travel, debug cada passo.

10.2. Modo Headless

npx cypress run
npx cypress run --browser chrome
npx cypress run --browser firefox
npx cypress run --spec "cypress/e2e/login.cy.js"
npx cypress run --record --key SUA_CHAVE

10.3. Configuracao (cypress.config.js)

const { defineConfig } = require('cypress');

module.exports = defineConfig({
    e2e: {
        baseUrl: 'http://localhost:3000',
        viewportWidth: 1280,
        viewportHeight: 720,
        defaultCommandTimeout: 10000,
        screenshotOnRunFailure: true,
        video: true,
        retries: {
            runMode: 1,
            openMode: 0
        },
    },
});

11. CI/CD com GitHub Actions

# .github/workflows/cypress.yml
name: Cypress Tests
on: [push]

jobs:
    cypress-run:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - uses: actions/setup-node@v4
              with:
                  node-version: '22'
                  cache: 'npm'
            - run: npm ci
            - run: npx cypress run --browser chrome
            - uses: actions/upload-artifact@v4
              if: failure()
              with:
                  name: cypress-screenshots
                  path: cypress/screenshots/
            - uses: actions/upload-artifact@v4
              if: always()
              with:
                  name: cypress-videos
                  path: cypress/videos/

12. Dicas e Boas Praticas

  • Use data-cy em vez de classes CSS — seletores mais resilientes
  • Evite cy.wait() com tempos fixos — confie no auto-wait e use cy.intercept()
  • Use fixtures para dados de teste — mantenha dados mockados separados
  • Custom commands para acoes repetitivas — login, criacao de dados
  • Limpe o estado antes de cada teste — use beforeEach() via API
  • Nao use cy.wait() para rede — prefira cy.intercept() + cy.wait('@alias')
  • Teste fluxos criticos — foque no que realmente importa para o negocio
  • Mantenha testes independentes — cada teste deve rodar sozinho em qualquer ordem
beforeEach(() => {
    cy.request('POST', '/api/test/reset');
    cy.fixture('usuario').as('userData');
});

describe('Fluxo de compra', () => {
    it('deve completar uma compra', function () {
        cy.login(this.userData.email, this.userData.senha);
        cy.intercept('POST', '/api/checkout').as('checkout');
        cy.get('[data-cy="produto-1"]').click();
        cy.get('[data-cy="finalizar-compra"]').click();
        cy.wait('@checkout').its('response.statusCode').should('eq', 200);
        cy.get('[data-cy="confirmacao"]').should('be.visible');
    });
});

13. Cypress vs Playwright vs Selenium

  • Cypress — melhor debug com Time Travel, ideal para apps React/Angular/Vue, limitado a Chromium/Firefox/Edge
  • Playwright — suporte nativo a Chromium + Firefox + WebKit, auto-wait, melhor para cross-browser
  • Selenium — suporte a todos os navegadores, mais lento, maior ecossistema legado

14. Proximos Passos

Agora que voce ja sabe iniciar um projeto com Cypress, explore:

  • Cypress Component Testing — teste componentes React/Vue/Angular
  • Cypress Dashboard — gravacao de resultados e analise de flaky
  • Visual Regression — cypress-image-snapshot
  • Cucumber + Cypress — BDD com Gherkin
  • Cypress com Docker — ambientes isolados para CI

Continue acompanhando o QA Overflow para mais tutoriais praticos sobre automacao de testes!