DEV Community

William Moreira da Silva
William Moreira da Silva

Posted on

Elevando a Qualidade: Guia Prático de Testes em Cypress para Componentes e E2E em Aplicações React

Os testes desempenham um papel fundamental no desenvolvimento de aplicações, garantindo a estabilidade, confiabilidade e qualidade do código. Neste artigo, vamos explorar a importância dos testes de componentes e os end-to-end (E2E) usando Cypress em aplicações React.

Um pouco sobre Cypress

O Cypress é uma poderosa ferramenta de automação de testes end-to-end (E2E) projetada para facilitar o processo de teste em aplicações web. Com um foco especial na simplicidade de uso e eficácia, o Cypress ganhou popularidade entre desenvolvedores e equipes de QA devido às suas características distintivas. Seu design intuitivo e capacidades abrangentes tornam-no uma peça fundamental no processo de garantia de qualidade para aplicações web modernas.

Principais Características:

  1. Integração Simples: A instalação do Cypress é direta, e a integração com projetos existentes é fácil
  2. Testes em Tempo Real: Ao contrário de muitas ferramentas de automação, o Cypress executa testes em tempo real enquanto interage com a aplicação, fornecendo feedback instantâneo e facilitando a depuração.
  3. Comandos Simples e Intuitivos: A sintaxe dos comandos Cypress é clara e intuitiva. Operações comuns, como clicar em elementos, preencher formulários e verificar resultados, são expressas de maneira concisa.
  4. Execução em Navegadores Reais: O Cypress executa testes diretamente em navegadores reais, o que significa que os desenvolvedores podem confiar na precisão dos resultados e na consistência com a experiência do usuário real.
  5. Conceito de "Subjects" e Encadeamento de Comandos (chains of commands): O Cypress gerencia um conceito de "subject" que permite o encadeamento natural de comandos, simplificando a construção de testes complexos.
  6. Ampla Gama de Assertivas (Assertions): A capacidade de verificar o estado do DOM e dos elementos usando assertivas robustas simplifica a validação de resultados esperados.
  7. Visual Regression Testing Integrado: O Cypress pode integrar facilmente testes de regressão visual, comparando capturas de tela para identificar alterações visuais não intencionais.
  8. API Mocking e Testes de API: A capacidade de simular chamadas de API e realizar testes de integração com facilidade contribui para uma cobertura de teste mais abrangente.
  9. Timeouts Configuráveis: O Cypress gerencia timeouts automaticamente, mas oferece controle configurável para adaptar a execução dos testes conforme necessário.
  10. Comunidade Ativa e Suporte Contínuo: O Cypress possui uma comunidade ativa, com suporte constante e atualizações frequentes, garantindo que a ferramenta permaneça relevante e eficiente.

Definindo algumas bases

Segue aqui alguns pontos importantes para utilizar o cypress com maestria.

Esse e vários outros pontos podemos encontrar na própria documentação do cypress:

1. Como o Cypress consulta o DOM:

O Cypress possui comandos específicos para interagir com elementos no DOM. Veja um exemplo de como você pode usar o comando cy.get para consultar e interagir com um elemento:

// Consulta e interação com um botão usando seu seletor
cy.get('button').click();

// Consulta e interação com um input usando um atributo específico
cy.get('[data-cy=username-input]').type('nome de usuário');
Enter fullscreen mode Exit fullscreen mode

2. Como o Cypress gerencia subjects e chains of commands:

O Cypress mantém uma referência ao elemento alvo como um "subject". Cada comando retorna um novo "subject", permitindo a encadeamento de comandos. Veja um exemplo:

// Cada comando retorna um novo "subject"
cy.get('ul')
  .find('li')   // O subject agora é a lista de itens dentro da ul
  .first()      // O subject agora é o primeiro item da lista
  .click();     // Clicando no primeiro item

Enter fullscreen mode Exit fullscreen mode

3. Como as assertivas (assertions) funcionam:

As assertivas no Cypress são usadas para verificar se o estado do DOM ou de outros elementos é como esperado. Exemplo:

cy.get('.status-message').should('be.visible'); // Verifica se o elemento está visível

cy.get('input[name="username"]').should('have.value', 'nome de usuário'); // Verifica o valor do input

Enter fullscreen mode Exit fullscreen mode

4. Como os timeouts são aplicados aos comandos:

O Cypress gerencia timeouts automaticamente, mas você pode personalizá-los conforme necessário. Exemplo:

// Configuração de um timeout específico para um comando
cy.get('elemento').click({ timeout: 10000 }); // Timeout de 10 segundos para o clique
Enter fullscreen mode Exit fullscreen mode

Esses exemplos demonstram como os conceitos fundamentais do Cypress são aplicados no contexto de consultas ao DOM, manipulação de "subjects", execução de assertivas e controle de timeouts. O Cypress é uma ferramenta poderosa que oferece controle detalhado sobre interações com o DOM e facilita a criação de testes E2E robustos.

Conceitos que irão parecer por aqui

Subjects:

No contexto do Cypress, "subjects" referem-se aos elementos HTML ou objetos que são o foco de uma cadeia de comandos. Cada comando no Cypress gera um novo "subject", e os comandos subsequentes são executados em cima desse "subject". Isso cria uma forma natural de encadear comandos, simplificando a escrita de testes e a interação com o DOM. Por exemplo:

cy.get('button')   // "get" retorna um novo "subject" representando o botão
  .click()        // "click" é executado no "subject" do botão
  .should('be.visible');  // "should" é executado no "subject" após o clique

Enter fullscreen mode Exit fullscreen mode

Chains of Commands:

As "chains of commands" (cadeias de comandos) referem-se à sequência de comandos encadeados que são executados em Cypress. Cada comando gera um novo "subject" que é passado para o próximo comando na cadeia. Isso cria uma forma clara e concisa de expressar interações e verificações em testes E2E. Exemplo:

cy.get('.menu')
  .should('be.visible')
  .contains('Item de Menu')
  .click()
  .should('have.class', 'ativo');
Enter fullscreen mode Exit fullscreen mode

Assertions:

As assertivas em Cypress são usadas para verificar se o estado de um "subject" ou de um elemento DOM corresponde às expectativas definidas no teste. Elas ajudam a garantir que a aplicação está se comportando conforme o esperado. Um exemplo comum usando a assertiva should:

cy.get('.elemento').should('be.visible');
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, a assertiva verifica se o elemento com a classe ".elemento" está visível.

Visual Regression Testing Integrado:

O Visual Regression Testing é uma técnica que compara imagens ou capturas de tela da aplicação em diferentes momentos para detectar alterações visuais inesperadas. O Cypress oferece integração nativa com esse tipo de teste, permitindo comparar automaticamente capturas de tela durante a execução do teste. Isso ajuda a identificar alterações visuais que podem ocorrer inadvertidamente ao longo do desenvolvimento.

cy.visit('/pagina');
cy.matchImageSnapshot();  // Compara a página atual com uma referência anterior
Enter fullscreen mode Exit fullscreen mode

esse exemplo é bem simplório, veja a documentação do cypress para aprofundar no assunto. https://docs.cypress.io/guides/tooling/visual-testing

API Mocking:

API Mocking refere-se à capacidade de simular chamadas de API durante os testes. Isso permite isolar o frontend do backend, garantindo que os testes se concentrem apenas no comportamento do frontend. O comando cy.intercept é comumente utilizado para definir respostas simuladas para solicitações de API. Exemplo:

cy.intercept('GET', '/api/dados', { fixture: 'dados.json' }).as('getDados');
cy.visit('/dashboard');
cy.wait('@getDados').its('response.statusCode').should('eq', 200);
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, a chamada de API é interceptada e substituída por uma resposta simulada, garantindo que os testes não dependam da disponibilidade do backend real durante a execução.

Testes de Componentes em React:

Os testes de componentes em React visam verificar se os componentes individuais funcionam conforme o esperado. Isso pode incluir testes de renderização, manipulação de estados, interações do usuário e muito mais. A biblioteca de testes mais comum para React é o Jest, frequentemente combinado com React Testing Library para testes centrados no usuário.

Exemplo de teste de renderização com Jest:

import { render, screen } from '@testing-library/react';
import Component from './Component';

test('renderiza o componente corretamente', () => {
  render(<Component />);
  const elemento = screen.getByText(/texto do component/i);
  expect(elemento).toBeInTheDocument();
});

Enter fullscreen mode Exit fullscreen mode

Exemplo com Cypress

import React from "react";
import ErrorMessage from "./ErrorMessage";

function ErrorMessage({ message }) {
  return <div className="error-message">{message}</div>;
}

describe("<ErrorMessage />", () => {
  it("renders", () => {
        // instancia do componente
    cy.mount(<ErrorMessage message="Mensagem de erro" />);
        // validação se a div com a class error-message contém a mensagem "Mensagem de erro"
    cy.get(".error-message").should(`have.text`, "Mensagem de erro");

        // ... Outros possíveis testes
  });
});
Enter fullscreen mode Exit fullscreen mode

Para rodar o teste basta executar o seguinte comando:

$ yarn cypress run --component
Enter fullscreen mode Exit fullscreen mode

ou ainda via interface

$ yarn cypress open
Enter fullscreen mode Exit fullscreen mode

Testes E2E com Cypress:

Os testes E2E simulam interações do usuário em uma aplicação completa. O Cypress é uma ferramenta poderosa para isso, permitindo simular cliques, preenchimento de formulários, navegação entre páginas e mais, enquanto monitora visualmente o comportamento da aplicação.

Exemplo de teste E2E com Cypress:

describe('Teste E2E em React com Cypress', () => {
  it('Deve fazer login corretamente', () => {
    cy.visit('/login');
    cy.get('input[name="username"]').type('usuario');
    cy.get('input[name="password"]').type('senha');
    cy.get('button[type="submit"]').click();
    cy.url().should('include', '/dashboard');
// ...
// podemos continuar esse teste fazendo diversas outras assertations em /dashboard para garantir o o bom funionanmento do workflow
  });
});
Enter fullscreen mode Exit fullscreen mode

Outros exemplos de testes

Vamos explorar exemplos específicos para testes mais avançados em Cypress, abordando pontos como API Mocking, Visual Regression Testing e Testes em Diferentes Dispositivos e Resoluções.

Exemplo 1: API Mocking

Suponha que você tenha um componente React que faz uma solicitação a uma API para recuperar dados. Aqui está um exemplo de como você pode usar o Cypress para simular essa chamada de API:

// cypress/integration/apiMocking.spec.js
describe('Teste E2E com API Mocking', () => {
  it('Deve simular a resposta da API', () => {
    cy.intercept('GET', '/api/data', { fixture: 'data.json' }).as('getData');
    cy.visit('/dashboard');
    cy.wait('@getData').its('response.statusCode').should('eq', 200);
    cy.get('.data-item').should('have.length', 5);
  });
});
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, o cy.intercept é usado para interceptar a chamada de API e fornecer uma resposta simulada a partir de um arquivo de fixture.

Exemplo 2: Visual Regression Testing

O Cypress suporta visual regression testing usando a biblioteca cypress-plugin-snapshots. Aqui está um exemplo básico:

// cypress/integration/visualRegression.spec.js
describe('Teste de Regressão Visual', () => {
  it('Deve garantir a consistência visual', () => {
    cy.visit('/dashboard');
    cy.matchImageSnapshot();
  });
});
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, cy.matchImageSnapshot() tira um print da página e a compara com uma referência anterior, alertando sobre qualquer diferença visual.

Exemplo 3: Testes em Diferentes Dispositivos e Resoluções

Cypress permite a simulação de diferentes dispositivos e resoluções. Veja um exemplo:

// cypress/integration/responsiveTesting.spec.js
describe('Teste de Responsividade', () => {
  it('Deve garantir layout responsivo', () => {
    cy.viewport('iphone-6');
    cy.get('.mobile-menu').should('be.visible');

    cy.viewport('macbook-15');
    cy.get('.desktop-menu').should('be.visible');
  });
});
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, cy.viewport é usado para simular diferentes tamanhos de tela e garantir que os elementos responsivos estejam visíveis conforme o esperado.

Estes são exemplos básicos, e a complexidade pode aumentar com a necessidade do seu projeto. Lembre-se de ajustar conforme necessário para atender aos requisitos específicos da sua aplicação.

Benefícios de Testes Abordados

Os principais benefícios dos testes incluem Garantia de Qualidade, Detecção Precoce de Problemas e Facilidade de Manutenção. A Garantia de Qualidade é assegurada através dos testes de componentes que verificam a funcionalidade individual de partes da aplicação. A Detecção Precoce de Problemas é obtida através dos testes E2E que identificam falhas em fluxos reais de usuário, permitindo a identificação e correção de problemas antes do lançamento. Por último, a Facilidade de Manutenção é conseguida por meio de testes automatizados que diminuem a necessidade de testes manuais repetitivos, permitindo uma maior precisão e eficiência.

A Garantia de Qualidade é um dos principais benefícios de realizar testes. Especificamente, os testes de componentes ajudam a assegurar que as partes individuais da aplicação funcionem corretamente. Isso é vital porque cada componente de uma aplicação é como um tijolo na construção de uma casa - se um tijolo é fraco ou defeituoso, pode comprometer a estrutura inteira. Portanto, garantir que cada componente funcione corretamente contribui para a construção de um produto final mais robusto e de alta qualidade, o que, por sua vez, traduz-se em uma melhor experiência para o usuário.

Outro benefício importante é a Detecção Precoce de Problemas. Aqui, os testes E2E desempenham um papel crucial. E2E, ou End-to-End, refere-se a testes que verificam o fluxo de uma aplicação, desde o início até o final. Estes testes identificam falhas em fluxos de usuário reais, permitindo que os desenvolvedores detectem e corrijam problemas antes do lançamento. Isso é extremamente valioso porque, sem esses testes, problemas podem passar despercebidos até o lançamento do produto, quando são mais difíceis e custosos de corrigir. A detecção precoce de problemas, portanto, evita problemas futuros e melhora a experiência do usuário.

Por último, mas não menos importante, os testes automatizados proporcionam Facilidade de Manutenção. Eles reduzem a necessidade de testes manuais repetitivos, o que não só economiza tempo, mas também garante uma maior precisão dos testes. Isso ocorre porque os testes manuais são propensos a erros humanos, enquanto os testes automatizados realizam as mesmas operações da mesma maneira todas as vezes. Além disso, os testes automatizados podem ser executados a qualquer momento, o que significa que os desenvolvedores podem verificar a qualidade do código constantemente, tornando a manutenção do código mais eficiente.

Conclusão

Investir em testes de componentes e E2E para aplicações React é crucial para o sucesso do desenvolvimento. O uso de ferramentas como Jest para testes de componentes e Cypress para testes E2E pode melhorar significativamente a qualidade e confiabilidade das aplicações, proporcionando uma experiência consistente para os usuários finais.

Este artigo oferece apenas uma visão geral, mas a prática constante e a adaptação às necessidades específicas do projeto são essenciais para garantir a eficácia dos testes em sua aplicação React.

Referências

Visual Testing | Cypress Documentation

Introduction to Cypress | Cypress Documentation

React Component Testing | Cypress Documentation

Repositório de pesquisa | GitHub

Top comments (0)