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(oucypress.config.ts). - Para versões mais antigas do Cypress (abaixo da 10): No arquivo
cypress.json.
Por Que Usar a baseUrl?
- URLs Mais Curtas e Limpas nos Testes:
- Sem
baseUrl:cy.visit('https://minha-aplicacao-incrivel.com/pagina-de-login'); - Com
baseUrlconfigurada parahttps://minha-aplicacao-incrivel.com:cy.visit('/pagina-de-login'); - Bem mais legível e menos propenso a erros de digitação na URL base!
- Sem
- 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 testescy.visit('/caminho')apontarão para o novo ambiente.
- Imagine que você tem diferentes ambientes para sua aplicação: Desenvolvimento (ex:
- Melhora a Manutenibilidade:
- Se o domínio principal da sua aplicação mudar, você só precisa atualizar a
baseUrl. Seus testes continuam intactos.
- Se o domínio principal da sua aplicação mudar, você só precisa atualizar a
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 suabaseUrl.- Se
baseUrl: 'https://meusite.com', entãocy.visit('/')irá parahttps://meusite.com/.
- Se
cy.visit('/caminho/da/pagina'): Irá navegar parabaseUrl+/caminho/da/pagina.- Se
baseUrl: 'https://meusite.com', entãocy.visit('/login')irá parahttps://meusite.com/login.
- Se
cy.visit('https://outro-dominio-completamente.diferente.com/outra-pagina'): Se você passar uma URL completa (comhttp://ouhttps://), abaseUrlé 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 parabaseUrl+/api/dados.- Se
baseUrl: 'https://meusite.com', entãocy.request('/api/users')irá parahttps://meusite.com/api/users.
- Se
cy.request('https://api.externa.com/info'): Mesma lógica docy.visit(), abaseUrlé 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
- Sempre configure uma
baseUrl: É uma das primeiras coisas que você deve fazer ao iniciar um novo projeto Cypress. - Combine com Variáveis de Ambiente: Para cenários de CI/CD (Integração Contínua/Entrega Contínua), você raramente vai “commitar” a
baseUrlde produção diretamente. Em vez disso, você pode configurar abaseUrlpara ler de uma variável de ambiente.- Exemplo no
cypress.config.js:
- Exemplo no
module.exports = defineConfig({
e2e: {
baseUrl: process.env.CYPRESS_BASE_URL || 'http://localhost:3000',
// ...
},
});
- E então, no seu pipeline de CI, você definiria
CYPRESS_BASE_URLpara a URL do ambiente apropriado. - Cuidado com Barras (
/):baseUrl: 'https://meusite.com'(sem barra no final) ecy.visit('/login')resulta emhttps://meusite.com/login.baseUrl: 'https://meusite.com/'(com barra no final) ecy.visit('login')(sem barra no início) também resulta emhttps://meusite.com/login.- Seja consistente para evitar
//nas URLs. A prática comum é não ter barra no final dabaseUrle sempre começar seus caminhos nocy.visit()com uma/se for a partir da raiz dabaseUrl.
“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:
- Arquivos de Configuração por Ambiente: Criaremos arquivos JSON distintos para cada ambiente, cada um contendo sua
baseUrlespecífica e outras configurações que possam variar (ex:defaultCommandTimeoutespecífico para um ambiente mais lento). - Pasta
config: Organizaremos esses arquivos em uma pastaconfigna raiz do nosso projeto Cypress. - 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
- Na raiz do seu projeto Cypress (onde está a pasta
cypresse ocypress.config.js), crie uma nova pasta chamadaconfig. - Dentro da pasta
config, crie três arquivos JSON:dev.jsonqa.jsonprd.json
- Edite cada arquivo para incluir a
baseUrle 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:
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.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 é:- Uma variável de ambiente do Cypress
configFilepassada via--env(ex:npx cypress open --env configFile=qa). - Uma variável de ambiente do sistema
CYPRESS_ENV(ex:CYPRESS_ENV=qa npx cypress open). - Se nenhuma for definida, usamos
'dev'como padrão.
- Uma variável de ambiente do Cypress
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 (comobaseUrl,defaultCommandTimeout) sobrescreverão as padrões definidas nocypress.config.jsou os padrões do próprio Cypress.mergedConfig.e2e.baseUrl = environmentConfig.baseUrl || config.e2e.baseUrl: Garantimos que abaseUrldo arquivo de ambiente seja aplicada à configuraçãoe2e.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.
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 openCYPRESS_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:
- Configure os arquivos
config/dev.json,config/qa.jsoncombaseUrls diferentes (podem ser URLs fictícias para teste, comohttp://dev.meuapp.localehttp://qa.meuapp.local). - Atualize seu
cypress.config.jscom a lógica mostrada acima. - 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'));
});
});
- Execute o Cypress especificando diferentes ambientes:
npx cypress open --env configFile=dev(oucross-env CYPRESS_ENV=dev npx cypress open)- Observe os logs no terminal e no Test Runner. O
cy.logdeve mostrar “dev” e abaseUrlde dev.
- Observe os logs no terminal e no Test Runner. O
- Feche o Cypress e rode:
npx cypress open --env configFile=qa(oucross-env CYPRESS_ENV=qa npx cypress open)- Agora o
cy.logdeve mostrar “qa” e abaseUrlde qa.
- Agora o
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.