Getting started with Cypress and Cucumber API
Vinayak Titti
Test Automation Engineer @Apple Inc | Corporate Trainer | ISTQB | SDET | Selenium Tester | Cypress & Playwright Automation | MABL | TestComplete | API Testing | JMeter | DevOps | AWS | AZURE |Test
e2e functional testing using Cypress-Cucumber-BDD framework…
Cypress Introduction
Cypress is a next generation javascript front end testing tool built for the modern web. Cypress enables to write all types of tests.
a. End-to-tend tests
b. Integration tests
c. Unit tests
Few of the features of cypress mentioned below:
a. Time travel: Dashboard test runner to see exactly what happened at each step of execution.
b. Debuggability using chrome dev tools
c. Automatic waiting
d. Network traffic control
e. Consistent results
f. Real time records
g. Screenshots & Videos: View screenshots taken automatically on failure, or videos of test suite when run from CLI.
Cucumber Introduction
Cucumber is a tool that supports Behaviour-Driven-Development (BDD). Cucumber reads executable specifications written in plain text and validates that the software does what those specifications say. The specifications consists of multiple examples, or scenarios. Each scenario is a list of steps for Cucumber to work through. Cucumber verifies that the software conforms with the specification and generates a report indicating success or failure for each scenario.
Ex:
Scenario: check buy a scarf Given I want to buy a wool scarf When I search for items containing 'wool' Then I should only see items related to 'wool'
Getting Started:
Create a CypressTest project folder and run command npm init to inject package.json file in the project root. Install Cypress & Cucumber node_modules as a dev dependency by executing below commands.
1. npm install cypress --save-dev 2. npm install --save-dev cypress-cucumber-preprocessor 3. npm link 4. npm link cypress-cucumber-preprocessor
To open Cypress dashboard test runner, we have to execute npx cypress open command. It will by default will install all cypress folders and cypress.json file where we can setup the baseurl configuration.
Folder Structure Description:
When execute npx cypress open for first time, Cypress will create a suggested folder structure as given below.
a. Integration folder will be located under cypress/integration to create spec or cucumber feature files.
b. Plugins/index.js file is used to add & load plugins when a project opened or re-opened.
c. Fixtures folder is used to create test data for data-driven testing.
d. Support folder is used to create & map cucumber step_definitions.
e. Commands file under support folder is used to create re-usable functions as given below
Cypress.Commands.add(‘logIn’, (args) => { }
Config: Step by step guidelines
Add plugin dependencies for `cypress-cucumber-preprocessor` module in the plugin/index.js file.
const cucumber = require('cypress-cucumber-preprocessor').default module.exports = (on, config) => { on('file:preprocessor', cucumber()); }
Create a SampleFunctionalTest.feature file in integration/features folder and add below snippet to the file.
Feature: Sample Login Test Scenario: check valid IMDB login test Given I open IMDB homepage When I click on "Sign In" And I press button "Sign in with IMDb" Then I should see "Sign-In" text displayed When I SignIn as user Then I should see title "Movies & TV Shows" And The account name should be displayed
Create a step_definitions file in the cypress/support folder and add below step implementations to the file.
import { loginPage } from '../../pageobjects/Login_PageObjects' Given('I open IMDB homepage', () => { cy.visit('/'); }); When('I SignIn as user', () => { loginPage.signIn(); }); then('The account name should be displayed', ()=>{ loginPage.verifyAccountNameDisplayed() })
Create a pageobjects folder and login_objetcs.js file & add below code snippet to the file.
const inputEmail = '#ap_email'; const inputPassword = '#ap_password'; const buttonSubmit = "https://input[@id='signInSubmit']"; const label_AccountName = "https://span[contains(@class,'imdb-header__account-toggle--logged-in')]"; export const loginPage = { enterEmail(args) { cy.get(inputEmail) .clear() .type(args); }, enterPassword(args) { cy.get(inputPassword) .clear() .type(args) }, clickSubmit() { cy.xpath(buttonSubmit) .click(); }, signIn() { cy.fixture('testdata').then((data) => { this.enterEmail(data.validemail); this.enterPassword(data.password); this.clickSubmit(); cy.wait(2000); }) }, verifyAccountNameDisplayed() { cy.fixture('testdata').then((data) =>{ cy.xpath(label_AccountName) .invoke('text') .should('contain', data.username); }) } }
Create a testdata.json file in `cypress/fixtures/` folder and add below test data to the file
{ "username": "username", "validemail": "[email protected]", "password": "Test1234", "invalidemail": "[email protected]" }
Create a shared.js file in `cypress/support/` folder and add below common step implementations to the file.
/* assertions */ then(`I should see title {string}`, (title) => { cy.title() .should('include', title) }) then(`I should see {string} text displayed`, (string) => { cy.contains(string) .invoke('show').should('be.visible'); }) then('The header should contain {string}', (string) => { cy.get('h1') .should('contain', string) }) then('The sub-header should contain {string}', (string) => { cy.get('h2') .should('contain', string) }) then('The header title should contain {string}', (string) => { cy.get('.header__title').invoke('text').then(function (text) { expect(text).to.include(string); }) }) then(`I should not see {string}`, (string) => { cy.contains(string, { timeout: 0 }) .should('not.be.visible'); }) then(`I should not see text {string}`, (string) => { cy.xpath('//*[contains(text(),"' + string + '")]') .should('not.be.visible'); }) then('The current url should contain {string}', function (string) { cy.url() .should('contain', string) }); /** * click action */ when('I click on {string}', (string) => { cy.xpath("https://*[contains(text(),'" + string + "')]") .first().click(); }) then('I press button {string}', (string) => { cy.contains(string) .click(); cy.wait(1000); }); // wait cmmds then('I wait for {string} secs', (string) => { cy.wait(string * 1000); }) then('I wait for few secs', () => { cy.wait(2000); })
Set baseurl in the cypress.json file: https://www.imdb.com/?ref_=nv_home
"baseUrl": "https://www.imdb.com/?ref_=nv_home",
Execution Time:
Dashboard Execution… Open Cypress dashboard test runner by running command npx cypress open in terminal. Test runner will be open as below, click on SampleFunctionalTest.feature file to execute the sample test.
Command Line Execution… For cmmd line execution create npm scripts in package.json file as below and run npm run test in terminal.
"scripts": { "test": "cypress run -b chrome -r mochawesome -s cypress/integration/features/SampleFunctionalTest.feature", "test:allure": "cypress run -b chrome -r mocha-allure-reporter -s cypress/integration/features/SampleFunctionalTest.feature", "generatereport": "allure generate allure-results --clean -o allure-report && allure open allure-report", },
Reports Part:
a. Command line logs:
b. Mochawesome HTML reports will be generated and saved to `mochawesome-report/mochawesome.html` file.
c. Allure graphical reports will be generated and saved to allure-results` folder.
Ending Part(Conclusion):
Cypress-cucumber-preprocessor is a great module for linking the accessibility of Cucumber with the robust testing framework of Cypress.js. With the integration of Cucumber with Cypress, we can write scripts in short time, less maintenance, reliable and provides easily readable documentation.
To get the scripts execute in seconds, can clone the given repo below into your local system and install the dependencies.
$ git clone https://github.com/vinayaktitti2015/Cypress-boilerplate.git $ npm install
*****************************************************************
Finally, please share feedback and give a free ?? for future updates and trending blogs.
Thanks!
Happy Learning 2020!