Overview
In this tutorial, we will create some UI tests as Cucumber Scenario(s)/Scenario Outline(s) and use Cypress to implement the tests in JavaScript.
Requirements
- Node.js
- cucumber-json-formatter
- npm packages
- cypress
-
@badeball/
cypress-cucumber-preprocessor
Description
For the purpose of this tutorial, we'll use a dummy website (source-code here) containing just a few pages to support login/logout kind of features; we aim to test precisely those features.
We need to configure Cypress to use the new @badeball/cypress-cucumber-preprocessor,
which provides the ability of understanding .feature files and also of producing Cucumber JSON reports.
This is done in Cypress' main configuration file, where you can also define the base URL of the website under test, the regex of the files that contain the test scenarios (i.e. <...>.feature files). Other options may be defined (e.g for bypassing chromeWebSecurity, additional reporters, the ability to upload results to Cypress infrastructure in the cloud, etc).
The configuration of @badeball/cypress-cucumber-preprocessor
can either be done on a JSON file .cypress-cucumber-preprocessorrc.json
or within package.json
.
Next, you may find an example of the contents of package.json.
We need to have the cucumber-json-formatter
tool, which can be downloaded from the respective GitHub repository. Make sure you pick the correct binary for your environment.
This tool is necessary to convert the Cucumber messages protobuf (*.ndjson file) report generated by @badeball/cypress-cucumber-preprocessor
.
In case you need to interact with Xray REST API at low-level using scripts (e.g. Bash/shell scripts), this tutorial uses an auxiliary file with the credentials (more info in Global Settings: API Keys).
Before moving into the actual implementation, we need to decide is which workflow we'll use: do we want to use Xray/Jira as the master for writing the declarative specification (i.e. the Gherkin based Scenarios), or do we want to manage those outside using some editor and store them in Git, for example?
Learn more
Please see Testing in BDD with Gherkin based frameworks (e.g. Cucumber) for an overview of the possible workflows.
The place that you'll use to edit the Cucumber Scenarios will affect your workflow. There are teams that prefer to edit Cucumber Scenarios in Jira using Xray, while there others that prefer to edit them by writing the .feature files by hand using some IDE.
Using Jira and Xray as master
This section assumes using Xray as master, i.e. the place that you'll be using to edit the specifications (e.g. the scenarios that are part of .feature files).
The overall flow would be something like this:
- create Scenario/Scenario Outline as a Test in Jira; usually, it would be linked to an existing "requirement"/Story (i.e. created from the respective issue screen)
- implement the code related to Gherkin statements/steps and store it in Git, for example
- generate .feature files based on the specification made in Jira
- checkout the code from Git
- run the tests in the CI
- import the results back to Jira
Usually, you would start by having a Story, or similar (e.g. "requirement"), to describe the behavior of a certain feature and use that to drive your testing.
If you have it, then you can just use the "Create Test" on that issue to create the Scenario/Scenario Outline and have it automatically linked back to the Story/"requirement".
Otherwise, you can create the Test using the standard (issue) Create action from Jira's top menu.
In this case, we'll create a Cucumber Scenario.
We need to create the Test issue first and fill out the Gherkin statements later on in the Test issue screen.
After the Test is created it will impact the coverage of related "requirement", if any.
The coverage and the test results can be tracked in the "requirement" side (e.g. user story). In this case, you may see that coverage changed from being UNCOVERED to NOTRUN (i.e. covered and with at least one test not run).
Additional tests could be created, eventually linked to the same Story or linked to another one (e.g. logout).
The related statement's code is managed outside of Jira and stored in Git, for example.
In Cypress, tests related code is mainly stored under cypress/integration
directory, which itself contains several other directories. In this case, we've organized the assets as follows:
cypress/support/step_definitions
: step implementation files, in JavaScript.cypress/integration/pages
: abstraction of different pages, somehow based on the page-objects model
You can then export the specification of the test to a Cucumber .feature file via the REST API, or the Export to Cucumber UI action from within the Test/Test Execution issue or even based on an existing saved filter. A plugin for your CI tool of choice can be used to ease this task.
So, you can either:
- use the UI
- use the REST API (more info here)
- use one of the available CI/CD plugins (e.g. see an example of Integration with Jenkins)
We will export the features to a new directory named features/
on the root folder of your Cypress project (we'll need to tell Cypress to use this folder).
After being exported, the created .feature(s) will contain references to the Test issue key, eventually prefixed (e.g. "TEST_") depending on an Xray global setting, and the covered "requirement" issue key, if that's the case. The naming of these files is detailed in Generate Cucumber Features.
To run the tests and produce Cucumber JSON reports(s), we can either use npm
or cypress
command directly.
npm run test # or instead... node_modules/cypress/bin/cypress run --spec 'features/**/*.feature'
This will produce one Cucumber JSON report.
After running the tests, results can be imported to Xray via the REST API, or the Import Execution Results action within the Test Execution, or by using one of the available CI/CD plugins (e.g. see an example of Integration with Jenkins).
#!/bin/bash BASE_URL=https://xray.cloud.getxray.app token=$(curl -H "Content-Type: application/json" -X POST --data @"cloud_auth.json" "$BASE_URL/api/v2/authenticate"| tr -d '"') curl -H "Content-Type: application/json" -X POST -H "Authorization: Bearer $token" --data @"cucumber-report.json" "$BASE_URL/api/v2/import/execution/cucumber"
Which Cucumber endpoint/"format" to use?
To import results, you can use two different endpoints/"formats" (endpoints described in Import Execution Results - REST):
- the "standard cucumber" endpoint
- the "multipart cucumber" endpoint
The standard cucumber endpoint (i.e. /import/execution/cucumber) is simpler but more restrictive: you cannot specify values for custom fields on the Test Execution that will be created. This endpoint creates new Test Execution issues unless the Feature contains a tag having an issue key of an existing Test Execution.
The multipart cucumber endpoint will allow you to customize fields (e.g. Fix Version, Test Plan), if you wish to do so, on the Test Execution that will be created. Note that this endpoint always creates new Test Executions (as of Xray v4.2).
In sum, if you want to customize the Fix Version, Test Plan and/or Test Environment of the Test Execution issue that will be created, you'll have to use the "multipart cucumber" endpoint.
A new Test Execution will be created (unless you originally exported the Scenarios/Scenario Outlines from a Test Execution).
One of the tests fails (on purpose).
The execution screen details of the Test Run will provide overall status information and Gherkin statement-level results, therefore we can use it to analyze the failing test.
A given example can be expanded to see all Gherkin statements and, if available, it is possible to see also the attached screenshot(s).
Note: in this case, the bug was on the Scenario Outline example which was using a valid username/password combination.
Results are reflected on the covered item (e.g. Story). On its issue screen, coverage now shows that the item is OK based on the latest testing results, that can also be tracked within the Test Coverage panel bellow.
Using Git or other VCS as master
You can edit your .feature files using your IDE outside of Jira (eventually storing them in your VCS using Git, for example) alongside with remaining test code.
In any case, you'll need to synchronize your .feature files to Jira so that you can have visibility of them and report results against them.
The overall flow would be something like this:
- look at the existing "requirement"/Story issue keys to guide your testing; keep their issue keys
- specify Cucumber/Gherkin .feature files in your IDE supporting Cypress and store it in Git, for example
- implement the code related to Gherkin statements/steps and store it in Git, for example
- import/synchronize the .feature files to Xray to provision or update corresponding Test entities
- export/generate .feature files from Jira, so that they contain references to Tests and requirements in Jira
- checkout the Cypress related code from Git
- run the tests in the CI
- import the results back to Jira
Usually, you would start by having a Story, or similar (e.g. "requirement"), to describe the behavior of a certain feature and use that to drive your testing.
Having those to guide testing, we could then move to Cypress to describe and implement the Cucumber test scenarios.
In Cypress, tests related code is mainly stored inside the cypress/integration
directory, which itself contains several other directories. In this case, we've organized the assets as follows:
cypress/support/step_definitions
: step implementation files, in JavaScript.cypress/integration/pages
: abstraction of different pages, somehow based on the page-objects modelcypress/integration/login
: Cucumber .feature files, containing the tests as Gherkin Scenario(s)/Scenario Outline(s). Please note that each "Feature: <..>" section should be tagged with the issue key of the corresponding "requirement"/story in Jira. You may need to add a prefix (e.g. "REQ_") before the issue key, depending on an Xray global setting.
Before running the tests in the CI environment, you need to import your .feature files to Xray/Jira; you can invoke the REST API directly or use one of the available plugins/tutorials for CI tools.
Please note
Each Scenario of each .feature will be created as a Test issue that contains unique identifiers, so that if you import once again then Xray can update the existent Test and don't create any duplicated tests.
Afterward, you can export those features out of Jira based on some criteria, so they are properly tagged with corresponding issue keys; this is important because results need to contain these references.
You can then export the specification of the test to a Cucumber .feature file via the REST API, or the Export to Cucumber UI action from within the Test/Test Execution issue or even based on an existing saved filter. A plugin for your CI tool of choice can be used to ease this task.
So, you can either:
- use the UI
- use the REST API (more info here)
- use one of the available CI/CD plugins (e.g. see an example of Integration with Jenkins)
For CI only purpose, we will export the features to a new temporary directory named features/
on the root folder of your Cypress project (we'll need to tell Cypress to use this folder). Please note that while implementing the tests, .feature files should be edited inside the cypress/integration/login folder, in this case;
After being exported, the created .feature(s) will contain references to the Test issue keys, eventually prefixed (e.g. "TEST_") depending on an Xray global setting, and the covered "requirement" issue key, if that's the case. The naming of these files is detailed in Generate Cucumber Features.
@REQ_CALC-632 Feature: As a user, I can login the application #As a user, I can login the application #Tests As a user, I can logout the application @TEST_CALC-634 Scenario: Valid Login Given browser is opened to login page When user "demo" logs in with password "mode" Then welcome page should be open #Tests As a user, I can logout the application @TEST_CALC-635 Scenario: Invalid Login Given browser is opened to login page When user "dummy" logs in with password "password" Then error page should be open @TEST_CALC-636 Scenario Outline: Login With Invalid Credentials Should Fail Given browser is opened to login page When user "<username>" logs in with password "<password>" Then error page should be open Examples: | username | password | | invalid | mode | | demo | invalid | | invalid | invalid | | demo | mode |
To run the tests and produce Cucumber JSON reports(s), we can either use npm
or cypress
command directly.
npm run test # or instead... node_modules/cypress/bin/cypress run --spec 'features/**/*.feature'
This will produce one Cucumber JSON report.
After running the tests, results can be imported to Xray via the REST API, or the Import Execution Results action within the Test Execution, or by using one of the available CI/CD plugins (e.g. see an example of Integration with Jenkins).
Which Cucumber endpoint/"format" to use?
To import results, you can use two different endpoints/"formats" (endpoints described in Import Execution Results - REST):
- the "standard cucumber" endpoint
- the "multipart cucumber" endpoint
The standard cucumber endpoint (i.e. /import/execution/cucumber) is simpler but more restrictive: you cannot specify values for custom fields on the Test Execution that will be created. This endpoint creates new Test Execution issues unless the Feature contains a tag having an issue key of an existing Test Execution.
The multipart cucumber endpoint will allow you to customize fields (e.g. Fix Version, Test Plan), if you wish to do so, on the Test Execution that will be created. Note that this endpoint always creates new Test Executions (as of Xray v4.2).
In sum, if you want to customize the Fix Version, Test Plan and/or Test Environment of the Test Execution issue that will be created, you'll have to use the "multipart cucumber" endpoint.
A new Test Execution will be created (unless you originally exported the Scenarios/Scenario Outlines from a Test Execution).
One of the tests fails (on purpose).
The execution screen details of the Test Run will provide overall status information and Gherkin statement-level results, therefore we can use it to analyze the failing test.
A given example can be expanded to see all Gherkin statements and, if available, it is possible to see also the attached screenshot(s).
Note: in this case, the bug was on the Scenario Outline example which was using a valid username/password combination.
Results are reflected on the covered item (e.g. Story). On its issue screen, coverage now shows that the item is OK based on the latest testing results, that can also be tracked within the Test Coverage panel bellow.
If we change the specification (i.e. the Gherkin scenarios), we need to import the .feature(s) once again.
Therefore, in the CI we always need to start by importing the .feature file(s) to keep Jira/Xray on synch.
FAQ and Recommendations
Please see this page.