[CUCUMBER-JVM] Configuring File Locations

1,396 views
Skip to first unread message

Jeff Nyman

unread,
Jun 14, 2014, 7:31:30 AM6/14/14
to cu...@googlegroups.com
Hey all.

Maybe there's a good resource out there that I'm missing, but I'm curious how and to what extent Cucumber-JVM lets you place files in different locations.

For example, I'm playing around with a standard Maven directory structure. So I have an app package/path of:

    src/main/java/nostalgic/textadv/voxam
    src/test/java/nostalgic/textadv/voxam

I created the following to hold my feature file:

    src/test/resources/nostalgic/textadv/voxam

That certainly works fine. However, I found that I could put my feature files directly in the resources directory and all would work fine. I could also create a specs directory (outside of the /test directory) like this:

    src/specs

Putting my feature files in there worked fine, as long as I passed the features= parameter to CucumberOptions.

After experimenting, I can see that the test runner can go directly in "src/test/java" without having to be in the package. But what about the step definitions? For example, what if someone wanted to store step definitions in:

    src/test/steps

Right now, of course, that wouldn't work for my set up because the test runner would not find those step definitions, thus my feature files would always appear to have undefined steps. Is there a way to tell Cucumber-JVM to look in that location for step definitions, just as I was able to tell it to look somewhere else for feature files.

I realize a lot of this may be constrained by the fact that you have to use a structure and pathing that Maven and JUnit can work with. So I'm just trying to see what kind of freedom Cucumber-JVM gives in comparison to that of Cucumber Ruby so I can better understand how to document this for testers.

Any tips would be appreciated, including just pointing me to a resource that I might have missed.

- Jeff

Björn Rasmusson

unread,
Jun 14, 2014, 9:40:37 AM6/14/14
to cu...@googlegroups.com
skrev Jeff Nyman wrote:
Hey all.

Maybe there's a good resource out there that I'm missing, but I'm curious how and to what extent Cucumber-JVM lets you place files in different locations.

For example, I'm playing around with a standard Maven directory structure. So I have an app package/path of:

    src/main/java/nostalgic/textadv/voxam
    src/test/java/nostalgic/textadv/voxam

I created the following to hold my feature file:

    src/test/resources/nostalgic/textadv/voxam

That certainly works fine. However, I found that I could put my feature files directly in the resources directory and all would work fine. I could also create a specs directory (outside of the /test directory) like this:

    src/specs

Putting my feature files in there worked fine, as long as I passed the features= parameter to CucumberOptions.

After experimenting, I can see that the test runner can go directly in "src/test/java" without having to be in the package. But what about the step definitions? For example, what if someone wanted to store step definitions in:

    src/test/steps

Right now, of course, that wouldn't work for my set up because the test runner would not find those step definitions, thus my feature files would always appear to have undefined steps. Is there a way to tell Cucumber-JVM to look in that location for step definitions, just as I was able to tell it to look somewhere else for feature files.
Hi,

One way of putting is, that you can put the step definitions wherever you want as long you:
A: make sure that they are compiled
B: make sure that the compiled step definition classes are put on the classpath
C: tell Cucumber-JVM the package(s) on the classpath it should search for step definitions (those packages and their sub-packages will be searched)

A and B is not directly related to Cucumber-JVM but the build tool you use (like Maven). If you want to put your step definitions in src/test/steps you need to tell Maven to compile the classes there and put the resulting compiled classes on the classpath when running tests.

Regarding C, if not told anything explicitly Cucumber-JVM will search the package the runner class (and its sub-packages) for step definitions, this can be overridden using --glue on the command line of glue = {} in @CucumberOptions.

With Maven a tip is to use -Dcucmber.option="--help" to get Cucumber-JVM to print the command line help which summarizes its command line options, which generally also is available from @CucumberOptions (--help is an exception, it is not available from @CucumberOptions)
 
Best Regards
Björn

Jeff Nyman

unread,
Jun 14, 2014, 10:03:55 AM6/14/14
to cu...@googlegroups.com

On Saturday, June 14, 2014 8:40:37 AM UTC-5, Björn Rasmusson wrote:
lots of good stuff; snipped

Okay, thanks for that. I'm really new to Java. (Coming from the Ruby world and not exactly enjoying the transition.) So if you'll bear with me, let's say I want this structure:

    src/main/java
    src/test/java
    src/specs
    src/steps

My application code of course lives in src/main/java.
My application unit test code (and the Cucumber-JVM test runner) lives in src/test/java.

My feature files live in src/specs and I can get those to be read by doing this:

    @CucumberOptions(features="src/specs")

Now if I want my step definitions to live in src/steps, ideally it would be nice if I could do this:

    @CucumberOptions(features="src/specs", steps="src/steps")

I realize I can't, though. So I get what you're saying is that I have to make sure Maven and then Cucumber-JVM know what's in src/steps. But here's my challenge. Let's say my step definition file is ParserSteps.java. Because it tests the application code in src/main/java (specifically a file called Parser.java), my step definition file starts off with:

    package nostalgic.textadv.voxam;

    import cucumber.api.java.*;

    public class ParserSteps {
        private Parser parser;

        @Given("^the game parser$")
        public void the_game_parser() throws Throwable {
          parser = new Parser();
        }

So my step definition has to include the package of the application that it's testing. So it's not clear to me how I can make my step definitions part of a different package structure such that Maven could find them and compile them while still allowing those step definitions to find the relevant application code.

Does the above make sense in terms of where I'm having trouble figuring this out? I fear I'm making none of this very clear.

- Jeff

Björn Rasmusson

unread,
Jun 15, 2014, 1:39:07 PM6/15/14
to cu...@googlegroups.com
Jeff Nyman wrote:

On Saturday, June 14, 2014 8:40:37 AM UTC-5, Björn Rasmusson wrote:
lots of good stuff; snipped

Okay, thanks for that. I'm really new to Java. (Coming from the Ruby world and not exactly enjoying the transition.) So if you'll bear with me, let's say I want this structure:

    src/main/java
    src/test/java
    src/specs
    src/steps

My application code of course lives in src/main/java.
My application unit test code (and the Cucumber-JVM test runner) lives in src/test/java.

It does not make very much sense in placing the Cucumber-JVM test runner in a different place than the step definitions. They are both java code used in the execution of the features.
 

My feature files live in src/specs and I can get those to be read by doing this:

    @CucumberOptions(features="src/specs")

Yes, Cucumber-JVM can read features from a directory path relative to the current directory, it can also read them from the classpath, which is what really happens when placing them under src/test/resources.
 

Now if I want my step definitions to live in src/steps, ideally it would be nice if I could do this:

You mean the source code for the step definitions, when compiled they are places somewhere else (generally speaking), the test code from src/test/java end up under target/test-classes by default (when using Maven).
 

    @CucumberOptions(features="src/specs", steps="src/steps")

Since step definitions in the end are compiled java code, the thing to tell Cucumber-JVM is what package they are in. If a step definition (source code) file starts with:

package nostalgic.textadv.voxam;

then it would be

@CucumberOptions(glue = {"nostalgic.textadv.voxam"})


and this is only necessary to say explicitly when the Cucumber-JVM test runner starts for with something different from

package nostalgic.textadv.voxam;


I saying is that I have to make sure Maven and then Cucumber-JVM know what's in src/steps. But here's my challenge. Let's say my step definition file is ParserSteps.java. Because it tests the application code in src/main/java (specifically a file called Parser.java), my step definition file starts off with:

    package nostalgic.textadv.voxam;

This says that this class is placed in a source code directory .../nostalgic/textadv/voxam/
It could not be place directly in src/specs
 

    import cucumber.api.java.*;

    public class ParserSteps {
        private Parser parser;

        @Given("^the game parser$")
        public void the_game_parser() throws Throwable {
          parser = new Parser();
        }

So my step definition has to include the package of the application that it's testing. So it's not clear to me how I can make my step definitions part of a different package structure such that Maven could find them and compile them while still allowing those step definitions to find the relevant application code.

Get the step definitions to access the application is not the problem, a Java class can access any other (public) Java class that is on the classpath.
To get Maven to find, compile and include on the classpath code from an unusual source code directory structure such as src/specs, you need to learn more about Maven than I know (or want to know).

Best Regards
Björn

Jeff Nyman

unread,
Jun 15, 2014, 7:56:50 PM6/15/14
to cu...@googlegroups.com
Thanks for your assistance. Much appreciated. I definitely see that the nature of the JVM (the need for classpath, the packages, etc) makes Cucumber-JVM a bit more cumbersome -- in some ways, at least -- than Ruby Cucumber. Again, though, I understand that's a function of the platform and not the tool.

I wrote up some experiences here:


Hopefully that will be useful to some of my fellow testers.
Reply all
Reply to author
Forward
0 new messages