Using Step Functions to Orchestrate Cucumber Tests in AWS CodePipeline

AWS CodePipeline is a continuous integration and continuous delivery (CI/CD) service for fast and reliable application and infrastructure updates. Combining AWS Step Functions with AWS CodePipeline can provide an elegant solution to orchestrate Cucumber tests for automated testing. This post will delve into how to integrate AWS Step Functions into your CodePipeline to run Cucumber tests, using Java for step definitions.

What Are AWS Step Functions?

AWS Step Functions is a serverless orchestration service that allows you to coordinate multiple AWS services into serverless workflows. With Step Functions, you can design and run workflows that stitch together services such as AWS Lambda, AWS Batch, and more. These workflows are represented as state machines, where each state can perform a task, make a choice, or wait for a period of time.

What is AWS CodePipeline?

AWS CodePipeline is a continuous integration and continuous delivery service that automates the build, test, and deploy phases of your release process every time there is a code change. CodePipeline integrates with other AWS services such as CodeCommit, CodeBuild, CodeDeploy, and now, Step Functions, to orchestrate end-to-end release processes.

What is Cucumber?

Cucumber is a testing tool that supports Behavior Driven Development (BDD). It allows you to write tests in plain language (Gherkin) that can be understood by business stakeholders and developers alike. These tests are then mapped to step definitions written in programming languages like Java, which execute the described actions.

Prerequisites

Before we start, ensure you have the following:

  1. An AWS account with necessary permissions to create and manage Step Functions, CodePipeline, Lambda, and other related services.
  2. Basic knowledge of Java and Cucumber.
  3. AWS CLI and SDK installed and configured.

Step-by-Step Guide

Step 1: Define Your Cucumber Tests

First, let’s create a simple Cucumber test. Suppose you are testing a login feature. Create a feature file login.feature:

Feature: Login

  Scenario: Successful login
    Given the user is on the login page
    When the user enters valid credentials
    Then the user should be redirected to the homepage

Now, implement the step definitions in Java:

package com.example.steps;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import static org.junit.Assert.*;

public class LoginSteps {

    @Given("the user is on the login page")
    public void theUserIsOnTheLoginPage() {
        // Code to navigate to the login page
        System.out.println("User is on the login page");
    }

    @When("the user enters valid credentials")
    public void theUserEntersValidCredentials() {
        // Code to enter valid credentials
        System.out.println("User enters valid credentials");
    }

    @Then("the user should be redirected to the homepage")
    public void theUserShouldBeRedirectedToTheHomepage() {
        // Code to verify redirection to the homepage
        System.out.println("User is redirected to the homepage");
    }
}

Step 2: Create an AWS Lambda Function to Run Cucumber Tests

Next, create a Lambda function that will run your Cucumber tests. Package your Java project into a JAR file and upload it to AWS Lambda. Here’s a sample Lambda handler:

package com.example.lambda;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import io.cucumber.core.cli.Main;

public class CucumberTestRunner implements RequestHandler<Object, String> {

    @Override
    public String handleRequest(Object input, Context context) {
        String[] cucumberOptions = new String[]{"--glue", "com.example.steps", "classpath:features"};
        Main.run(cucumberOptions, Thread.currentThread().getContextClassLoader());
        return "Cucumber tests executed";
    }
}

Ensure your build.gradle or pom.xml includes necessary dependencies:

dependencies {
    implementation 'io.cucumber:cucumber-java:7.0.0'
    implementation 'io.cucumber:cucumber-core:7.0.0'
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.1'
}

Step 3: Define the Step Functions Workflow

Create a state machine definition to orchestrate your Cucumber tests. Here’s a sample Step Functions state machine definition (in JSON):

{
  "Comment": "A State Machine to run Cucumber tests",
  "StartAt": "RunCucumberTests",
  "States": {
    "RunCucumberTests": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:YOUR_LAMBDA_FUNCTION_NAME",
      "End": true
    }
  }
}

Step 4: Integrate Step Functions with CodePipeline

Create a CodePipeline pipeline and integrate the Step Functions state machine. Here’s an example of how your pipeline definition might look in CloudFormation:

Resources:
  MyPipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      RoleArn: arn:aws:iam::ACCOUNT_ID:role/CodePipelineRole
      Stages:
        - Name: Source
          Actions:
            - Name: Source
              ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: S3
                Version: 1
              Configuration:
                S3Bucket: your-source-bucket
                S3ObjectKey: your-source-key.zip
              OutputArtifacts:
                - Name: SourceOutput
        - Name: Build
          Actions:
            - Name: Build
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: 1
              InputArtifacts:
                - Name: SourceOutput
              OutputArtifacts:
                - Name: BuildOutput
              Configuration:
                ProjectName: your-codebuild-project
        - Name: Test
          Actions:
            - Name: RunCucumberTests
              ActionTypeId:
                Category: Invoke
                Owner: AWS
                Provider: StepFunctions
                Version: 1
              InputArtifacts:
                - Name: BuildOutput
              Configuration:
                StateMachineArn: arn:aws:states:REGION:ACCOUNT_ID:stateMachine:YOUR_STATE_MACHINE_NAME

Ensure that the CodePipeline has appropriate permissions to invoke Step Functions and that the Step Functions state machine can invoke the Lambda function.

Conclusion

Using AWS Step Functions to orchestrate Cucumber tests in AWS CodePipeline can provide a robust and scalable solution for automated testing. This approach leverages the serverless capabilities of AWS, reducing the operational burden and allowing you to focus on writing tests and improving software quality. By integrating these AWS services, you can create a seamless CI/CD pipeline that ensures your applications are tested and deployed with confidence.

If you found this article helpful and are interested in integrating Cucumber Automation Framework with AWS CodePipeline, I suggest you check out some of the other articles I’ve written for this series:

If you’re looking for a deeper dive into some of the concepts and specifics discussed in my article, feel free to reach out to me directly or as always you can checkout the official AWS CodePipeline Developer Documentation for more information.

Related Posts