Extending Iridium With Custom Step Definitions
Iridium makes it easy for developers to build in their own custom step definitions, removing the need to write custom code gluing Cucumber and WebDriver together.
Join the DZone community and get the full member experience.
Join For FreeCucumber, which is the library that Iridium is built on, has been designed to allow developers to easily have their own code run in response to a step inside a feature script. Once you have all the boilerplate code written to initialize Cucumber, having it run your own code is as simple as creating a POJO with methods that have the annotations @Then, @When, @But, @Given or @And.
But getting all the boilerplate code written is not quite as easy as it sounds, especially when you are integrating Cucumber with WebDriver in order to drive a web browser. In fact, the bulk of code in Iridium has been written to provide an environment where WebDriver and Cucumber can work together. Writing the code that is executed by a feature script is actually one of the easiest aspects of the Iridium code base.
Making Iridium Better With Custom Steps
There is always room for improvement, and that is exactly what people who use Iridium on a regular basis believe. They often want to add custom steps to the system in order to create something that is more beneficial than they ever deemed possible.
It is to your advantage to use Iridium on a regular basis to make sure you are constantly improving the quality of work that you push out to the world, and the best way to do that is to use Iridium in a customized way. It will allow you to finally get the full potential out of Iridium that you have been waiting for. To get that full potential, you just need to throw in some special customized code that you have designed to make it happen.
Fortunately, developers can take advantage of the work done in Iridium to create their own step definitions which can then be run by Iridium alongside (or completely replacing) the standard set of steps provided by Iridium.
To demonstrate this, we’ll create a simple extension with a simple step definition that logs a message.
To start with, you’ll also need to create a GPG key, which is used to sign the extension JAR files. The Building chapter of the Getting Started Guide has details on how to create a GPG key.
You’ll also need to sign up to the Sonatype Open Source Maven publishing programme. This is a service provided by Sonatype that allows open source developers to publish artifacts to the central Maven repositories, which is incredibly useful given that Maven is the de facto method for sharing Java artifacts.
Once you have created your GPG key and have a Sonatype account, those details go in the file ~/.gradle/gradle.properties.
signing.keyId=12345678
signing.password=password
signing.secretKeyRingFile=/home/username/.gnupg/secring.gpg
ossrhUsername=sonatype_user
ossrhPassword=sonatype_password
With that done, we can create the Java project. We’ll start with the Gradle build script in the build.gradle file.
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
maven {
url 'https://oss.sonatype.org/content/repositories/releases'
}
}
dependencies {
classpath 'com.matthewcasperson:build:0.+'
}
}
apply plugin: 'com.matthewcasperson.build.iridiumextension'
This build file takes advantage of a custom Gradle plugin that handles everything you need to create an Iridium extension. You can find the source code of this plugin here. By using the Gradle plugin, things like maven repos, maven publishing, dependencies, and code style checking are implemented for you.
One of the requirements enforced by the plugin is the need to specify the number of properties of the extension. This is done in the gradle.properties file.
# Update these properties to reflect the details of the extension
Group=com.matthewcasperson
ArchivesBaseName=example-extension
Version=0.0.1-SNAPSHOT
MavenName=Iridium Example Exntension
MavenDescription=A demo of an extension that can be used with the Iridium testing application
MavenURL=https://github.com/mcasperson/iridium-example-extension
MavenSCMConnection=scm:git:https://github.com/mcasperson/iridium-example-extension
MavenSCMURL=https://github.com/mcasperson/iridium-example-extension
MavenLicenseName=MIT
MavenLicenseURL=https://opensource.org/licenses/MIT
MavenDeveloperID=mcasperson
MavenDeveloperName=Matthew Casperson
MavenDeveloperEMail=matthewcasperson@gmail.com
To make it easy for others to build your project, create a Gradle wrapper with the command
gradle wrapper --gradle-version 2.12
This saves some scripts in your project that are intended to be checked into source control. Running these scripts will download the appropriate version of Gradle onto the user’s local PC if it doesn’t already exist, and this means that other developers don’t need Gradle installed to build your project.
Now we create the class that will hold our step definition. The class needs to be in a package under au.com.agic.apptestingext.steps. This is because Iridium has been configured to scan all classes under au.com.agic.apptestingext.steps for step definitions.
package au.com.agic.apptestingext.steps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cucumber.api.java.en.When;
/**
* Cucumber steps exist in a POJO
*/
public class Example {
private static final Logger LOGGER = LoggerFactory.getLogger(Example.class);
/**
* Annotate a public method with @And, @But, @When, @Given or @Then, and cucumber
* will recognise the method as a Gherkin step
*
* @param message The message to be written to the log
*/
@When("I write \"(.*?)\" as a log message")
public void writeExampleLogMessage(final String message) {
LOGGER.info(message);
}
}
The @When annotation takes a regular expression that is matched to any steps in a feature script. The groups in the regular expression are passed into the method as parameters. In this case, we have one regular expression group, which takes the message to be logged, and this is passed to the message parameter.
Inside the method, we use these parameters however we like. Our example takes the message and logs it to the console.
Once you are happy with the code, publish it to Sonatype with the command:
./gradlew build uploadArchive
This uploads the artifact to the Sonatype staging repo. Note that while it is in the staging repo, the artifact is not available to other developers unless they specifically add the staging repo to their build scripts. Our Gradle plugin does add the staging repo though, so anyone using this plugin will have access to your artifact. Publishing to the central Maven repo (which makes the artifact globally available) is covered by the Sonatype docs.
With your Iridium extension in the staging Maven repo, we now need to incorporate it into a build of Iridium. To do this, clone the Iridium repo, and the following line to the build.gradle file:
dependencies {
// Existing dependencies go here...
compile group: 'com.matthewcasperson', name: 'example-extension', version: '0.0.1-SNAPSHOT'
}
Doing so adds your new extension JAR as a dependency of the Iridium project. You can now build a self contained uberjar with the command:
./gradlew clean shadowJar --refresh-dependencies
The resulting JAR file in the build/libs directory now contains your JAR file with the step definitions. You can reference these step definitions from a feature script like any of the step definitions included with Iridium.
Feature: Local Test
Scenario: Local Scenario
And I write "Hello World" as a log message
The source code to this example extension can be found here.
Published at DZone with permission of Matthew Casperson, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments