Cypress + Page Object = Sucesso
Que tal aprender esse padrão de projeto super utilizado nos dias de hoje e que nos faz economizar muuuuito tempo??
Bom, antes de começarmos a falar aqui sobre como implementar o padrão PageObject no nosso projeto Cypress, precisamos saber se vocês realmente sabem o que é PageObject.
“Eu já ouvi falar muuuito por alto, mas creio que seja algo que envolve as páginas dos nossos testes.”
Resumidamente falando… Page object é um padrão de projeto amplamente utilizado na área de QA e tem como objetivo separar os elementos e/ou ações das nossas páginas/telas dos nossos cenários de automação de testes. Ou seja, vamos criar uma separação entre nossos testes e as interações com as telas da nossa aplicação.
“Tá, mas qual é o benefício de fazer essa separação? Tá me parecendo que vou ter trabalho a mais sem muito ganho real…”
Isso vai nos trazer algumas vantagens como por exemplo:
- Facilidade na leitura e entendimento dos testes;
Nossos cenários ficarão muito mais enxutos, pois ao invés de blocos de código com ações diretamente nos testes, teremos a chamada de uma ou mais funções para a realização daquela ação.

- Reuso de código mais simplificado;
Como nossos elementos/ações ficarão separados dos testes, não vamos precisar copiar blocos de código para realizar ações repetidas dentro de cenários. Chamaremos apenas a referência já existente de um elemento ou ação específica daquela página.
- Mudanças vão gerar menos impacto nos testes;
Novamente, como nossos elementos/ações ficarão separados dos testes, não teremos necessidade de realizar alterações em todos os cenários onde aquela mudança impactará. Será necessário alterar apenas o arquivo onde se encontra a referência para aquela ação/elemento.
Levando em consideração esses benefícios, já podemos perceber que o PageObject só vai agregar no nosso projeto Cypress, então vamos lá para os próximos passos!!
Lembrando que existem várias formas de implementar o padrão PageObject, então vou trazer aqui a que acho mais organizada e fácil.
Mas antes… Vou deixar aqui um artigo explicando mais detalhadamente o objetivo e comportamento do padrão PageObject caso vocês se interessem ou não tenham captado muito bem a ideia.
Outro ponto importante é que vamos tomar como base o projeto Cypress que utilizamos nos artigos anteriores sobre esse framework. Caso você não tenha lido e/ou não tenha um projeto Cypress, deixo aqui o link pra o projeto que utilizamos nesses artigos:
E lá vamos nós… 🌊
Bom, vamos utilizar como base para fazer essa mudança a feature de ‘saucedemo.feature’ que utiliza o site https://www.saucedemo.com para execução dos cenários de teste.
Primeiramente precisamos criar um novo diretório chamado ‘pages’ (podem colocar o nome que acharem melhor, mas um pouco mais na frente vamos chamar esse diretório, então lembre de mudar lá também) dentro do nosso diretório de ‘support’. Então o caminho fica assim: ‘cypress/support/pages’.
Como você deve estar imaginando, dentro desse diretório ‘pages’ vão ficar os nossos PageObject’s. Porém, vamos separar os elementos da ações, ou seja, os identificadores dos elementos ficarão em um local e as ações realizadas naquela página ficarão em outro. Lembrando que isso é opcional, nós podemos deixar esses dois juntos.
Vamos agora criar uma pasta chamada ‘login’ dentro desse diretório (‘cypress/support/pages/login’), essa pasta vai ser responsável por guardar todas as informações de elementos e ações referentes ‘a página de login do sistema. Em seguida criamos um arquivo chamado ‘elements.js’ dentro da pasta de login com as seguintes informações:
Se vocês prestaram atenção, nós simplesmente criamos uma const chamada ELEMENTS que possui alguns valores. Essas chaves-valores correspondem exatamente aos localizadores dos elementos que são utilizados nos nossos cenários:
“Ok, nós já temos os localizadores dos elementos que vamos utilizar nos cenários, mas onde a gente coloca isso?” 😐
Nós poderíamos usar esses localizadores diretamente nos nossos stepdefinitions, mas a ideia aqui é deixarmos tudo bem encapsulado e organizado. Então vamos agora criar outro arquivo chamado ‘index.js’ dentro do mesmo diretório de ‘login’.
Esse arquivo vai ser responsável por realizar as ações dentro da nossa página utilizando os elementos que já definimos no arquivo de ‘elements.js’.
Primeiramente precisamos importar a variável ELEMENTS que está no arquivo ‘elements.js’ e que contém os localizadores dos elementos que vamos utilizar nas ações da página. Pra isso adicionamos a instrução const elem = require(‘./elements’).ELEMENTS;
Depois disso vamos criar as funções que realizarão as ações na nossa página/tela/aplicação. É nesse ponto que começamos a usar os localizadores que criamos anteriormente.
Normalmente chamamos um elemento no Cypress dessa forma:
cy.get(‘[id=user-name]’)
Porém, como já possuímos o localizador do elemento de usuário, vamos alterar para esse formato:
cy.get(elem.username)
Lembre que importamos os elementos dentro da constante ‘elem’. Ao apontarmos para ‘elem.username’, estamos dizendo que vamos pegar o valor referente ‘a chave ‘username’ dentro da constante ELEMENTS.
Vou deixar aqui embaixo o código de como ficariam as ações para a tela de login da nossa feature, pega visão:
E por último mas não menos importante, precisamos disponibilizar essa classe para ser utilizada em outros momentos. Para isso vamos incluir o código abaixo que será responsável por fazer a exportação dessa classe:
export default login();
Pra facilitar a visualização de tudo que eu falei que era necessário nesse arquivo de ações, podem dar uma olhada aqui em como ele vai ficar:
Feito isso, podemos agora chamar nossas ações dentro dos nossos stepdefinitions!! ❤ ❤
Partiu Stepdefs 🏃
Agora não tem segredo, é só chutar pro gol e correr pra o abraço!!
Simplesmente vamos pegar nossos steps que são realizados na tela de login e alterar o código deles para chamar as ações que criamos com os PageObject’s.
Se liguem em como estão os steps atualmente:
Perceberam que existem dois steps para o login, sendo o primeiro responsável por acessar a página e validar se ela foi carregada, e o segundo responsável por inserir as informações do login e prosseguir.
Como vocês se lembram, nós criamos duas funções dentro da nossa classe de ‘index.js’ para realizar essas ações, são elas acessAndValidateLoginPage e logIntoTheSystem. Simplesmente vamos alterar o código de dentro do step para apenas realizarmos a chamada dessas funções!!
Obs: O único ponto que precisamos de atenção é na hora de importar a classe de ‘index.js’, pois precisamos realizar essa ação para termos acesso ‘as funções criadas para realizar as ações. Para isso vamos utilizar o seguinte comando:
import login from ‘../../support/pages/login’
Com isso nos indicamos que estamos importando a classe de login que se encontra no arquivo index.js de caminho ‘../../support/pages/login’
.
“Calma, em nenhum momento eu vi você indicando o nome do arquivo ‘index.js’ no comando, como ele vai saber qual é o arquivo?? E outra, por que usamos esses ‘../../’ ”
Vamos lá… Quando importamos um diretório sem especificar qual é o arquivo e esse diretório possui um arquivo chamado ‘index.js’, o Node entende que esse arquivo ‘index.js’ será utilizado no import, por isso não precisamos passar o nome dele no comando.
Agora falando sobre os ‘../../’
Cada ‘../’ no caminho do arquivo serve para informar um nível de antecedência na hierarquia de pastas. Ou seja, estamos dizendo que a partir do arquivo que estamos agora (cypress/integration/saucedemo/steps.js), precisamos primeiramente voltar dois níveis de pastas (cypress/integration/) para depois acessarmos o caminho correto (cypress/integration/support/pages/login).
Caso essas explicações não tenham ficado muito claras, podem dar uma olhada nesse texto aqui que explica mais detalhadamente alguns aspectos desse tema:
Tudo explicado, agora é só colocar o import certinho e chamar as ações dentro dos steps. Vou deixar aqui embaixo uma ideia de como deve ficar, pega visão:
Notaram como os steps ficam mais organizados e bem escritos?? Isso facilita a leitura e entendimento de quem for avaliar ou dar manutenção na automação.
E é só 😎
Perceberam que aqui eu fiz apenas uma página do nosso arquivo de feature, né? Agora que vocês já sabem como criar os PageObject’s para suas páginas, podem replicar isso para todas as outras páginas e até adicionar outros cenários já iniciando-os utilizando esse novo padrão!!
Lembrando que eu deixei o caminho do projeto que utilizo nesses artigos do Cypress lá no começo do artigo, então podem dar uma olhada se ficaram com alguma dúvida!!
Hora de vocês colocarem a mão na massa e da minha partida…