Testing front-end applications with Cucumber and Cypress

Leonardo Tironi Fassini
TaqtileBR
Published in
6 min readDec 1, 2020

In this article I’ll be explaining how to test your front-end applications with Cucumber using Cypress to run the assertions and a preprocessor to integrate both of them.

It will be split in two parts. The first one is where the Gherkin language will be explained, together with some examples and uses. In the second one, it will be about how to execute the commands of Cucumber with Cypress.

Photo by William Iven on Unsplash

Gherkin language

The Gherkin language follow a tab and line indentation. This means that after every keyword, if the next keyword is nested, then it should be separated by a line and a new space shall be made.

In the Gherkin language, there are some key words where most of our tests will be based on. Below it’s the meaning of them.

Feature

This is where you define the meaning of this test. In the above example, all my scenarios will be about logging in. I could make all possible tests, like “does my login page support wrong passwords?”, “does my login page handle sql injection?”. Making all these tests, each one in a different file, would make things messy, and that’s why we group them by the feature we are testing.

Right under a Feature, you can also add any type of comment, like “I want to test signing in into my application”. This comment section will end when you type another Gherkin key word.

Scenario

A Scenario (also called an Example in new Cucumber versions) is where you say what exactly you will be testing. We already defined the feature, now we will define what part of the feature we will test. In the above example, I’m testing if my application supports the happy path. In other words, if I provide the right credentials, then I should be able to log in.

Each scenario consist of a list of steps. These steps are executed one right after another, in the order you wrote them. If a step fail, then the next step won’t be executed.

Given

This step is used to define something that have already happened. In the login example, the Given is that I’m already in the login page. Some other examples could be

  • Given I have money
  • Given there’s 3 bananas on the shop

When

This step determine an action that should be done. In the login example, the actions are:

  • Try to input your login
  • Try to input your password
  • Try to click on login button.

And

Writing Given, When and Then more than once can be a little ugly to read, so you can use And to mimic the last step you made. Example:

  • Given I have money
  • And there’s three bananas available in the shop

instead of

  • Given I have money
  • Given there’s three bananas available in the shop

However, you don’t need to specifically declare the step definition as an And. Cucumber preprocessor treat And , Given and Then as the same thing on the step definitions. So, if you use in more than one case, and both cases are considered the same statement (Given , as example), then it’s best to maintain the Given on the step definition and use And on the statement.

Then

This step is where the assertion should occur. After you do some action, there should be a result of that action, right? here is where you verify if the result really occurred, and if it occured as expected. In the above example the result expected was that I would be redirected to the todo page. Some other example could be:

  • Then I should be able to buy a banana.

Background

A background is used when there’s the need to do something before any scenario begins and should be ran before every scenario.

Suppose that before every step on login, it is needed to go to the login page. If I put it in every scenario, I would be repeating myself and that’s not cool. We are trying to get time with tests, so it shouldn’t be good spending it repeating yourself.

That’s were the background is useful. We could make a background that could be something like “ Given i am at the login page”, which redirect us to the login page and our problems would be solved!

Scenario outline

To explain what a scenario outline is, let me first introduce a problem. Suppose we have to write a scenario like this:

If we needed to add some other fruits or other liquids to this feature, then it would be a tedious task to do right? That’s why scenario outline exists. It is defined like this:

Instead of passing the fruit directly to my step, it’s passed the example column instead. This Scenario Outline would run once for every line in the example. This means that first it would try the combination banana — milk — good, then apple — milk — good and so on.

Step definitions

When we are defining the steps, sometimes we will need the same step definition, but for some other purpose. Let’s use the fruit example:

  • When I put a banana in the bowl
  • When I put an apple in the bowl

To solve this problem we can use the step definition to make it. Step definitions are declared like this:

The (a|an) part is just to let Cucumber run this example even if I use a banana or an apple. It will be returned as the first argument, since I won’t use it, I just put an _. The second one, which is the one we want, will be sent to us as a string and is defined by {<type>}. We can also use this to define the steps of a Scenario Outline, and by this way, allowing our test code creation be faster.

Just to make things clear, Cucumber will always return the variables in order. So, if you made something like

The variable first will be the first {string} we created, the variable second will be the second one and so on. A step definition for the first example I gave, in the beginning of this article is

After you created all your Features, Scenarios, and Steps, you can easily look at the DOM to make the assertions using Cypress (there’s a guide on the way). Below I’ll link a full implementation of an application with Cucumber and Cypress integrated.

Tagging

You can use tags on your feature files to have a more granular control over the scenarios. They can be used either to allow only some tags to run, as to run something before running the tagged scenario.

As an example, suppose you have an application which can only be accessed if the user is logged in. When you’re testing something inside the application, it’s not needed to test the login case again, so you can mock the user data onto your browser and test only the targeted features.

Before and After

Those two functions are used to do something before running the scenarios. Let’s use the following example:

Instead of using the Background statement, which would run in every scenario of this feature, I could have ran a Before targeting a tag like @loggedIn at the feature, and the script would have done the same as Background. The main difference between background and Before is that you can run the Before on any feature that have the @loggedIn tag.

Troubleshooting

Hint

You can also code your step definitions in Typescript. To do so, change your index.ts to this:

And also create a config.ts file.

And finally, create a typings.d.ts where inside there’s only an import.

If you don’t want to do thin last part, you need to put in every file the following comment:

Cannot find step for Given with variables.

Use string instead of regexp. Example:

Cannot find step for Given with options (a|b).

Use regexp instead of normal string.

References

--

--