š§Ŗ E2E tests made easy with Cypress + Cucumber
If you're a developer I'm pretty sure end to end testing is something you've heard about a lot
While it may āsoundā like daunting task at first what if i tell you that there is a relatively easy way to implement itā¦
Feature : Test redirection
Scenario : Test the redirect
Given that im on "Home" page
When i click "#redirect"
Then i should see "Redirected" as "h1"
What you read just now is a fully functional test written in what is called a Gherkin syntax used by Cucumber which is a BDD testing tool and its open source ofcourse
But Cucumber on it's own isn't really capable of doing E2E tests And That's where Cypress comes in to save the day
Now, that's fine and all but
How exactly do we do it you may ask
Well apparantly its quite the simple process thanks to the magicāØ that's open source and the hardwork of badeball who created the
cypress-cucumber-preprocessor š„ which if you couldnāt guess already allows us to use cucumber along side cypress
now as you might expect (almost) nothing in the tech industry works without a bit of configuration and this tool is no exception, though the good thing is that it is pretty simple to configure and as a matter of fact it can be done in 3 super easy steps
Step 1 : Install all the dependencies
ofcoure š¤· duh weād have to do this one & itās kinda self explanatory, you only need to install a few things i.e cypress
, @badeball/cypress-cucumber-preprocessor
, esbuild
and lastly cypress-esbuild-preprocessor
To do so simply run the following command and watch it complete
yarn add --dev cypress @badeball/cypress-cucumber-preprocessor esbuild cypress-esbuild-preprocessor typescript
OR
npm install --save-dev cypress @badeball/cypress-cucumber-preprocessor esbuild cypress-esbuild-preprocessor typescript
if thatās your thing
now you can throw in Typescript (š) into this if you want to which I obviously did, but itās totally optional & upto you
Step 2 : Generating the basic configuration
Now that we have all what we need letās start the actual configuration but hereās the plot twist,
Initially though you will not have the basic cypress configuration, to generate it simply run
yarn cypress open
or npx cypress open
if npmās your thing
And follow the dialogs to configure the e2e testing and that should give you a basic configuration that we need
Step 3 : The Actual Configuration
Okay this time for sure
Now that we have all the basic configuration we need lets start by telling cypress to use the .feature files (thatās the extension for a test written with cucumber), To do that all we need to do is specify the āspecPatternā property in the cypress.config.ts (or .js if youre using js)
import { defineConfig } from "cypress";
export default defineConfig({
e2e:{
setupNodeEvents(on, config){
//
},
specPattern: "**/*.feature",
}
})
Now that thatās out of the way lets focus on the other part which is actually using the preprocessor to do that weāll have to use a bundler to process these .feature files, there are many bundlers out there so you can use any bundler you want to, I personally prefer using esbuild because it is fast and easy to configure
And so to do this all we have to do setup an on() event handler and configure our cypress-cucumber-preprocessor plugin and the bundler inside of the setupNodeEvents function that allows us to tap into, modify, or extend the internal behavior of Cypress
import { defineConfig } from "cypress";
import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor";
import createBundler from "@bahmutov/cypress-esbuild-preprocessor";
import createEsbuildPlugin from "@badeball/cypress-cucumber-preprocessor/esbuild";
export default defineConfig({
e2e:{
setupNodeEvents(on, config){
addCucumberPreprocessorPlugin(on, config);
on("file:preprocessor",createBundler({
plugins: [createEsbuildPlugin(config)],
});
)
},
specPattern: "**/*.feature",
}
})
And Thatās all weāre done with the configuration all thatās left is to take it for a spin and write some tests
Writing your First Test
To write a test just add a .feature file inside of the ā cypress/e2e/ ā folder and creative a respective spec file for it
what is a spec file? you may ask well its a file that tells cypress how to process the statements inside of the feature file, youāll see what i mean in just a sec
So lets quickly write a feature file first
Feature: Google.com
Scenario: visting the frontpage
When I visit google.com
Then I should see Google as the Title
And thatās it, all this test does is navigate to google.com and check whether the title for the website is google or not, simple as that š
Now obviously you can do more complex stuff with this but for the sake of demo and simplicity letās keep it to that for now
And letās move on to writing the actual spec file for this test, to do that just create a file ending in .ts (or .js) with the same name as that of the feature file e.g. google.ts if you called it google.feature
import { When, Then } from "@badeball/cypress-cucumber-preprocessor";
When("I visit google.com", () => {
cy.visit("https://google.com");
});
Then("I should see Google as the Title", () => {
cy.get("title").should("Google");
});
Now to run this test just run yarn cypress run
or npx cypress run
and if you followed through correctly then youāll see the test pass š
Common Step Definitions
You donāt have to actually write a spec file for each .feature file what you can do is use a common spec file and define all the reoccurring step definitions inside of it to do so add the following line inside of your package.json
"cypress-cucumber-preprocessor": {
"stepDefinitions": [
"cypress/e2e/common/index.ts"
]
}
and now you can define all the common step definitions inside of the index.ts and yes you can call this file whatever you want i call it index.ts because i kinda like it š¤·āāļø
Reusable Step definitions
YES, you read it right you can actually write reusable step definitions for the feature statements that you will probably use multiple times e.g.
Feature: Google.com
Scenario: visting the frontpage
When I visit "google.com"
Then I should see "Google" as the "title"
Notice the double quotes on google.com, Thats what we're going to use to make this statement reusable
The main part is tho happens in the spec file
import { When, Then } from "@badeball/cypress-cucumber-preprocessor";
When(`I visit {string}`, (url: string) => {
cy.visit(`https://${url}`);
});
Then(`I should see {string} as the {string}`, (text, target) => {
cy.get(location).should("contain", text);
});
What we do here is take arguments from the feature statements inside the double quotes and then we use them as parameters in the callbacks
And thus, We can now use these two statements as many times as we want to by just changing the values inside the double quotes
And That is How you can make End to End Testing much more easy and Fun for beginners on your team
Hello there š, Thank you for reading to the bottom, Hope you liked this blog and that it was Helpfull to you in some way or the other, This is the first blog post i ever wrote so please feel free to point out some short commings if you find any constructive criticism is always welcomed
Thank you for Reading, and I hope to see you on next one
Subscribe to my newsletter
Read articles from Takshak Ramteke directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Takshak Ramteke
Takshak Ramteke
I'm a 20 year old fun loving, enthusiastic & passionate Developer (+Designer) who loves Open source & free software stuff, I Currently work as a freelance fullstack developer and designer, professiant with tools like Next.js, TypeScript, prisma, etc. along with design tools like Figma, Inkscape & GIMP although Next.js (for dev) and Inkscape (for design) are my favourite ones I am also currently pursuing my Bachelors in computer science and engineering (senior year) from S.B.Jain Institute of Technology, Management and Research, Nagpur