Running Cucumber tests directly from executable jar

Arpan Buch picture Arpan Buch · Mar 22, 2016 · Viewed 22k times · Source

I have a project with cucumber and maven also I am using the JUnit.

I am able to run and build my project successfully from Eclipse.

Now I want to run the test from command line in another system which does(should) not have eclipse or cucumber installed. I have an idea that we can create a JAR from jar we can run the tests by java cli commands.

Below are the combinations I am trying to run my tests from , also I am pasting the pom.xml and RunCukesTest.java file..

enter image description here

pom.xml

<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>pmc</groupId>
    <artifactId>se</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>storeEnabler</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.2.0</version>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-testng</artifactId>
            <version>1.2.0</version>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.52.0</version>
        </dependency>

        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>io.appium</groupId>
            <artifactId>java-client</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.11-beta3</version>
        </dependency>

        <dependency>
            <groupId>xml-apis</groupId>
            <artifactId>xml-apis</artifactId>
            <version>2.0.2</version>
        </dependency>

        <dependency>
            <groupId>xerces</groupId>
            <artifactId>xercesImpl</artifactId>
            <version>2.8.0</version>
        </dependency>
    </dependencies>

    <build>
        <testResources>
            <testResource>
                <directory>${project.basedir}/src/test/java</directory>
            </testResource>
            <testResource>
                <directory>${project.basedir}/src/test/resource</directory>
            </testResource>
        </testResources>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <fork>true</fork>
                        <executable>C:\Program Files\Java\jdk1.8.0_60\bin\javac.exe</executable>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.18</version>
                    <dependencies>
                        <dependency>
                            <groupId>org.apache.maven.surefire</groupId>
                            <artifactId>surefire-junit47</artifactId>
                            <version>2.18</version>
                        </dependency>
                    </dependencies>
                </plugin>
                    <plugin>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <configuration>
                        <archive>
                            <manifest>
                            <addClasspath>true</addClasspath>
                                <mainClass>cucumber.api.cli.Main</mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

RunCukesTest.java

package se.stepDefinations;


import org.junit.runner.RunWith;

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resource/features/Printing.feature:117", plugin = { "pretty",
        "html:target/cucumber-html-report" }, glue = { "se.stepDefinations" }, tags = {})
public class RunCukesTest {

    public static void main(String[] args) throws Exception {


    }
}
  • I have added JUNIT Jar in Class path.

I am generating jars in 2 ways,

1) Exporting JAR using - > Project ->Export -> JAR File Selecting MAIN Class in the last step as : RunCukesTest as I have defined main method here for the entry point(do we require this main method in this class???)

After the export , I am running below command ,

1.1 java -jar xyz.jar I get error : NoClassDef found : org/junit/runner/JUnitCore

So I ran it this way :

1.2 java -cp xyz.jar;junit-4.12.jar org.junit.runner.JUnitCore It said,

JUnit version 4.12
Time:0.001
OK(0 tests) 

It still didnt work , So I appended the RunCukesTest file namespace at the last,
1.3 java -cp xyz.jar;junit-4.12.jar org.junit.runner.JUnitCore se.stepDefinations.RunCukesTest
It gave me error :Type cucumber.api.junit.Cucumber not present

2) So I gave up on the option for Export of jar and I am trying now to use the JAR from the maven Build. I selected the POM to run with Maven Build and it created 2 jars in the target folder ,

1 with name xyz-0.0.1-SNAPSHOT with 16kb another with 2nd with
xyz-0.0.1-SNAPSHOT-jar-with-dependencies with 33mb

1) I ran the bigger file with dependencies using

java -jar xyz-0.0.1-SNAPSHOT-jar-with-dependencies.jar

It gave me message :

Got no path to feature directory

2) So I tried appending the namespace to RunCukesTest file,

java -jar xyz-0.0.1-SNAPSHOT-jar-with-dependencies.jar se.stepDefinations.RunCukesTest

I received an error : not a file or directory found

, as of course as the error says , it is trying to find a feature inside the target folder.

Again , I want to run the JAR independent of any such project file dependencies in any other computer like an executable.

Any help would be appreciated. Thanks.

Answer

Thomas Sundberg picture Thomas Sundberg · Mar 23, 2016

I would divide the problem you are thinking of in two parts.

  • Create an executable jar
  • Run Cucumber from your own main method

Creating an executable jar using Maven can be done in different ways. One way of doing it is described here: http://www.thinkcode.se/blog/2011/03/05/create-an-executable-jar-from-maven

It is a small example that only focuses on executing something from a command line like this:

java -jar executable-example.jar

The example contains all dependencies. They are all bundled in the same jar. No need for any additional jars.

Next step would be to execute Cucumber from a main method. My approach would be to write a main that executes the Cucumber main method used for the command line version of Cucumber. The main method used to run cucumber from a command line lives in the cucumber-java library. You will find it at cucumber.api.cli.Main

Running a main method from another main method is done like this:

public static void main(String[] args) throws Throwable {
    String[] arguments = {"foo", "bar"};
    cucumber.api.cli.Main.main(arguments);
}

where arguments are the command line arguments you always want to execute Cucumber with.

Given these two steps, you should be able to execute Cucumber from your own executable jar wherever you are able to execute a jar at all.

Notice that you are mixing library version for Cucumber in your pom. I would use the latest version of all libraries. Compare cucumber-java, cucumber-testng and cucumber-junit. The latest Cucumber version is 1.2.4. I would use it for all of them.

More information about running Cucumber from a command line can be found here: https://cucumber.io/docs/cucumber/api/#from-the-command-line