Skip to Content
Diego Yuri
Youtube Instagram Github Linkedin

8 Minutos de Leitura


Aprenda a implementar cucumber ao Cypress em testes automatizados

Neste artigo, iremos explorar uma abordagem para implementar Cucumber com Cypress em projetos de automação de testes.


Antes de iniciarmos, precisamos que se tenha instalado e configurado os seguites pré-requisitos

Após a instalação dos itens, Vamos confirmar que o Node foi configurado corretamente. Abra o terminal e execute os comandos npm -v para verificar a versão do Node.js.

1npm -v
1npm -v

Se a versão for exibida corretamente, a configuração foi bem-sucedida.

Agora, criaremos uma pasta para o projeto e abriremos-a no Visual Studio Code. Após isso No terminal( CTRL + SHIFT + ' ) do VS Code, execute o comando:

1npm init -y
1npm init -y

Isso criará o arquivo package.json na pasta. Em seguida, instalaremos o Cypress e o plugin do Cucumber:

1npm install cypress --save-dev
2npm install cypress-cucumber-preprocessor --save-dev
1npm install cypress --save-dev
2npm install cypress-cucumber-preprocessor --save-dev

Após a instalação, abra o Cypress para criar uma estrutura inicial do projeto:

1npx cypress open
1npx cypress open

No Cypress, clique em "E2E Testing", escolha um navegador (por exemplo, Electron), crie um novo arquivo de especificação e execute o teste de exemplo, feito isso podemos fechar o cypress.

Neste ponto, é fundamental entender a estrutura das pastas do projeto. Teremos duas pastas principais: Cypress e Node_Modules. Além disso, serão encontrados os seguintes arquivos essenciais: Cypress.config.js, package-lock.json e package.json.

Estrutura de Pastas

Para iniciar a configuração do Cucumber, acessaremos o arquivo Cypress.config.js, onde importaremos o plugin necessário. Na primeira linha do código, adicionaremos o seguinte comando:

1const cucumber = require("cypress-cucumber-preprocessor").default;
1const cucumber = require("cypress-cucumber-preprocessor").default;

Feito isso, dentro deste mesmo arquivo, iremos adicionar a configuração do preprocessor dentro do Module.exports. Dentro da função setupNodeEvents, adicionaremos o seguinte comando:

1on("file:preprocessor", cucumber());
1on("file:preprocessor", cucumber());

Assim, o código neste momento ficará assim:

1const cucumber = require("cypress-cucumber-preprocessor").default;
2const { defineConfig } = require("cypress");
3
4module.exports = defineConfig({
5 e2e: {
6 setupNodeEvents(on, config) {
7 on("file:preprocessor", cucumber());
8 },
9 },
10});
1const cucumber = require("cypress-cucumber-preprocessor").default;
2const { defineConfig } = require("cypress");
3
4module.exports = defineConfig({
5 e2e: {
6 setupNodeEvents(on, config) {
7 on("file:preprocessor", cucumber());
8 },
9 },
10});

Além disso, dentro do bloco e2e, adicionaremos a localização das features. Embora isso possa ser configurado conforme preferência, por padrão, manteremos as features dentro da própria pasta e2e. A configuração será da seguinte forma:

1specPattern: "cypress/e2e/step_definitions/*.feature";
1specPattern: "cypress/e2e/step_definitions/*.feature";

Isso indica que nossos arquivos .feature estarão dentro da pasta STEP_DEFINITIONS na pasta e2e.

O arquivo final terá a seguinte aparência:

1const cucumber = require("cypress-cucumber-preprocessor").default;
2const { defineConfig } = require("cypress");
3
4module.exports = defineConfig({
5 e2e: {
6 setupNodeEvents(on, config) {
7 on("file:preprocessor", cucumber());
8 },
9 specPattern: "cypress/e2e/step_definitions/*.feature",
10 },
11});
1const cucumber = require("cypress-cucumber-preprocessor").default;
2const { defineConfig } = require("cypress");
3
4module.exports = defineConfig({
5 e2e: {
6 setupNodeEvents(on, config) {
7 on("file:preprocessor", cucumber());
8 },
9 specPattern: "cypress/e2e/step_definitions/*.feature",
10 },
11});

Entretanto, neste momento, a pasta necessária ainda não foi criada no projeto. Dentro da pasta e2e, encontraremos apenas o arquivo exemplo que criamos anteriormente ao abrir o Cypress. Portanto, podemos acessar a pasta e2e, excluir o arquivo de exemplo (spec.cy.js), e dentro desta mesma pasta, criar a pasta step_definitions.

Essa organização é crucial para estruturar o projeto de forma clara, eliminando arquivos desnecessários e preparando o terreno para a inclusão das definições de passos do Cucumber.

Com a estrutura inicial ajustada, é hora de realizar as configurações necessárias no arquivo package.json. Isso é crucial para garantir que o Cucumber e o Cypress funcionem harmoniosamente. Adicione a seguinte configuração dentro do bloco

1"cypress-cucumber-preprocessor": {
2 "nonGlobalStepDefinitions": true,
3 "stepDefinitions": "cypress/e2e/step_definitions"
4}
1"cypress-cucumber-preprocessor": {
2 "nonGlobalStepDefinitions": true,
3 "stepDefinitions": "cypress/e2e/step_definitions"
4}

Explicando cada parte:

  • nonGlobalStepDefinitions: Este é um comando padrão do plugin e é essencial para o seu correto funcionamento.

  • "stepDefinitions": "cypress/e2e/step_definitions": Aqui, especificamos o caminho para a pasta que contém as definições de etapas dos nossos testes. No exemplo, estamos definindo que nossos arquivos .js de definição de etapas estão na própria pasta step_definitions.

A estrutura final do seu arquivo package.json pode se assemelhar a este exemplo:

1{
2 "name": "artigo1",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "scripts": {
7 "test": "echo \"Error: no test specified\" && exit 1"
8 },
9 "keywords": [],
10 "author": "",
11 "license": "ISC",
12 "devDependencies": {
13 "cypress": "^13.6.2",
14 "cypress-cucumber-preprocessor": "^4.3.1"
15 },
16 "cypress-cucumber-preprocessor": {
17 "nonGlobalStepDefinitions": true,
18 "stepDefinitions": "cypress/e2e/step_definitions"
19 }
20}
1{
2 "name": "artigo1",
3 "version": "1.0.0",
4 "description": "",
5 "main": "index.js",
6 "scripts": {
7 "test": "echo \"Error: no test specified\" && exit 1"
8 },
9 "keywords": [],
10 "author": "",
11 "license": "ISC",
12 "devDependencies": {
13 "cypress": "^13.6.2",
14 "cypress-cucumber-preprocessor": "^4.3.1"
15 },
16 "cypress-cucumber-preprocessor": {
17 "nonGlobalStepDefinitions": true,
18 "stepDefinitions": "cypress/e2e/step_definitions"
19 }
20}

Essas configurações são cruciais para garantir que o ambiente esteja devidamente preparado para a integração do Cucumber com o Cypress, e que as definições de etapas estejam devidamente reconhecidas.

Neste ponto, todas as configurações essenciais foram realizadas para criar um ambiente de trabalho alinhado com o escopo do projeto. É importante destacar que seguimos uma abordagem específica para organizar nossos arquivos.

Na raiz da pasta STEP_DEFINITIONS, a prática será deixar nossos arquivos .feature. Mas a organização não para por aí. Dentro da pasta STEP_DEFINITIONS, criaremos uma pasta para cada feature. Isso significa que na raiz teremos o arquivo .feature correspondente, e dentro da pasta, teremos outros elementos relacionados a essa feature.

Este método de organização facilita a manutenção e compreensão do projeto, tornando a estrutura mais intuitiva. Afinal, um arquivo .feature na raiz representa a feature em si, enquanto a pasta com o nome da feature contém elementos adicionais relacionados a ela.

Essa abordagem flexível e intuitiva proporciona uma experiência mais clara e eficiente ao trabalhar com os testes e cenários definidos no projeto.

o nosso exemplo, o escopo do projeto se apresenta conforme a imagem abaixo:

Escopo do Projeto

Vale ressaltar que este tutorial não visa aprofundar-se no ensino detalhado das ferramentas, mas sim orientar sobre como implementar o Cucumber com Cypress. Inicialmente, abordaremos a utilização prática dessas ferramentas, proporcionando um entendimento gradual.

Vamos começar criando, na raiz da pasta step_definitions, o arquivo .feature para nosso projeto, nomeando-o como form.feature. A seguir, apresentarei um exemplo prático, delineando os passos do BDD (Behavior-Driven Development):

1Feature: Form
2
3Scenario: Valid Form
4Given que o site seja acessado
5When preencher o formulário
6Then Valido o acesso
1Feature: Form
2
3Scenario: Valid Form
4Given que o site seja acessado
5When preencher o formulário
6Then Valido o acesso

Este cenário fictício representa a interação com um formulário em um site. Durante a execução dos testes, cada passo (Given, When, Then) será associado a ações específicas no código de automação.

O intuito é proporcionar uma visão inicial do funcionamento do BDD/Cucumber no projeto, partindo de um exemplo simples.

Após criar e configurar o arquivo .feature, avançaremos para a criação da estrutura de funções. Dentro da pasta step_definitions, criaremos uma subpasta chamada form. Dentro dessa subpasta, será criado o arquivo form.js.

Para cada feature testada, será necessário implementar/importar os códigos dos passos do Cucumber, como Given, When, Then. Portanto, adicionaremos o seguinte código nos arquivos .js:

1import { Given, Then, When } from "cypress-cucumber-preprocessor/steps";
1import { Given, Then, When } from "cypress-cucumber-preprocessor/steps";

Este trecho de código localiza o caminho configurado no cypress.config.js, acessando o diretório steps.

O arquivo .js ficará da seguinte forma:

1import { Given, Then, When } from "cypress-cucumber-preprocessor/steps";
2
3Given("que o site seja acessado", () => {
4 cy.visit("https://vinothqaacademy.com/demo-site/");
5 cy.title().should("eq", "Demo Site – Registration Form – Vinoth Q.A Academy");
6});
7
8When("preencher o formulario", () => {
9 cy.get("#vfb-5").type("Yuri");
10 cy.get("#vfb-7").type("Lima");
11 cy.get("#vfb-31-1").click();
12 cy.get("#vfb-14").type("teste@teste.com");
13 cy.get("#vfb-3").type("99");
14 cy.get("#vfb-4").click();
15});
16
17Then("Valido acesso", () => {
18 cy.title().should("eq", "Demo Site – Dynamic Transaction – Vinoth Q.A Academy");
19});
1import { Given, Then, When } from "cypress-cucumber-preprocessor/steps";
2
3Given("que o site seja acessado", () => {
4 cy.visit("https://vinothqaacademy.com/demo-site/");
5 cy.title().should("eq", "Demo Site – Registration Form – Vinoth Q.A Academy");
6});
7
8When("preencher o formulario", () => {
9 cy.get("#vfb-5").type("Yuri");
10 cy.get("#vfb-7").type("Lima");
11 cy.get("#vfb-31-1").click();
12 cy.get("#vfb-14").type("teste@teste.com");
13 cy.get("#vfb-3").type("99");
14 cy.get("#vfb-4").click();
15});
16
17Then("Valido acesso", () => {
18 cy.title().should("eq", "Demo Site – Dynamic Transaction – Vinoth Q.A Academy");
19});

Aqui, utilizamos Given, When e Then em vez do habitual it do Cypress, construindo assim nosso ambiente conforme necessário. No exemplo, o passo Given valida o acesso ao site, onde é visitado e confirmado pelo título. O passo When realiza o preenchimento do formulário, e, por fim, o passo Then valida a página seguinte, para onde é redirecionado após o envio do formulário.

Essa abordagem básica exemplifica o comportamento do BDD/Cucumber no projeto, destacando a naturalidade da linguagem de especificação.

Ressalta-se a necessidade do entendimento do BDD e Cucumber, onde a nomenclatura inicial após abrir a função (Given, When, Then) deve ser exatamente a mesma definida no arquivo .feature.

No nosso exemplo:

1Given("que o site seja acessado", () => {
2 cy.visit("https://vinothqaacademy.com/demo-site/");
3 cy.title().should("eq", "Demo Site – Registration Form – Vinoth Q.A Academy");
4});
1Given("que o site seja acessado", () => {
2 cy.visit("https://vinothqaacademy.com/demo-site/");
3 cy.title().should("eq", "Demo Site – Registration Form – Vinoth Q.A Academy");
4});

A frase "que o site seja acessado" deve ser estritamente idêntica à linha "Given que o site seja acessado" contida no arquivo .feature. Qualquer divergência nesses pontos resultará na falha da execução do teste.

Na imagem a seguir, podemos visualizar a execução do teste.

Espero que tenham apreciado o conteúdo e que seja produtivo para vocês. Para qualquer assistência adicional, estou à disposição.

Teste Executado

Gif do Teste em Ação

Obrigado!