Running Cucumber tests directly from executable jar

Solution 1:

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

Solution 2:

I'd like to extend the accepted answer to support Gradle, since this might be helpful for someone.

Given this is your project's structure

  • .root
    • src/
      • main/
        • java/ --> Put your .java files here
          • CukesRunner.java --> This is your main file
        • resources
          • features/ --> Put your .feature files here

The build.gradle file should look like something like this:


    apply plugin: 'java'
    
    sourceSets {
        main {
            java {
                srcDirs = ['src/main/java']
            }
            resources {
                srcDirs = ['src/main/resources']
            }
        }
    }
    
    dependencies {
         // Include your dependencies here
         compile '...'
     }
    
    configurations {
        cucumberRuntime {
            extendsFrom compile
        }
    }
    
    jar {
        from {
            // Package all dependencies in the .jar
            configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
        }
        manifest {
            // Indicate the main class for the .jar file
            attributes 'Main-Class': 'CukesRunner'
        }
    }

Then you can customize your CukesRunner.java just like the accepted answer suggested, but making sure to call for the features you compressed together with your jar file:

public class CukesRunner {
    
    public static void main(String[] args) throws Throwable {
        final String[] arguments = new String[]{
                "--glue", "<my Java classes packages reference>",
                "classpath:features" // This will look for the classpath inside the jar file
        };
        cucumber.api.cli.Main.main(arguments);
    }

}

Solution 3:

@SpringBootApplication
public class Application {

    public static void main(final String[] args) throws Throwable {
        // SpringApplication.run(TestApplication.class, args);
        JUnitCore.main(CucumberTest.class.getCanonicalName());
    }

}