Aprenda a implementar cucumber ao Cypress em testes automatizados
Tags: cypress, cucumber, testes, automation
Published: 2023-12-30 23:30:55

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

- [Node.js](https://nodejs.org/en/)
- [Visual Studio Code](https://code.visualstudio.com/)

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.
```bash
npm -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:

```bash
npm init -y
```

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

```bash
npm install cypress --save-dev
npm install cypress-cucumber-preprocessor --save-dev
```

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

```bash
npx 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](https://yuridiego.tech/assets/img/blog/Esqueleto-1.png)

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:

```javascript
const 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:

```javascript
on('file:preprocessor', cucumber())
```

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

```javascript
const cucumber = require('cypress-cucumber-preprocessor').default;
const { defineConfig } = require("cypress");

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('file:preprocessor', cucumber())
     
    },
  },
});
```

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:

```javascript
specPattern: "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:

```javascript
const cucumber = require('cypress-cucumber-preprocessor').default;
const { defineConfig } = require("cypress");

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('file:preprocessor', cucumber())
      
    },
    specPattern: "cypress/e2e/step_definitions/*.feature"
  },
});
```


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

```json
"cypress-cucumber-preprocessor": {
  "nonGlobalStepDefinitions": true,
  "stepDefinitions": "cypress/e2e/step_definitions"
}
```

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:

```json
{
  "name": "artigo1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "cypress": "^13.6.2",
    "cypress-cucumber-preprocessor": "^4.3.1"
  },
  "cypress-cucumber-preprocessor": {
    "nonGlobalStepDefinitions": true,
    "stepDefinitions": "cypress/e2e/step_definitions"
  }
}
```

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](https://yuridiego.tech/assets/img/blog/Esqueleto-2.png)

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):

```gherkin
Feature: Form

Scenario: Valid Form
Given que o site seja acessado
When preencher o formulário
Then 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`:

```javascript
import { Given, When, Then } 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:

```javascript
import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';

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

When("preencher o formulario", () => {
    cy.get('#vfb-5').type('Yuri');
    cy.get('#vfb-7').type('Lima');
    cy.get('#vfb-31-1').click();
    cy.get('#vfb-14').type('teste@teste.com');
    cy.get('#vfb-3').type('99');
    cy.get('#vfb-4').click();
});

Then("Valido acesso", () => {
    cy.title().should('eq', 'Demo Site – Dynamic Transaction – Vinoth Q.A Academy');
});
```

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:

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

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](https://yuridiego.tech/assets/img/blog/Teste-Example.png)

![Gif do Teste em Ação](https://yuridiego.tech/assets/img/blog/form-feature.gif)

Obrigado!