First look at Eclipse Vert.x

Eclipse Vert.x is a lightweight framework for developing web applications, microservices and more.

I’ve created a project using IntelliJ named VertxTest based upon a Maven project to try out the routing functionality in Vert.x.

Dependencies – the pom

Our pom.xml looks like this

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>VertxTest</groupId>
    <artifactId>VertxTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <vertx.version>3.5.0</vertx.version>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>io.vertx.core.Launcher</Main-Class>
                                        <Main-Verticle>com.putridparrot.MainVerticle</Main-Verticle>
                                    </manifestEntries>
                                </transformer>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/services/io.vertx.core.spi.VerticleFactory</resource>
                                </transformer>
                            </transformers>
                            <artifactSet>
                            </artifactSet>
                            <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.5.0</version>
                <configuration>
                    <mainClass>io.vertx.core.Launcher</mainClass>
                    <arguments>
                        <argument>run</argument>
                        <argument>com.putridparrot.MainVerticle</argument>
                    </arguments>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-unit</artifactId>
            <version>${vertx.version}</version>
        </dependency>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web</artifactId>
            <version>${vertx.version}</version>
        </dependency>
    </dependencies>
</project>

The Verticle

As you can see from this my class MainVerticle (which extends AbstractVerticle) is created in the package com.putridparrot and the code looks like this

package com.putridparrot;

import io.vertx.core.AbstractVerticle;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;

public class MainVerticle extends AbstractVerticle {
    @Override
    public void start() {

        Router router = Router.router(vertx);

        router.route("/hello").handler(ctx -> {
            ctx.response()
                .putHeader("content-type", "text/plain")
                .end("Hello " + ctx.queryParam("name"));
        });

        vertx.createHttpServer()
            .requestHandler(router::accept)
            .listen(8080);

        System.out.println("HTTP server started on port 8080");
    }
}

Note: queryParam actually returns a List so in this example we would probably want to actually check the result and then get items from the list.

We extend AbstractVerticle overriding the start method to handle the setting up of our routes etc.

Building and Running

We execute mvn clean install and then mvn package to generate the executable jar. Finally we can run this using java -jar target/VertxTest-1.0-SNAPSHOT-fat.jar or similar in a configuration in an IDE (for example a JAR Application configuration within Intelli J just requires the path to the JAR listed above).

Testing and more

Now we should be able to run the following from your preferred web browser or Intelli J’s REST client (or similar in another IDE).

http://localhost:8080/hello?name=Mark

We can easily add further routes and/or handle GET or POST HTTP methods. For example here’s the addition of an error route using the get method

router.get("/error")
   .handler(this::handleGetError);

and

private void handleGetError(RoutingContext ctx) {
   ctx.response()
      .setStatusCode(500)
      .end();
}

Now browsing to

http://localhost:8080/error

will display a 500 error.

Static pages

We can also add static pages by declaring a route such as

 router.route("/pages/*")
   .handler((StaticHandler.create("pages")));

where the pages directory is located off the root off of the project folder (in this example). Simply place your HTML pages in this folder and you can access them using the following URL

http://localhost:8080/pages/index.html

Routing based upon mime type

Along with routine based upon the specific query/resource requested we can also route based upon the Content-Type within a request. For example if using HTTP POST with Content-Type application/json we would want to return JSON, likewise if Content-Type is application/xml we’d expect XML return (and so on).

To route based upon the mime type we simply write the following

router.route()
   .consumes("*/json")
   .handler(ctx -> {
      System.out.println("JSON request");
});

router.route()
   .consumes("*/xml")
   .handler(ctx -> {
      System.out.println("XML request");
});

Obviously in the examples above we’re simply routing off of the root “/” URL. Supply a path within the route method, as per previous example for other routing scenarios.

Running our Vertx application

We’ve seen we can create and run the JAR, but we can also create a Vertx application by creating a main method that looks something like this

public static void main(String[] args) {
   Vertx vertx = Vertx.vertx();

   vertx.deployVerticle(new MainVerticle());
}

We use deployVerticle along with our Verticle and Vertx does the rest.

Creating an ansible dockerfile

I was trying to run the ansible docker image on Docker hub, but it kept failing, so I went through the steps listed in http://docs.ansible.com/ansible/latest/intro_installation.html inside of an Ubunto docker image

  • apt-get update
  • apt-get install software-properties-common
  • apt-add-repository ppa:ansible/ansible
  • apt-get update
  • apt-get install ansible

Then running ansible –version demonstrated everything was working.

I decided to use the same commands to create a Dockerfile and hence create my own image of ansible.

  • Create an ansible folder
  • Create the file Dockerfile in the ansible folder

Please note, this is not a complete implementation of a Docker image of ansible so much as a starting point for experimenting with ansible.

Now we’ll create a fairly simple image based on ubuntu and install all the libraries etc. as above. So the Dockerfile should have the following contents

FROM ubuntu:latest

RUN apt-get -y update
RUN apt-get -y install software-properties-common
RUN apt-add-repository ppa:ansible/ansible
RUN apt-get -y update
RUN apt-get -y install ansible

From the ansible folder run sudo docker build -t ansible ., if all goes well you’ll have an image name ansible created. Just run sudo docker images to see it listed.

Now run sudo docker run -it ansible to run the image in interactive mode and then within the container run ansible –version to see if everything worked.

Now we’re up and running there’s obviously more to do to really use ansible and hopefully I’ll cover some of those topics in subsequent posts on ansible.

Sorting a range on specific column of data using VBA in Excel

In my previous post I imported a CSV file into my spreadsheet and displayed the rows after my headings row. I now want to sort the rows by a column of data, but I do not want the heading to be part of the sort, so I basically want to sort the rows based upon the column starting at the row below the column headings – I hope that makes sense.

Anyway, we’re going to need to find all the rows and columns that make our range of data and then select a slice of the data which are our value items to sort. Here’s the code

rows = ws.Cells(Rows.Count, "A").End(xlUp).Row
columns = ws.Cells(3, Columns.Count).End(xlToLeft).Column
    
Set dataRange = ws.Range(Cells(3, 1), Cells(rows, columns))
Set sortColumn = ws.Range(Cells(3, 5), Cells(rows, 5))
dataRange.Sort key1:=sortColumn, order1:=xlDescending

In this example we set rows to be the row count and columns to be the number of columns starting at row 3 (where our data is imported to). Next we turn these values into a range object (mine’s named dataRange) again using row 3 as our data’s starting point. Next we create a sortColumn range to be the actual column we want to use as our sort key, in this case I’m using column 5 data. Finally we sort the first data range using the second and mine sort is descending in this example.

Loading an CSV file into a workseet in Excel

Let’s assume we have an Excel worksheet with some nicely formatted headers and just above the row containing the headers we’ve placed a button which will we use to load a csv file into the rows below header row (without losing our formatting etc.)

Go to the Developer tab in Excel and select Visual Basic then create a subroutine like this

Sub LoadFile()
Dim fileName As String
   
   fileName = "c:\myfile.csv"

   Set ws = ActiveWorkbook.Sheets("Import")

   ws.Rows("3:" & Rows.Count).ClearContents
    
   With ws.QueryTables.Add(Connection:="TEXT;" & fileName, Destination:=ws.Range("A3"))
        .TextFileParseType = xlDelimited
        .TextFileCommaDelimiter = True
        .AdjustColumnWidth = False
        .Refresh
    End With
    
End Sub

I’ve simplified the code to have an explicit filename, instead of getting the filename via a folder selection dialog box or from a cell on the spreadsheet.

Simply get the active worksheet (mine’s named Import) and from this we’ll clear all row’s below our heading row (my rows start as row 3).

Next we use the QueryTables object and add the “Connection” supplying the filename that is to be imported. The destination is the start column/row where we want to place our data.

AdjustColumnWidth = False is useful to stop the import resizing your columns, the Refresh procedure will cause the spreadsheet to redraw itself.

Now this will load the CSV into the area below the column headings and not resize the columns to match the data size (hence not ruin existing formatting).

cxf-codegen-plugin not generating proxies everytime

In case this helps others out…

I am working on a Java project at the moment using Maven to build the code and run tests etc. I’m also using the cxf-codegen-plugin plugin (as below) to generate some proxies for a soap/wsdl file I have.

<plugin>
   <groupId>org.apache.cxf</groupId>
   <artifactId>cxf-codegen-plugin</artifactId>
   <version>3.2.2</version>
   <executions>
      <execution>
         <id>generate-sources</id>
         <phase>generate-sources</phase>
         <configuration>
         <wsdlOptions>
            <wsdlOption>
               <wsdl>${project.basedir}/src/main/resources/wsdl/Svc.wsdl</wsdl>
               <wsdlLocation>classpath:wsdl/Svc.wsdl</wsdlLocation>
               <extraargs>
                  <extraarg>-verbose</extraarg>
                  <extraarg>-client</extraarg>
                  <extraarg>-p</extraarg>
                  <extraarg>com.putridparrot.soap</extraarg>
               </extraargs>
            </wsdlOption>
         </wsdlOptions>
         </configuration>
         <goals>
            <goal>wsdl2java</goal>
         </goals>
      </execution>
   </executions>
</plugin>

I found that when I tried to either use mvn generate-sources mvn install the generated source folder was deleted and recreated, however the proxies folder had no proxy code/files (i.e. the files were deleted and not regenerated).

If I ran mvn clean install the proxy code would re-appear, but subsequent calls to generate-source of install would again delete the proxy code/files.

To cut a long story short it appeared that another plugin was clearing out the generated-sources folder but the cxf-codegen-plugin plugin would not regenerate it’s proxy code/files because of another file which the plugin created in the cxf-codegen-plugin-markers folder.

Within this folder is a file with a UUID style name. This was being plugin used by the plugin to check whether it needed to regenerate it’s proxy code/files (it doesn’t check if the files exist or simply regenerate them each time it’s run).

You can recreate the problem easily by running mvn generate-sources to create the proxies, then delete the generated-sources folder and run mvn generate-sources again. No proxy files are created. Now delete the marker file and the proxies will get regenerated.

Deleting this folder (or just the file within it) will fix the problem.

To stop this happening again you can either ensure the folder or file are deleted when the generate-sources folder is deleted or even simpler just write your proxies to another folder, so this would now get deleted by the other plugins.

i.e.

<configuration>
   <sourceRoot>${project.build.directory}/cxf</sourceRoot>
   <!-- other config -->
</configuration>

Running a maven plugin

Occasionally you might want to run a maven plugin without building/installing etc. at the same time – for example I am using wsdl2java to generate proxies for webservice and every now and then I want to just regenerate those proxies.

We can simply run

mvn antrun:run@your_execution_id

Embedding files and/or templates within templates using Velcocity

We can embed a file or other templates within Velocity templates – this is obviously useful for reusing snippets of code/text or whatever in more than file. We still need to create the context mappings for all the template file that form out overall template – in other words we supply the mappings the container template and all of the embedded templates.

To embed a template we simply use the #include or #parse directives. #include is used to pull in a template or file without transforming it using the template engine, i.e. any variables etc. will not be transformed or rendered by Velocity whereas #parse will transform any Velocity variables or code.

Taking the template (template.txt.vm) from my previous post, which looked like this

Hello $name,

This is a $template_name template.

we might break this template into the following two templates

salutation.txt.vm

Hello $name,

and template.txt.vm becomes

#parse("templates/salutation.txt.vm")

This is a $template_name template.

This will result in the combined and transformed template.

Using the Velocity template engine

Velocity is a template engine written for Java. It allows us to take files (or strings) with embedded Velocity Template Language (VTL) code and transform the files (or strings) based upon supplied values.

Let’s create a simple template file (by default we use the extension .vm and a good convention is to append it to the original extension file type, so you know what type of file you’re transforming) then we’ll use Velocity to transform the file.

We’ll create a standard Maven layout project

  • From IntelliJ create a new project and select Maven
  • In the src/test folder add a new directory names resources
  • Mark the directory as test resources
  • Add a folder to resources named templates
  • Add the file template.txt.vm

My template.vm looks like this

Hello $name,

This is a $template_name template.

As you’ve probably guessed the $ prefix denotes a variable which we will supply to Velocity.

The first thing we need to do is create the Velocity engine and then set it up to allow us to load our files from the resources folder, here’s the code for this

VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty(
   "resource.loader", 
   "file");
velocityEngine.setProperty(
   "file.resource.loader.class", 
   "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
velocityEngine.setProperty(
   "file.resource.loader.path", 
   "src/test/resources");

Next up we create a VelocityContext which we use to supply our mappings to the variable names used within the template file. We do not include the $ when supplying the variable name. We simply supply key value pairs, where the key is a String which represents the variable name and the value is what we want to replace it with (this is an Object which can be more complex than just a String). For this example our value will just be a String, so we have the following

VelocityContext velocityContext = new VelocityContext();
velocityContext.put("name", "PutridParrot");
velocityContext.put("template_name", "MyPutridParrotTemplate");

Note: If we do not add a context mapping then the result will be the original $variable_name, unchanged.

Finally, we want to actually “merge” (as Velocity calls the process) our context against the template and at the same time we’re going to convert the resultant “merged” template into a string

StringWriter writer = new StringWriter();
Template template = velocityEngine.getTemplate("templates/template.txt.vm");
template.merge(velocityContext, writer);

// to prove it worked...
System.out.println(writer.toString());

Running the above code we will get the output (as you would expect)

Hello PutridParrot,

This is a MyPutridParrotTemplate template.

Taking things a little further

As mentioned previously the value stored within the context is an Object, so we can store an array of values if we want.

Let’s assume we have the following template file

Hello $name,

My templates

#foreach( $t in $template_name)
    * $t
#end

As you can see the VTL supports foreach loops, so if we change the code that assigns the template_name to the context to look like this

ArrayList<String> list = new ArrayList<>();
list.add("Putrid");
list.add("Parrot");

velocityContext.put("template_name", list);

Our output will now be

Hello PutridParrot,

My templates

    * Putrid
    * Parrot

Take a look at the VTL reference for more options.

And finally

Finally for this post, it’s not unusual to have a string that represents the template, for example, maybe we get our templates from a web service or just load from another file location into memory.

Here’s the full code for this

String templateString = "Hello $name,\n\nThis is a $template_name template.";

RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
StringReader reader = new StringReader(templateString);
SimpleNode node = runtimeServices.parse(reader, "Velocity Template");

VelocityContext velocityContext = new VelocityContext();
velocityContext.put("name", "PutridParrot");
velocityContext.put("template_name", "MyPutridParrotTemplate");

StringWriter writer = new StringWriter();
Template template = new Template();
template.setRuntimeServices(runtimeServices);
template.setData(node);
template.initDocument();

template.merge(velocityContext, writer);

// to prove it worked...
System.out.println(writer.toString());

The key differences are how we create the SimpleNode and then create the Template.

Duplicate step definitions in Gherkin & Cucumber (using IntelliJ)

Continuing from my last post Gherkin & Cucumber in Java (using IntelliJ).

Let’s assume you have a project set-up as per my previous post, delete any existing feature files and let’s create two very simple and very similar feature files

Feature: Calculator Add

  Scenario: Add two numbers
    Given Two input values, 1 and 2
    When I add the two values
    Then I expect the result 3
Feature: Calculator Subtract

  Scenario: Subtract two numbers
    Given Two input values, 1 and 2
    When I subtract the two values
    Then I expect the result -1

When we start creating our step definition files we might start with the Add feature and create something like AddStepdefs.java which includes the following code

package com.putridparrot;

import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class AddStepdefs {
    @Given("^Two input values, (-?\\d+) and (-?\\d+)$")
    public void twoInputValuesAnd(int a, int b) throws Throwable {
    }

    @When("^I add the two values$")
    public void iAddTheTwoValues() throws Throwable {
    }

    @Then("^I expect the result (-?\\d+)$")
    public void iExpectTheResult(int r) throws Throwable {
    }
}

Next we might start creating the step definitions file for the Subtract feature and notice, IntelliJ shows one step as already existing (i.e. it’s not got a highlight background colour). If you press the CTRL key and move the mouse over the step which appear to exist already (i.e. Two input values, 1 and 2) a hyperlink line will appear, click this and it will take you to the previously added step in the AddStepdefs file.

What’s happening here is that whilst we might define separate classes per feature (which may well seem a logical way to write our test code/step definitions), Cucumber is actually matching to methods based upon the RegEx within the annotations, i.e. Given Two input values, 1 and 2 maps to

@Given("^Two input values, (-?\\d+) and (-?\\d+)$")
public void twoInputValuesAnd(int a, int b) throws Throwable {
}

Cucumber doesn’t actually take notice of the Given/When/Then annotations for matching the method to the line of Gherkin code.

Let us assume that we simply copy the missing step into the SubtractStepdefs.java file, we now have duplicate step definitions according to Cucumber, which is ofcourse correct if we think that each step is in essence globally scoped by Cucumber.

Or to put it another way, Cucumber will search through all the packages within the “Glue” package(s) to locate matching RegEx’s. If it finds more than one matching RegEx we get a duplicate step error. Here’s the (truncated) error that Cucumber will display for us when we try to run all features.

Exception in thread "main" cucumber.runtime.DuplicateStepDefinitionException: Duplicate step definitions in com.putridparrot.SubtractStepdefs.twoInputValuesAnd(int,int)

Handling duplicate step definitions

So how do we resolve a situation where we want to run all features and we have duplicate steps?

The easiest solution is, ensure you never have duplicate steps unless you intended to reuse the same step definition code – the general idea is to think of the language used to define a step in Gherkin as a specific task and another step using the same text is really the same task (at least when associated with the same package).

Ofcourse we can have duplicate steps in different packages, we just need to ensure we run features against on that package using the Glue option, i.e. do not reference all packages but just point to the one’s specific to the features.

If we therefore have the code like this in AddStepdefs and not in SubtractStepdefs

public class AddStepdefs {
   private int value1;
   private int value2;

   @Given("^Two input values, (-?\\d+) and (-?\\d+)$")
   public void twoInputValuesAnd(int a, int b) throws Throwable {
      value1 = a;
      value2 = b;  
   }
   // other code removed
}

the we have created another problem. The instance variables, value1 and value2 or stored in AddStepdefs and hence we’d also have similar variables stored in SubtractStepdefs (for use with the subtract scenario) however, the twoInputValuesAnd will never change the instance variables in the SubtractStepdefs for obvious reasons…

So how do we share instance data across our step definition files?

As programmers we might see a Scenario as analogous to a class but you can see that to ensure we adhere to the DRY principle we’d actually be better off creating a single class with all step definitions across all scenarios. This ofcourse is also not ideal because once we start to rack up a large number of scenarios, our class will become large and unwieldy.

So what we really want to do is create an instance of some shared state and have Cucumber pass this to each step definition class.

This is where cucumber-picocontainer comes in. If we add the following to the pom.xml

<dependency>
   <groupId>info.cukes</groupId>
   <artifactId>cucumber-picocontainer</artifactId>
   <version>1.2.5</version>
   <scope>test</scope>
</dependency>

and can “context” like this

public class ScenarioContext {
    private int value1;
    private int value2;
    private int result;

    public int getValue1() {
        return value1;
    }

    public void setValue1(int value) {
        this.value1 = value;
    }

    public int getValue2() {
        return value2;
    }

    public void setValue2(int value) {
        this.value2 = value;
    }

    public int getResult() {
        return result;
    }

    public void setResult(int value) {
        this.result = value;
    }
}

We can now change our step definitions files to look like this, first the AddStepdefs file

public class AddStepdefs {

    private ScenarioContext context;

    public AddStepdefs(ScenarioContext context) {
        this.context = context;
    }

    @Given("^Two input values, (-?\\d+) and (-?\\d+)$")
    public void twoInputValuesAnd(int a, int b) throws Throwable {
        context.setValue1(a);
        context.setValue2(b);
    }

    @When("^I add the two values$")
    public void iAddTheTwoValues() throws Throwable {
        Calculator calculator = new Calculator();

        context.setResult(calculator.add(context.getValue1(), context.getValue2()));
    }

    @Then("^I expect the result (-?\\d+)$")
    public void iExpectTheResult(int r) throws Throwable {
        Assert.assertEquals(r, context.getResult());
    }
}

and the SubtractStepdefs without any duplicated steps could look like this

public class SubtractStepdefs {

    private ScenarioContext context;

    public SubtractStepdefs(ScenarioContext context) {
        this.context = context;
    }

    @When("^I subtract the two values$")
    public void iSubtracTheTwoValues() throws Throwable {
        Calculator calculator = new Calculator();

        context.setResult(calculator.subtract(context.getValue1(), context.getValue2()));
    }
}

When a feature file is run, Cucumber will get an instance of our ScenarioContext passed to each class by the picocontainer which will them be used by the class methods.

Gherkin & Cucumber in Java (using IntelliJ)

This post will be based around implementing features etc. using IntelliJ, so your experience with tooling may differ from those experiences outlined in this post.

If you’re coming from Specflow and C# to IntelliJ and Java

I’ve used Gherkin previously when using Specflow in Visual Studio and with C#. The concepts, syntax etc. are exactly the same, however be aware that the generated code isn’t just different in terms of the language used (i.e. C# and Java for example) but also in the RegEx generated. As an example if your Gherkin has numbers then Specflow generated code allows for negatives, whereas the code generated within the IntelliJ/Java systems is a little stricter with it’s RegEx and negatives need to be added to the RegEx.

Creating our demo project

  • File | New Project
  • Select Maven project type
  • Enter the GroupId and ArtifactId

Now open the pom.xml and add the following

<dependencies>
   <dependency>
      <groupId>info.cukes</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>1.2.5</version>
      <scope>test</scope>
   </dependency>
   <dependency>
      <groupId>info.cukes</groupId>
      <artifactId>cucumber-jvm</artifactId>
      <version>1.2.5</version>
      <type>pom</type>
   </dependency>
   <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
   </dependency>
</dependencies>

Creating our code

Let’s create a simple little class to run our tests against. Within src/java add a new class, mine’s named com.putridparrot.Calculator. Here’s the code that’s stored in src/main/java/com.putridparrot package

package com.putridparrot;

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

In src/test create a folder named resources and right mouse click on this folder and select Mark Directory As | Test Resources Root.

Note: the resources folder is not a requirement, more a convention.

Next, add a folder named features and within this folder create a new file named add.feature, this is a really simple example feature

Note: this post is not about writing good feature’s so this example is extremely basic.

Feature: Calculator
  
  Scenario Outline: add two numbers
    Given Two input values, <first> and <second>
    When I add the two values
    Then I expect the result <result>

  Examples:
    | first | second | result |
    | 1     | 12     | 13     |
    | -1    | 6      | 5      |

Select the end of each the Given, When and Then line and press alt+enter for each and select create steps definition. Name the file AddStepDef (mine’s created in the src/test/java/com/putridparrot folder/package) and set the file type to Java when you create your first step definition, then subsequently add step definitions to this same file.

Note: At the time of writing, selecting create all step definitions, does not seem to work as expected and simply creates a single step, not yet sure why.

Here’s what my generated steps looked like

package com.putridparrot;

import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class AddStepDefs {
    @Given("^Two input values, <first> and <second>$")
    public void twoInputValuesFirstAndSecond() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        throw new PendingException();
    }

    @When("^I add the two values$")
    public void iAddTheTwoValues() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        throw new PendingException();
    }

    @Then("^I expect the result <result>$")
    public void iExpectTheResultResult() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        throw new PendingException();
    }
}

Sadly these require editing as the placeholders (the <> wrapped text) are not being passed as arguments into our methods. The simplest way to solve this is to change the placeholders to numbers (or the type we expect) delete the methods from the step definition file and then regenerate the step definitions. So here’s my “temporary” change to the feature to get valid steps generated.

Feature: Calculator

  Scenario Outline: add two numbers
    Given Two input values, 1 and 2
    When I add the two values
    Then I expect the result 3

    Examples:
      | first | second | result |
      | 1     | 12     | 13     |
      | -1    | 6      | 5      |

this gives us the following code

package com.putridparrot;

import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class AddStepDefs {


    @Given("^Two input values, (\\d+) and (\\d+)$")
    public void twoInputValuesAnd(int arg0, int arg1) throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        throw new PendingException();
    }

    @When("^I add the two values$")
    public void iAddTheTwoValues() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        throw new PendingException();
    }
    
    @Then("^I expect the result (\\d+)$")
    public void iExpectTheResult(int arg0) throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        throw new PendingException();
    }

}

Return the feature file back to the version with placeholders.

Before we write our actual test code, let’s run the feature tests. In IntelliJ we can right mouse click on an individual feature file or the folder with the features and select Run feature or Run all features.

As we only have one feature file at the moment, select it, right mouse click and select Run: Feature Calculator, you’ll probably be hit with output in the test window along the lines of

Undefined step: Given… etc.

We need to edit the configuration for the runner and supply the Glue (in my case I have the steps in the package com.putridparrot, so I enter that in the Glue: option). Now running the feature should result in another error

Undefined step: Given Two input values, -1 and 6

As you can see, there’s a problem with the generated code as it expects a method that handles a negative number and none exist, we need to amend our RegEx for all methods to include a possible – sign. Changed all (\\d+) to (-?\\d+) now running the feature will have fixed the error.

Writing our test code

We can now write fairly standard unit testing code into the step definition file (in this case I’m using JUnit), so here’s a simple example

package com.putridparrot;

import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.junit.Assert;

public class AddStepDefs {

    private Calculator calculator;
    private int value1;
    private int value2;
    private int result;

    @Before
    public void before() {
        calculator = new Calculator();
    }

    @Given("^Two input values, (-?\\d+) and (-?\\d+)$")
    public void twoInputValuesAnd(int arg0, int arg1) throws Throwable {
        value1 = arg0;
        value2 = arg1;
    }

    @When("^I add the two values$")
    public void iAddTheTwoValues() throws Throwable {
        result = calculator.add(value1, value2);
    }

    @Then("^I expect the result (-?\\d+)$")
    public void iExpectTheResult(int arg0) throws Throwable {
        Assert.assertEquals(arg0, result);
    }
}

Common mistakes

Glue, glue and more glue – make sure you set up the glue.