A Mágica da baseUrl – Simplificando suas Visitas!

O Que é a baseUrl?

Pensem na baseUrl como o “endereço padrão” da sua aplicação para os testes do Cypress. É uma configuração que você define uma única vez no seu arquivo de configuração do Cypress, e ela serve como o prefixo para todos os seus comandos cy.visit() e cy.request() que usam caminhos relativos.

Onde configurar?

  • Para Cypress 10 e superior: No arquivo cypress.config.js (ou cypress.config.ts).
  • Para versões mais antigas do Cypress (abaixo da 10): No arquivo cypress.json.

Por Que Usar a baseUrl?

  1. URLs Mais Curtas e Limpas nos Testes:
    • Sem baseUrl: cy.visit('https://minha-aplicacao-incrivel.com/pagina-de-login');
    • Com baseUrl configurada para https://minha-aplicacao-incrivel.com: cy.visit('/pagina-de-login');
    • Bem mais legível e menos propenso a erros de digitação na URL base!
  2. Facilidade para Mudar de Ambiente:
    • Imagine que você tem diferentes ambientes para sua aplicação: Desenvolvimento (ex: http://localhost:3000), Staging (ex: https://staging.meuapp.com), e Produção (ex: https://meuapp.com).
    • Sem baseUrl, você teria que mudar a URL completa em todos os seus testes para rodá-los em um ambiente diferente. Que pesadelo! 😱
    • Com baseUrl, você muda apenas essa configuração em um único lugar (ou usa variáveis de ambiente para defini-la dinamicamente), e todos os seus testes cy.visit('/caminho') apontarão para o novo ambiente.
  3. Melhora a Manutenibilidade:
    • Se o domínio principal da sua aplicação mudar, você só precisa atualizar a baseUrl. Seus testes continuam intactos.

Como Configurar a baseUrl (Cypress 10+)?

É super simples! Abra seu arquivo cypress.config.js e adicione a propriedade e2e.baseUrl:

(Exemplo no cypress.config.js)

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

module.exports = defineConfig({
  e2e: {
    // Aqui definimos a baseUrl para nossos testes E2E
    baseUrl: 'https://todomvc.com/examples/react/dist/', // <<< NOSSA BASEURL AQUI!
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
    // Outras configurações de E2E podem vir aqui, como specPattern, etc.
  },
  // Outras configurações globais do Cypress podem vir aqui
  // defaultCommandTimeout: 5000, 
});

E para quem usa versões mais antigas (abaixo da 10)?

No cypress.json:

{
  "baseUrl": "https://todomvc.com/examples/react/dist/",
  "defaultCommandTimeout": 5000
}

“Agora, vamos dar como exemplo o TodoMVC. Em vez de digitar a URL completa em cada beforeEach, podemos configurar a baseUrl.”


Como a baseUrl Funciona com cy.visit() e cy.request()?

Uma vez que a baseUrl está configurada:

  • cy.visit('/'): Irá navegar para a sua baseUrl.
    • Se baseUrl: 'https://meusite.com', então cy.visit('/') irá para https://meusite.com/.
  • cy.visit('/caminho/da/pagina'): Irá navegar para baseUrl + /caminho/da/pagina.
    • Se baseUrl: 'https://meusite.com', então cy.visit('/login') irá para https://meusite.com/login.
  • cy.visit('https://outro-dominio-completamente.diferente.com/outra-pagina'): Se você passar uma URL completa (com http:// ou https://), a baseUrl é ignorada para aquele comando específico. Isso é útil se você precisar interagir com um site externo em um teste.
  • cy.request('/api/dados'): Fará uma requisição para baseUrl + /api/dados.
    • Se baseUrl: 'https://meusite.com', então cy.request('/api/users') irá para https://meusite.com/api/users.
  • cy.request('https://api.externa.com/info'): Mesma lógica do cy.visit(), a baseUrl é ignorada se uma URL completa for fornecida.

Demonstração Prática no VSCode

“Vamos pegar nosso arquivo de teste do TodoMVC (todomvc.cy.js). Lembram do nosso beforeEach?”

// Antes (sem baseUrl configurada ou sem usá-la efetivamente)
// cypress/e2e/todomvc.cy.js
describe('Testes para a aplicação TodoMVC', () => {
    beforeEach(() => {
        cy.visit('https://todomvc.com/examples/react/dist/'); // URL completa
    });
    // ... seus testes ...
});

“Agora, com a baseUrl: 'https://todomvc.com/examples/react/dist/' configurada no cypress.config.js, podemos simplificar:”

// Depois (com baseUrl configurada)
// cypress/e2e/todomvc.cy.js
describe('Testes para a aplicação TodoMVC com baseUrl', () => {
    beforeEach(() => {
        cy.visit('/'); // Visita a raiz da baseUrl!
    });

    it('Deve adicionar uma tarefa (usando baseUrl)', () => {
        const novaTarefa = 'Entender baseUrl';
        cy.get('.new-todo').type(`${novaTarefa}{enter}`);
        cy.get('.todo-list li')
          .should('have.length', 1)
          .and('contain.text', novaTarefa);
    });
    // ... outros testes ...
});

“Salvem ambos os arquivos (cypress.config.js e todomvc.cy.js) e executem os testes do TodoMVC novamente. Eles devem funcionar exatamente da mesma forma! Mas nosso código de teste ficou mais limpo e flexível.”

Simulando Mudança de Ambiente:

“Agora, imaginem que a equipe de desenvolvimento nos deu uma nova URL para o ambiente de Staging do TodoMVC: https://staging.todomvc.com/examples/react/dist/.”

“O que precisaríamos fazer para rodar nossos testes lá? Simplesmente iríamos ao cypress.config.js e mudaríamos:”

// cypress.config.js (exemplo de alteração)
module.exports = defineConfig({
  e2e: {
    baseUrl: 'https://staging.todomvc.com/examples/react/dist/', // URL do ambiente de Staging
    // ...
  },
});

“E pronto! Todos os cy.visit('/'), cy.visit('/alguma-rota-interna') agora apontariam para o ambiente de Staging. Nenhuma alteração nos arquivos de teste seria necessária para os caminhos relativos.”


Dicas e Boas Práticas

  1. Sempre configure uma baseUrl: É uma das primeiras coisas que você deve fazer ao iniciar um novo projeto Cypress.
  2. Combine com Variáveis de Ambiente: Para cenários de CI/CD (Integração Contínua/Entrega Contínua), você raramente vai “commitar” a baseUrl de produção diretamente. Em vez disso, você pode configurar a baseUrl para ler de uma variável de ambiente.
    • Exemplo no cypress.config.js:
module.exports = defineConfig({
  e2e: {
    baseUrl: process.env.CYPRESS_BASE_URL || 'http://localhost:3000',
    // ...
  },
});
  1. E então, no seu pipeline de CI, você definiria CYPRESS_BASE_URL para a URL do ambiente apropriado.
  2. Cuidado com Barras ( / ):
    • baseUrl: 'https://meusite.com' (sem barra no final) e cy.visit('/login') resulta em https://meusite.com/login.
    • baseUrl: 'https://meusite.com/' (com barra no final) e cy.visit('login') (sem barra no início) também resulta em https://meusite.com/login.
    • Seja consistente para evitar // nas URLs. A prática comum é não ter barra no final da baseUrl e sempre começar seus caminhos no cy.visit() com uma / se for a partir da raiz da baseUrl.

“A baseUrl é uma pequena configuração com um grande impacto na organização, legibilidade e manutenibilidade dos seus testes Cypress. Adotem-na desde o início e simplifiquem a forma como seus testes navegam pela sua aplicação!”

Gerenciamento Avançado de baseUrl: Configurando Múltiplos Ambientes

À medida que nossos projetos crescem, testar em diferentes estágios do ciclo de vida do software se torna crucial. Não queremos testar apenas em localhost! Precisamos validar em ambientes de QA, Staging e, às vezes, até mesmo rodar um conjunto seguro de testes em Produção.

A Estratégia:

  1. Arquivos de Configuração por Ambiente: Criaremos arquivos JSON distintos para cada ambiente, cada um contendo sua baseUrl específica e outras configurações que possam variar (ex: defaultCommandTimeout específico para um ambiente mais lento).
  2. Pasta config: Organizaremos esses arquivos em uma pasta config na raiz do nosso projeto Cypress.
  3. Lógica Dinâmica no cypress.config.js: Nosso arquivo principal de configuração do Cypress (cypress.config.js) lerá o ambiente desejado (geralmente através de uma variável de ambiente) e carregará o arquivo JSON correspondente.

Passo 1: Criando a Pasta e os Arquivos de Configuração por Ambiente

  1. Na raiz do seu projeto Cypress (onde está a pasta cypress e o cypress.config.js), crie uma nova pasta chamada config.
  2. Dentro da pasta config, crie três arquivos JSON:
    • dev.json
    • qa.json
    • prd.json
  3. Edite cada arquivo para incluir a baseUrl e quaisquer outras configurações específicas do ambiente:

(Exemplo: config/dev.json)

{
  "baseUrl": "http://localhost:3000",
  "defaultCommandTimeout": 4000,
  "video": false
}

(Exemplo: config/qa.json)

{
  "baseUrl": "https://qa.minha-aplicacao-incrivel.com",
  "defaultCommandTimeout": 8000

}

(Exemplo: config/prd.json)

{
  "baseUrl": "https://www.minha-aplicacao-incrivel.com",
  "defaultCommandTimeout": 10000,

  "env": {
    "isProd": true
  }
}

Observação: Você pode adicionar quaisquer configurações válidas do Cypress nesses arquivos. Elas serão mescladas com a configuração base. O env no prd.json é um exemplo de como passar variáveis de ambiente específicas para os testes daquele ambiente.


Passo 2: Modificando o cypress.config.js para Carregar a Configuração Dinamicamente

Agora, vamos fazer a mágica acontecer no cypress.config.js. Precisaremos dos módulos fs (File System) e path do Node.js para ler os arquivos.

(Conteúdo do cypress.config.js)

const { defineConfig } = require('cypress');
const fs = require('fs'); // Módulo File System do Node.js
const path = require('path'); // Módulo Path do Node.js

// Função para carregar a configuração do ambiente
function getConfigurationByFile(environment) {
  const pathToConfigFile = path.resolve('config', `${environment}.json`); // Caminho para o arquivo de config

  if (!fs.existsSync(pathToConfigFile)) {
    console.warn(`Arquivo de configuração para o ambiente "${environment}" não encontrado em: ${pathToConfigFile}`);
    console.warn('Usando configuração padrão ou vazia.');
    return {}; // Retorna um objeto vazio ou uma config padrão se o arquivo não existir
  }

  console.log(`Carregando configuração do ambiente: ${environment} de ${pathToConfigFile}`);
  return JSON.parse(fs.readFileSync(pathToConfigFile, 'utf-8'));
}

module.exports = defineConfig({
  // Primeira forma: Definir o ambiente via variável de ambiente CYPRESS_ENV
  // Ex: CYPRESS_ENV=qa npx cypress open
  // Se CYPRESS_ENV não estiver definida, podemos usar um ambiente padrão, como 'dev'.
  e2e: {
    setupNodeEvents(on, config) {
      // Pegar o nome do ambiente da variável de ambiente (ex: CYPRESS_ENV)
      // Ou você pode definir um ambiente padrão se a variável não estiver configurada.
      const environment = config.env.configFile || process.env.CYPRESS_ENV || 'dev';

      // Carregar as configurações do arquivo JSON do ambiente correspondente
      const environmentConfig = getConfigurationByFile(environment);

      // Mesclar a configuração carregada com a configuração base do Cypress.
      // A configuração do arquivo de ambiente terá precedência.
      // Precisamos garantir que o baseUrl seja aplicado corretamente dentro de 'e2e'.
      const mergedConfig = {
        ...config, // Configuração base do Cypress (incluindo o que vem da linha de comando)
        ...environmentConfig, // Configurações do arquivo JSON (pode sobrescrever baseUrl, defaultCommandTimeout, etc.)
        e2e: {
          ...config.e2e,
          ...environmentConfig.e2e, // Se tiver configurações e2e específicas no JSON
          baseUrl: environmentConfig.baseUrl || config.e2e.baseUrl, // Garante que baseUrl seja aplicado
        },
        env: { // Mescla variáveis de ambiente
            ...config.env,
            ...environmentConfig.env,
            currentEnv: environment, // Adiciona o ambiente atual às variáveis de ambiente do Cypress
        }
      };

      // Se o baseUrl não estiver na raiz do JSON, mas sim dentro de uma chave 'e2e'
      if (environmentConfig.e2e && environmentConfig.e2e.baseUrl) {
        mergedConfig.e2e.baseUrl = environmentConfig.e2e.baseUrl;
      } else if (environmentConfig.baseUrl) { // Se baseUrl estiver na raiz do JSON
        mergedConfig.e2e.baseUrl = environmentConfig.baseUrl;
      }
      // Faça o mesmo para outras configurações que podem estar na raiz ou em e2e


      console.log(`Configuração final para o ambiente "${environment}":`);
      console.log('Base URL:', mergedConfig.e2e.baseUrl);
      console.log('Default Command Timeout:', mergedConfig.defaultCommandTimeout);
      // Adicione outros logs conforme necessário

      return mergedConfig;
    },
    // Você pode ter um baseUrl padrão aqui, que será sobrescrito
    // baseUrl: 'http://default.example.com',
    specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
  },
  // Outras configurações globais padrão podem ir aqui
  // defaultCommandTimeout: 3000,
  // video: true,
});

Entendendo o cypress.config.js acima:

  1. getConfigurationByFile(environment): Esta função constrói o caminho para o arquivo JSON (ex: config/qa.json), verifica se ele existe e, se existir, lê e parseia seu conteúdo.
  2. setupNodeEvents(on, config): Esta é a função onde podemos modificar a configuração do Cypress antes que os testes rodem.
    • environment = config.env.configFile || process.env.CYPRESS_ENV || 'dev': Tentamos obter o nome do ambiente. A ordem de precedência é:
      1. Uma variável de ambiente do Cypress configFile passada via --env (ex: npx cypress open --env configFile=qa).
      2. Uma variável de ambiente do sistema CYPRESS_ENV (ex: CYPRESS_ENV=qa npx cypress open).
      3. Se nenhuma for definida, usamos 'dev' como padrão.
    • environmentConfig = getConfigurationByFile(environment): Carregamos a configuração do arquivo.
    • mergedConfig = { ... }: Mesclamos a configuração base do Cypress com a configuração carregada do arquivo. As configurações do arquivo JSON do ambiente (como baseUrl, defaultCommandTimeout) sobrescreverão as padrões definidas no cypress.config.js ou os padrões do próprio Cypress.
    • mergedConfig.e2e.baseUrl = environmentConfig.baseUrl || config.e2e.baseUrl: Garantimos que a baseUrl do arquivo de ambiente seja aplicada à configuração e2e.
    • env: { ...currentEnv: environment }: É uma boa prática adicionar o nome do ambiente atual às variáveis de ambiente do Cypress (Cypress.env('currentEnv')), para que seus testes possam saber em qual ambiente estão rodando, se necessário.
  3. return mergedConfig;: Retornamos a configuração finalizada para o Cypress usar.

Passo 3: Executando o Cypress com um Ambiente Específico

Agora, para rodar seus testes contra um ambiente específico, você precisará definir a variável de ambiente CYPRESS_ENV (ou configFile via --env) antes de executar o Cypress.

Exemplos no Terminal:

  • Para rodar no ambiente de QA:
    • CYPRESS_ENV=qa npx cypress open
    • CYPRESS_ENV=qa npx cypress run
    • usando a flag --env: npx cypress open --env configFile=qa
  • Para rodar no ambiente de Desenvolvimento (se for seu padrão, ou explicitamente):
    • CYPRESS_ENV=dev npx cypress open
  • Para rodar no ambiente de Produção:
    • CYPRESS_ENV=prd npx cypress open

Dica para package.json scripts:

Para facilitar e garantir consistência entre diferentes sistemas operacionais, você pode usar o pacote cross-env. Primeiro, instale-o: npm install --save-dev cross-env ou yarn add --dev cross-env.

Depois, no seu package.json, você pode adicionar scripts como:

{
  "scripts": {
    "cy:open:dev": "cross-env CYPRESS_ENV=dev cypress open",
    "cy:run:dev": "cross-env CYPRESS_ENV=dev cypress run",
    "cy:open:qa": "cross-env CYPRESS_ENV=qa cypress open",
    "cy:run:qa": "cross-env CYPRESS_ENV=qa cypress run --browser chrome",
    "cy:open:prd": "cross-env CYPRESS_ENV=prd cypress open",
    "cy:run:prd": "cross-env CYPRESS_ENV=prd cypress run --spec 'cypress/e2e/smoke-tests/**'"
  }
}

E então você pode rodar, por exemplo: npm run cy:open:qa ou yarn cy:run:qa.


Demonstração Prática e Verificação:

  1. Configure os arquivos config/dev.json, config/qa.json com baseUrls diferentes (podem ser URLs fictícias para teste, como http://dev.meuapp.local e http://qa.meuapp.local).
  2. Atualize seu cypress.config.js com a lógica mostrada acima.
  3. Crie um teste simples em cypress/e2e/meu_teste.cy.js:
describe('Teste de Ambiente', () => {
  it('Deve visitar a baseUrl correta e logar o ambiente', () => {
    cy.visit('/'); // Visita a raiz da baseUrl configurada
    cy.log(`Estou rodando no ambiente: ${Cypress.env('currentEnv')}`);
    cy.log(`Minha baseUrl é: ${Cypress.config('baseUrl')}`);
    cy.url().should('include', Cypress.config('baseUrl'));
  });
});
  1. Execute o Cypress especificando diferentes ambientes:
    • npx cypress open --env configFile=dev (ou cross-env CYPRESS_ENV=dev npx cypress open)
      • Observe os logs no terminal e no Test Runner. O cy.log deve mostrar “dev” e a baseUrl de dev.
    • Feche o Cypress e rode: npx cypress open --env configFile=qa (ou cross-env CYPRESS_ENV=qa npx cypress open)
      • Agora o cy.log deve mostrar “qa” e a baseUrl de qa.

Configurar múltiplos ambientes dessa forma torna seu framework de testes Cypress muito mais flexível, profissional e adaptável às realidades de um ciclo de desenvolvimento de software. Você pode facilmente alternar entre baseUrls, timeouts, números de retentativas e até mesmo variáveis de ambiente específicas para cada contexto, mantendo seus arquivos de teste limpos e focados na lógica de teste, não na configuração do ambiente.

Leave a Comment

Your email address will not be published. Required fields are marked *