DEV Community

Cover image for E2E Testing with Cypress - 04 - Cucumber / Gherkin Integration
Kiran Parajuli for JankariTech

Posted on

E2E Testing with Cypress - 04 - Cucumber / Gherkin Integration

There is no official gherkin support available for Cypress, but there are nice libraries that add support for using feature files when testing with Cypress. Among them, we’re using cypress-cucumber-preprocessor in our project for automation testing.

To get started in Cypress with cucumber preprocessor, follow these simple steps:

Installation

npm install --save-dev cypress-cucumber-preprocessor
Enter fullscreen mode Exit fullscreen mode

Cypress Configuration

Add it to your plugins cypress/plugins/index.js:

const cucumber = require('cypress-cucumber-preprocessor').default

module.exports = (on, config) => {
  on('file:preprocessor', cucumber())
}
Enter fullscreen mode Exit fullscreen mode

Add support for feature files to your Cypress configuration cypress.json

{
  "testFiles": "**/*.feature"
}
Enter fullscreen mode Exit fullscreen mode

Pre-processor Configuration

It lets you define the path to a folder containing step definitions required for your tests.

Where to define? 🤔

You can use cosmiconfig which helps to search for and loading configuration for your program. Or you can configure simply by adding this to your package.json.

{
    "cypress-cucumber-preprocessor": {
      "nonGlobalStepDefinitions": true
  }
}
Enter fullscreen mode Exit fullscreen mode

Available Configurations

OPTION DEFAULT DESCRIPTION
commonPath cypress/integration/common when nonGlobalStepDefinitions is true
cypress/support/step_definitions when nonGlobalStepDefinitions is false
${nonGlobalStepBaseDir}/common when nonGlobalStepBaseDir is defined
define the path to a folder containing all common step definitions of your tests.
nonGlobalStepDefinitions false If true use the Cypress Cucumber Preprocessor Style pattern for placing step definitions files.
nonGlobalStepBaseDir undefined If defined and nonGlobalStepDefinitions is also true then step definition searches for folders with the features name will start from the directory provided here.
stepDefinitions cypress/integration when nonGlobalStepDefinitions is true
cypress/support/step_definitions when nonGlobalStepDefinitions is false
Path to the folder containing our step definitions.

Organize Tests

Single feature files

After adding .feature support in cypress configuration, you can add feature files in cypress/integration/

You can easily integrate Background, Scenario Outlines, DataTables within a feature file.

Bundled feature files

When running Cypress tests in the headless mode, the execution time can get pretty bloated, this happens because by default Cypress will relaunch the browser between every feature file. The cypress-cucumber-preprocessor gives you the option to bundle all feature files before running the tests, therefore reducing the execution time.

You can take advantage of this by creating .features files. You choose to have only one in the root of the directory cypress/integrations or per directory.

Adding support for .features files to your Cypress configuration

cypress.json

{
  "testFiles": "**/*.{feature,features}"
}
Enter fullscreen mode Exit fullscreen mode

Step Definitions

The steps in the .feature file look for their implementation inside a directory configured from preprocessor configuration. Step definitions files are by default in: cypress/support/step_definitions. If you want to put them somewhere else please use cosmiconfig format. For example, add to your package.json.

{
  "cypress-cucumber-preprocessor": {
    "step_definitions": "cypress/support/step_definitions/"
  }
}
Enter fullscreen mode Exit fullscreen mode

An example of some step definitions done in the cypress way is as follows:

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

const url = 'https://google.com'
Given('I open Google page', () => {
  cy.visit(url)
})
Then(`I see {string} in the title`, (title) => {
  cy.title().should('include', title)
})
Enter fullscreen mode Exit fullscreen mode

Before and After hooks

The cypress-cucumber-preprocessor supports both Mocha’s before/beforeEach/after/afterEach hooks and Cucumber’s Before and After hooks.

The cucumber hooks implementation fully supports tagging as described in the cucumberJs documentation. So they can be conditionally selected based on the tags applied to the Scenario. This is not possible with Mocha hooks.

Example:

const { Before, After, Given, Then }
  = require("cypress-cucumber-preprocessor/steps");

// this will get called before each scenario
Before(() => {
  beforeCounter += 1;
  beforeWithTagCounter = 0;
});

// this will only get called before scenarios tagged with @foo
Before({ tags: "@foo" }, () => {
  beforeWithTagCounter += 1;
});

Given("My Step Definition", () => {
  // ...test code here
})
Enter fullscreen mode Exit fullscreen mode

Note: to avoid confusion with the similarly named Mocha before and after hooks, the Cucumber hooks are not exported onto the global scope. So they need explicit importing as shown above.

Smart Tagging

Start your tests without setting any tags and then put a @focus on the scenario (or scenarios) you want to focus on while developing or bug fixing.

Feature: Smart Tagging

  As a cucumber cypress plugin which handles Tags
  I want to allow people to select tests to run if focused
  So they can work more efficiently and have a shorter feedback loop

  Scenario: This scenario should not run if @focus is on another scenario
    Then this unfocused scenario should not run

  @focus
  Scenario: This scenario is focused and should run
    Then this focused scenario should run

  @this-tag-affects-nothing
  Scenario: This scenario should also not run
    Then this unfocused scenario should not run

  @focus
  Scenario: This scenario is also focused and also should run
    Then this focused scenario should run
Enter fullscreen mode Exit fullscreen mode

Run tests

Run your Cypress Launcher the way you would usually do.

yarn run cypress open
Enter fullscreen mode Exit fullscreen mode

Then click on a .feature file on the list of specs, and see the magic happening!

  • Running tagged tests
  ./node_modules/.bin/cypress-tags run -e TAGS='not @foo and (@bar or @zap)'
Enter fullscreen mode Exit fullscreen mode
  • Limiting to a subset of feature files
    ./node_modules/.bin/cypress-tags run -e GLOB='cypress/integration/**/*.feature'
Enter fullscreen mode Exit fullscreen mode

You can also configure these from cypress configuration env property with TAGS sub-property.

  {
      "env": {
          "TAGS": "not @ignore"
      },
      //rest of configuration options
      "baseUrl": "yourBaseUrl",
      "ignoreTestFiles": "*.js"
      //etc
  }
Enter fullscreen mode Exit fullscreen mode

What's next

Cool! 😎 I’m sure this will get you started with cypress running your test in the Gherkin theme. Throughout the series, I've discussed E2E testing with Cypress, but in the next part of the series, we will be comparing cypress with other e2e testing frameworks. Till then, bye-bye, sayonara

Discussion (5)

Collapse
liviufromendtest profile image
Liviu Lupei

Have they figured out a way to switch between multiple browser tabs yet?
There are a ton of e2e scenarios which involve switching between browser tabs, such as SSO, 2FA, checking emails, checking external links, etc.

Collapse
kiranparajuli589 profile image
Kiran Parajuli Author

Cypress does not and may never have multi-tab support for various reasons. Multiple tabs work against the way Cypress automates your application and they are inherently flaky and inconsistent - even if we did find a way to support them. You can look here to look at what Cypress has to say about it. Luckily there are lots of easy and safe workarounds that enable you to test the behavior of your application. This repo contains some examples for links opening new tabs.

Collapse
liviufromendtest profile image
Liviu Lupei

Working with multiple tabs is flaky and inconsistent?
I don't think that is true.
Selenium can do that without any issue.
Browser tabs are browser tabs, they don't appear and disappear in a random way.
Even if your anchor element has the correct attributes, simply checking the existence and values of those attributes does not make up for the lack of an actual test.
That's just my opinion.
I noticed that all your articles are about Cypress.
Do you work for them or have they offered you any incentive to write positive things about them?
I think it's important that you should mention that.

Thread Thread
kiranparajuli589 profile image
Kiran Parajuli Author

If you're using Cypress as a test framework and you've managed to navigate to multiple tabs -- then the tests would surely go flaky and inconsistent because of Cypress architecture. I would highly recommend frameworks like Nightwatch, CodeceptJS, Behat, Behave which works together with selenium if you want to test multiple tabs web UI interactions.
P.S. I'm a QA developer and like to write about the tools I'm familiar with. 😊
Happy Coding!

Collapse
phillipebojorquez profile image
Phillipe Bojorquez

To get around navigating to another page based on a clicked link, use:

cy.get(selectors.productNameTitle)
.invoke('attr', 'href')
.then((href) => cy.visit(href));

Cypress has said they will never support multi-tab testing but do have some workarounds listed here: github.com/cypress-io/cypress-exam...