Integrating jira with cucumber and serenity js for enhanced test management

Oct 8, 2024 | by Ralph Van Der Horst

Integrating JIRA with Cucumber and Serenity/JS for Enhanced Test Management

Test automation is crucial to ensuring the quality and reliability of applications. Combining Serenity/JS, Cucumber, and Playwright offers a powerful testing framework that allows developers and testers to write clean, expressive BDD-style tests while leveraging Playwright’s robust browser automation capabilities. When integrated with JIRA, you can manage and track issues efficiently, ensuring any bugs uncovered during testing are logged and actionable right away.

In this post, we’ll walk through a simple example of integrating JIRA with Cucumber, Serenity/JS, and Playwright for effective test case management.

Prerequisites

To follow along, you’ll need the following:

  • Node.js installed on your machine
  • Cucumber, Serenity/JS, and Playwright set up in your project
  • A JIRA account and API access token for interacting with JIRA programmatically
  • A JIRA Project to manage your issues

Step 1: Set Up Serenity/JS, Cucumber, and Playwright

If you haven’t already, you can install Cucumber, Serenity/JS, and Playwright as dependencies:

npm install --save @serenity-js/core @serenity-js/assertions @serenity-js/web @cucumber/cucumber @playwright/test

To follow along, you’ll need the following:

  • Node.js installed on your machine
  • Cucumber, Serenity/JS, and Playwright set up in your project
  • A JIRA account and API access token for interacting with JIRA programmatically
  • A JIRA Project to manage your issues

Step 1: Set Up Serenity/JS, Cucumber, and Playwright

If you haven’t already, you can install Cucumber, Serenity/JS, and Playwright as dependencies:

npm install --save @serenity-js/core @serenity-js/assertions @serenity-js/web @cucumber/cucumber @playwright/test

if you want to skipp the installation I have also have an example github environment which you can clone, specific for this jira integration exersise. This github is a clone of the orginal github provided by the senenity team itself. Cucumber JIRA Integration GitHub Repository.

For more details and the complete codebase, you can check out the Cucumber playwright serenity-js GitHub Repository.

With this setup, you can start creating your test steps in Cucumber using Serenity/JS and Playwright for smooth, powerful assertions and browser interactions.

Step 2: Define a Cucumber Step with a JIRA Issue Report

Let’s take a look at an example where we are testing checkboxes on a webpage and want to log a JIRA issue if any of the tests fail. Here’s a breakdown of how this can be achieved.

Step 1: Define locators for your elements

You’ll want to select specific elements on the page for testing. In this example, we’re locating two checkboxes using Playwright:

import { PageElement, By } from '@serenity-js/web';

const FirstCheckbox = PageElement.located(By.css('[for="checkbox1"]')).describedAs('first checkbox');
const SmileyIconForFirst = PageElement.located(By.css('label[for="checkbox1"] .icon')).describedAs('smiley icon for first checkbox');

Step 2: Write test steps to interact with these elements

Using assertions, you can validate behavior. Below, we’ll attempt to select the checkbox and verify if it displays the expected icon. If the test fails, we’ll log the issue in JIRA.

Here’s an example step definition file jira.steps.ts:

import { Given, When, Then } from '@cucumber/cucumber';
import { Actor } from '@serenity-js/core';
import { Navigate, PageElement, Click, isSelected, isVisible, Text } from '@serenity-js/web';
import { Ensure, equals } from '@serenity-js/assertions';
import { By } from '@serenity-js/web';
import { createJiraIssue } from '../../test/interactions/ReportToJira';
import { Browser, chromium } from '@playwright/test';

const FirstCheckbox = PageElement.located(By.css('[for="checkbox1"]')).describedAs('first checkbox');
const SecondCheckbox = PageElement.located(By.css('[for="checkbox2"]')).describedAs('second checkbox');
const SmileyIconForFirst = PageElement.located(By.css('label[for="checkbox1"] .icon')).describedAs('smiley icon for first checkbox');
const SmileyIconForSecond = PageElement.located(By.css('label[for="checkbox2"] .icon')).describedAs('smiley icon for second checkbox');

// Step to navigate to the Checkboxes page
Given('{actor} navigates to the Checkboxes page', async (actor: Actor) =>
    actor.attemptsTo(
        Navigate.to('https://practiceautomatedtesting.com/webelements/Checkboxes')
    )
);

// Step to check the first checkbox, ensuring visibility with Ensure
When('{pronoun} checks the first checkbox', async (actor: Actor) =>
    actor.attemptsTo(
        Ensure.that(FirstCheckbox, isVisible()),  // Ensure the checkbox is visible
        Click.on(FirstCheckbox)                   // Click the checkbox once visible
    )
);

// Step to verify that the first checkbox is checked and displays a smiley face
Then('{pronoun} should see that the first checkbox is checked with a smiley icon', async (actor: Actor) => {
    const featureFileName = 'Checkbox.feature';  // Feature file name for reference
    const gwtSteps = \`
      Given the user navigates to the Checkboxes page
      When the user checks the first checkbox
      Then the user should see that the first checkbox is checked with a smiley icon
    \`;
    
    try {
        await actor.attemptsTo(
            Ensure.that(FirstCheckbox, isSelected()),               // Ensure the first checkbox is selected
            Ensure.that(Text.of(SmileyIconForFirst), equals('😊'))  // Ensure the smiley icon shows a happy face
        );
    } catch (error) {
        console.error('Test failed:', error.message);
        await createJiraIssue(error.message, featureFileName, gwtSteps);  // Pass the error message, feature file name, and GWT steps
    }
});

Integrating with JIRA for Issue Tracking

To automatically create a JIRA issue whenever a test fails, we can add an interaction in ReportToJira.ts that sends a PostRequest to JIRA’s REST API. Here’s how:

import { actorCalled } from '@serenity-js/core';
import { CallAnApi, LastResponse, PostRequest, Send } from '@serenity-js/rest';
import { Ensure, equals } from '@serenity-js/assertions';

export async function createJiraIssue(errorDescription: string, featureFileName: string, gwtSteps: string) {
    const JIRA_BASE_URL = 'https://learnautomatedtesting.atlassian.net';
    const PROJECT_KEY = 'XSP';
    const ISSUE_TYPE = 'Bug';
    const JIRA_USERNAME = process.env.JIRA_USERNAME || 'your username'; //(is your email)
    const JIRA_API_TOKEN = process.env.JIRA_API_TOKEN || 'your api key';

    await actorCalled('JiraReporter')
        .whoCan(CallAnApi.at(JIRA_BASE_URL))
        .attemptsTo(
            Send.a(PostRequest.to('/rest/api/3/issue').with({
                fields: {
                    project: {
                        key: PROJECT_KEY,
                    },
                    summary: `Automated Test Failure in Feature: ${featureFileName} - Unable to Login`,
                    description: {
                        type: 'doc',
                        version: 1,
                        content: [
                            {
                                type: 'paragraph',
                                content: [
                                    {
                                        type: 'text',
                                        text: `The following feature file failed: Steps:

${gwtSteps}`
                                    }
                                ]
                            },
                            {
                                type: 'paragraph',
                                content: [
                                    {
                                        type: 'text',
                                        text: `The test failed with the following error:

${errorDescription}`
                                    }
                                ]
                            }
                        ]
                    },
                    issuetype: {
                        name: ISSUE_TYPE,
                    },
                },
            }).using({
                headers: {
                    'Authorization': `Basic ${Buffer.from(`${JIRA_USERNAME}:${JIRA_API_TOKEN}`).toString('base64')}`,
                    'Content-Type': 'application/json',
                }
            })),
            Ensure.that(LastResponse.status(), equals(201))
        );
}

With this setup, you can leverage Playwright for browser interactions, Serenity/JS for BDD-style testing, and JIRA for automatic issue tracking. This combination provides a robust solution for maintaining test coverage and addressing bugs effectively.

Important Note on Real-life Defect Creation

In real-life applications, you typically don’t create JIRA defects automatically for every test failure in automation. This approach could lead to an overload of issues in JIRA. Instead, it’s recommended to review test results first, and then selectively create defects for specific failures as needed. This can be managed by implementing a boolean flag to control defect creation, enabling you to rerun tests for which defects should be logged.

For more details and the complete codebase, you can check out the Cucumber JIRA Integration GitHub Repository.

by Ralph Van Der Horst

arrow right
back to blog

share this article

Relevant articles

Setup oauth2 client for Salesforce dev env for API testing using curl postman and Katalon

Setup oauth2 client for Salesforce dev env for API testing using curl postman and Katalon

Setup oauth2 client for Salesforce dev env for API testing using curl postman and Katalon

Setup oauth2 client for Salesforce dev env for API testing using curl postman and Katalon

ISTQB Advanced level

ISTQB Advanced level