Skip to content

Option cucumber.features does not work in cucumber.properties file #2245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ufjena opened this issue Feb 26, 2021 · 7 comments
Closed

Option cucumber.features does not work in cucumber.properties file #2245

ufjena opened this issue Feb 26, 2021 · 7 comments

Comments

@ufjena
Copy link

ufjena commented Feb 26, 2021

My test class is:

import org.junit.runner.RunWith;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/java/posters/cucumber/features", glue = "posters.cucumber.support", tags = "@Chrome and not @Skip", monochrome = true)
public class SingleFeatureTest
{
}

My cucumber.properties file is:

cucumber.publish.quiet=true
cucumber.plugin = pretty, summary, html:target/cucumber-report/cucumber.html

This works fine.

Then I move the "features" and the "glue" option from the test class to the cucumber.properties file:

New test class:

import org.junit.runner.RunWith;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(tags = "@Chrome and not @Skip", monochrome = true)
public class SingleFeatureTest
{
}

New cucumber.properties file:

cucumber.publish.quiet=true
cucumber.plugin = pretty, summary, html:target/cucumber-report/cucumber.html
cucumber.features = src/test/java/posters/cucumber/features
cucumber.glue = posters.cucumber.support

It does NOT work.

java jdk 14
cucumber-junit 6.8.1
cucumber-java 6.8.1
cucumber-picocontainer 6.8.1

I couldn't find anything in internet documentation that helped me.
There are very few examples of the cucumber.properties file.
On the other hand, I found the class io.cucumber.core.options.Constants and believe that I have found the possible options in the cucumber.properties.
Is that right?

Many thanks for your help

@mpkorstanje
Copy link
Contributor

https://github.com/cucumber/cucumber-jvm/blob/main/junit/src/main/java/io/cucumber/junit/CucumberOptions.java#L32-L44

    /**
     * Either a URI or path to a directory of features or a URI or path to a
     * single feature optionally followed by a colon and line numbers.
     * <p>
     * When no feature path is provided, Cucumber will use the package of the
     * annotated class. For example, if the annotated class is
     * {@code com.example.RunCucumber} then features are assumed to be located
     * in {@code classpath:com/example}.
     *
     * @return list of files or directories
     * @see    io.cucumber.core.feature.FeatureWithLines
     */
    String[] features() default {};

@ufjena
Copy link
Author

ufjena commented Mar 1, 2021

@mpkorstanje if that is the solution to my problem, i did not understand you. can you explain it to me in more detail please?

@mpkorstanje
Copy link
Contributor

When using @RunWith(Cucumber.class) properties are taken from the properties file, the @CucumberProperties annotation, the environment and the system. With the latter replacing the former. When the annotation does not define features it will use the package of the annotated class as the location for the features instead. Because it always provides a possible location, the value from the properties file is always replaced.

So you can not use a properties file to provide the location of features. Instead consider putting them in the same package as the runner. So if the runner class is located in src/test/java/com/example/RunCucumber.java then your features should be in src/test/resources/com/example. Alternatively consider using @CucumberOptions(features = "path/to/features")

@ufjena
Copy link
Author

ufjena commented Mar 2, 2021

https://github.com/cucumber/cucumber-jvm/blob/main/junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java
https://github.com/cucumber/cucumber-jvm/blob/main/core/src/main/java/io/cucumber/core/options/Constants.java

The cucumber.publish.quiet option works in the cucumber.properties file

  • it is in io/cucumber/core/options/Constants.java
  • and in io/cucumber/junit/platform/engine/Constants.java

cucumber.glue does not work

  • it is in io/cucumber/core/options/Constants.java
  • and in io/cucumber/junit/platform/engine/Constants.java

cucumber.features does not work
FEATURES_PROPERTY_NAME = "cucumber.features" is in io/cucumber/core/options/Constants.java
FEATURES_PROPERTY_NAME is not in io/cucumber/junit/platform/engine/Constants.java

@mpkorstanje
Copy link
Contributor

Yes, that is working as expected.

addDefaultFeaturePathIfNoFeaturePathIsSpecified(args, clazz);
addDefaultGlueIfNoOverridingGlueIsSpecified(args, clazz);

But I feel there is some information missing. What are you trying to accomplish? Providing context helps us come up with a solution.

@ufjena
Copy link
Author

ufjena commented Mar 2, 2021

My test suite has different packgages e.g.:

  • posters.cucumber.features
  • posters.cucumber.tests
  • posters.pageobjects.pages

We have multiple test classes to filter features with the tag option.
We also do not want to mix feature files and CucumberTest files in one package to keep the view clean.

Therefore every CucumberTest file has the following entry:
@CucumberOptions(features = "src/test/java/posters/cucumber/features")

I would like to move this option to the cucumber.properties file so
that it is used for all CucumberTest files:
cucumber.features = src/test/java/posters/cucumber/features

I understand now that this does not work since the annotation always falls back to the current package path.
This leaves setting the path of my features via the environment or system.
Yet, this is strange since this is really only meant for this test suite.
So I suggest that the annotation should first fall back to the cucumber.properties and only then fall back to the current package path.

We moved the @CucumberOptions plugin and publish from the CucumberTest files
to the cucumber.properties file as cucumber.plugin and cucumber.publish.quiet option.
This works fine.

Regarding cucumber.glue:
I'm unsure what you meant with your code example. Do you mean that it works the same way cucumber.feature does?
If so, why is it in the JUnit constants if it does not work? If not, would you be so kind to explain what you meant.

@mpkorstanje
Copy link
Contributor

Regarding cucumber.glue:
I'm unsure what you meant with your code example. Do you mean that it works the same way cucumber.feature does?

Yes.

If so, why is it in the JUnit constants if it does not work?

You are using cucumber-junit, the JUnit 4 integration. The constants you are referencing are part of the cucumber-junit-platform-engine module and do work as expected when using the JUnit Platform (part of JUnit5).

I understand now that this does not work since the annotation always falls back to the current package path.
This leaves setting the path of my features via the environment or system.
Yet, this is strange since this is really only meant for this test suite.
So I suggest that the annotation should first fall back to the cucumber.properties and only then fall back to the current package path.

That would make sense. Unfortunately this quirk has been around since v1, changing it now could have its own surprising results. And now that Junit 5 exists I don't think its will be worth while to spend too much time improving on JUnit 4.

So I would suggest the following options:

  1. Consider moving the feature files to the resources folder instead (so src/test/resources/posters/cucumber/features) and put the runner classes in posters.cucumber package. Maven/Gradle will put all files in the resources folder on the class path. Because Cucumber checks the package of the runner you can now omit the features directory entirely.

  2. Create a BaseRunner class annotated with a @CucumberOptions applicable to all runners. All other runner then extend the BaseRunner. (Poorly documented unfortunately Document @CucumberOptions from parent class are merged #2215).

  3. If not dependent on JUnit 4 features such as before hooks consider using the declarative test suites from JUnit 5.8.0-M1 in combination with the cucumber-junit-platform-engine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants