temyers / cucumber-jvm-parallel-plugin

Maven plugin to help running Cucumber features in parallel
Apache License 2.0
129 stars 121 forks source link

ERROR Running from an Executable JAR: Features directory does not exist #179

Closed osuser2018 closed 5 years ago

osuser2018 commented 6 years ago

I receive this error when trying to run my tests from an executable JAR (created by the maven-assembly-plugin). The error description looks like this:

[ERROR] Failed to execute goal com.github.temyers:cucumber-jvm-parallel-plugin:5.0.0:generateRunners (generateRunners) on project webui-auto-test: Features directory does not exist

When I look inside the JAR file, I see a "features" folder at the top level in the JAR. Inside of this features folder are all the sub-folders I have in the Eclipse project. There is also a "test/java" folder structure and I am surprised that the resources/features folder did not build inside of here.

So I get the impression that the plugin expects the features in one place, but when the JAR is assembled, the features are placed elsewhere.

When I run these tests in Eclipse, no errors...everything runs smoothly. Could this be an issue related to the build path? Or, is the plugin constructed to limit the featuresDirectory in some way?

Pertinent data about this issue...

My general project folder structure is: src --->test ------->java ----------->stepDefinitions ------->resources ------------>features -----------------> {numerous feature sub folders}

--->main ------>java -----------> {numerous sub folders and java classes, including path to the MAIN entry class to the JAR} ------->resources -----------> {numerous supporting files}


Here is a look at the plugin configuration in my pom.xml:

<plugin>
    <groupId>com.github.temyers</groupId>
    <artifactId>cucumber-jvm-parallel-plugin</artifactId>
    <version>5.0.0</version>
    <executions>
        <execution>
            <?m2e execute onConfiguration?>
            <id>generateRunners</id>
            <phase>generate-test-resources</phase>
            <goals>
                <goal>generateRunners</goal>
            </goals>
            <configuration>
                <glue>
                    <package>test.java.stepDefinitions</package>
                </glue>
                <outputDirectory>${project.build.directory}\</outputDirectory> <!-- /test/java/autoGeneratedRunner --> <!-- runner classes will auto-generate here -->
                <packageName>autoGeneratedRunners</packageName>  <!-- Will create a package folder for the runners -->
                <featuresDirectory>src/test/resources/features/</featuresDirectory><!--Cucumber feature file location-->
                <cucumberOutputDir>target/reports/cucumber-parallel</cucumberOutputDir><!--Cucumber default reporting path-->
                <plugins>
                 <plugin>
                    <!--The available options are junit, testng, html, pretty, json, usage and rerun -->
                <name>json</name>
                <extension>json</extension>
                <!--Optional output directory. Overrides cucumberOutputDirectory. Usefull when different plugins create files with the same extension-->
                    <outputDirectory>${project.build.directory}/reports/cucumber-parallel/json/</outputDirectory>
                 </plugin>
        </plugins>
        <strict>true</strict>
        <monochrome>true</monochrome>
                <tags>
            <tag>@ConsoleMessageAllTests,@MenuElementAllTests</tag> 
                </tags>                     
                <useTestNG>true</useTestNG>                     
                <!-- The naming scheme to use for the generated test classes.  One of ['simple', 'feature-title', 'pattern'] -->
                <namingScheme>pattern</namingScheme>
                <!-- The class naming pattern to use.  Only required/used if naming scheme is 'pattern'.-->
                <namingPattern>{f}_RUNNER</namingPattern>
                <!-- One of [SCENARIO, FEATURE]. SCENARIO generates one runner per scenario.  FEATURE generates a runner per feature. -->
                <parallelScheme>FEATURE</parallelScheme>
            </configuration>
        </execution>
    </executions>
</plugin>

My build path includes the following source folders: **1. project-name/src --Included: main/java, test/java, test/java/stepDefinitions, and main/java/com/os/{path to my static main method} --Excluded: None

  1. project-name/src/main/resources... I'll leave out the detail here as it seems unrelated
  2. project-name/src/test/resources --Included: features/ --Excluded: None**
osuser2018 commented 6 years ago

Some additional info: I am running maven programmatically (using maven-invoker-plugin) from the main class entry point for the Jar. In this code (see below), one must designate the location of the pom.xml file. Ideally, I would like to reference the pom.xml within the compiled executable JAR except the pom is not compiled into it. Once the JAR file is built (using maven-shade-plugin), I move it to another folder outside of the project folders to test the JAR. In this folder, I place the JAR and the pom.xml file. I think this is where the problem is. When I run the JAR, things progress until the cucumber-jvm-parallel-plugin tries to access the featuresDirectory which does not exist in this new folder location. The features do, however, exist in the executable JAR but I am not sure how to set the featuresDirectory in the pom to make sure the plugin look internally into the JAR for the features.

As a test, I simply copied the "src" folder and all of its sub-folders to this new folder where the compiled jar now sits. When running now, the compiled jar runs...

So, why isnt the pom added in the compiled jar by the maven-shade-plugin? If it were, could it be accessed by the code listed below?

```

public static void main(String[] args) throws FileNotFoundException {
System.out.println(""); System.out.println("----- Test Mode : PARALLEL -----"); System.out.println("");

    InvocationRequest request = new DefaultInvocationRequest();
    InputStream stream = new ByteArrayInputStream(new byte[] {});

    request.setInputStream(stream);
    request.setPomFile( new File("pom.xml") );
    request.setShowErrors(true);

    List<String> goalList = Arrays.asList("clean","verify");
    request.setGoals( goalList );

    Invoker invoker = new DefaultInvoker();
    invoker.setMavenHome(new File(System.getenv("MAVEN_HOME")));

    InvocationResult result = null;
    try {
        result = invoker.execute( request );
    } catch (MavenInvocationException e) {
        e.printStackTrace();
    }

    if ( result.getExitCode() != 0 )
    {
        throw new IllegalStateException( "Build failed." );
    }                   
}