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
baseUrl
configurada 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
baseUrl
de produção diretamente. Em vez disso, você pode configurar abaseUrl
para 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_URL
para 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 dabaseUrl
e 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
baseUrl
específica e outras configurações que possam variar (ex:defaultCommandTimeout
específico para um ambiente mais lento). - Pasta
config
: Organizaremos esses arquivos em uma pastaconfig
na 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
cypress
e ocypress.config.js
), crie uma nova pasta chamadaconfig
. - Dentro da pasta
config
, crie três arquivos JSON:dev.json
qa.json
prd.json
- 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:
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
configFile
passada 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.js
ou os padrões do próprio Cypress.mergedConfig.e2e.baseUrl = environmentConfig.baseUrl || config.e2e.baseUrl
: Garantimos que abaseUrl
do 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 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:
- Configure os arquivos
config/dev.json
,config/qa.json
combaseUrl
s diferentes (podem ser URLs fictícias para teste, comohttp://dev.meuapp.local
ehttp://qa.meuapp.local
). - Atualize seu
cypress.config.js
com 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.log
deve mostrar “dev” e abaseUrl
de 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.log
deve mostrar “qa” e abaseUrl
de 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 baseUrl
s, 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.