Skip to content

Commit ad9e931

Browse files
committed
[Core] CLI should search classpath root by default
The Cucumber CLI is rather complex to use. To work correctly it needs both a `--glue` parameter in the form of a package name and a location of a feature file in form of a classpath uri or path. As a result people often configure Cucumber incorrectly and are left wondering why their features or glue can not be found. This can be simplified as shown by the Cucumber Platform Engine which defaults to the classpath root and the JUnit and TestNG runners which default to the package of the runner class. So it makes sense to do the same with the CLI. Assuming the following project layout the CLI can discover and execute all features without needing additional arguments. ``` ├── pom.xml ├── src │   ├── main │   │   └── java │   │      └── com/example/Application.java │   └── test │   ├── java │   │   └── com/example/StepDefinitions.java │   └── resources │   └── com/example/example.feature ``` This can be with a single maven command: ``` mvn exec:java \ -Dexec.classpathScope=test \ -Dexec.mainClass=io.cucumber.core.cli.Main ``` Additional benefits can be found in the fact that IDEA often can't work out which package should be used as glue and does not provide a default. The Cucumber Eclipse plugin on the other hand always defaults to the class path root. Fixes: #1875
1 parent 5b102a0 commit ad9e931

File tree

7 files changed

+73
-10
lines changed

7 files changed

+73
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
### Changed
13+
* [Core] CLI should search classpath root by default ([#1889](https://github.com/cucumber/cucumber-jvm/pull/1889) M.P. Korstanje)
1314

1415
### Deprecated
1516

core/src/main/java/io/cucumber/core/cli/Main.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public static byte run(String[] argv, ClassLoader classLoader) {
5454

5555
RuntimeOptions runtimeOptions = new CommandlineOptionsParser()
5656
.parse(argv)
57+
.addDefaultGlueIfAbsent()
58+
.addDefaultFeaturePathIfAbsent()
5759
.addDefaultFormatterIfAbsent()
5860
.addDefaultSummaryPrinterIfAbsent()
5961
.build(systemOptions);

core/src/main/java/io/cucumber/core/options/RuntimeOptions.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import java.util.regex.Pattern;
1818
import java.util.stream.Collectors;
1919

20+
import static io.cucumber.core.resource.ClasspathSupport.rootPackageUri;
21+
import static java.util.Collections.emptyList;
2022
import static java.util.Collections.unmodifiableList;
2123
import static java.util.Collections.unmodifiableMap;
2224

@@ -64,6 +66,17 @@ void addDefaultSummaryPrinterIfAbsent(){
6466
}
6567
}
6668

69+
void addDefaultGlueIfAbsent() {
70+
if (glue.isEmpty()) {
71+
glue.add(rootPackageUri());
72+
}
73+
}
74+
75+
void addDefaultFeaturePathIfAbsent() {
76+
if (featurePaths.isEmpty()) {
77+
featurePaths.add(FeatureWithLines.create(rootPackageUri(), emptyList()));
78+
}
79+
}
6780
public int getCount() {
6881
return count;
6982
}

core/src/main/java/io/cucumber/core/options/RuntimeOptionsBuilder.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public final class RuntimeOptionsBuilder {
3232
private Class<? extends ObjectFactory> parsedObjectFactoryClass = null;
3333
private boolean addDefaultSummaryPrinterIfAbsent;
3434
private boolean addDefaultFormatterIfAbsent;
35+
private boolean addDefaultGlueIfAbsent;
36+
private boolean addDefaultFeaturePathIfAbsent;
3537

3638
public RuntimeOptionsBuilder addRerun(Collection<FeatureWithLines> featureWithLines) {
3739
if (parsedRerunPaths == null) {
@@ -134,6 +136,14 @@ public RuntimeOptions build(RuntimeOptions runtimeOptions) {
134136
runtimeOptions.addDefaultSummaryPrinterIfAbsent();
135137
}
136138

139+
if (addDefaultGlueIfAbsent) {
140+
runtimeOptions.addDefaultGlueIfAbsent();
141+
}
142+
143+
if (addDefaultFeaturePathIfAbsent) {
144+
runtimeOptions.addDefaultFeaturePathIfAbsent();
145+
}
146+
137147
return runtimeOptions;
138148
}
139149

@@ -205,6 +215,17 @@ public RuntimeOptionsBuilder addDefaultFormatterIfAbsent() {
205215
return this;
206216
}
207217

218+
public RuntimeOptionsBuilder addDefaultGlueIfAbsent() {
219+
this.addDefaultGlueIfAbsent = true;
220+
return this;
221+
}
222+
223+
public RuntimeOptionsBuilder addDefaultFeaturePathIfAbsent() {
224+
this.addDefaultFeaturePathIfAbsent = true;
225+
return this;
226+
}
227+
228+
208229
public void setObjectFactoryClass(Class<? extends ObjectFactory> objectFactoryClass) {
209230
this.parsedObjectFactoryClass = objectFactoryClass;
210231
}

core/src/main/resources/io/cucumber/core/options/USAGE.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ Options:
66
Defaults to 1.
77

88
-g, --glue PATH Package to load glue code (step
9-
definitions, hooks and plugins) from.
10-
E.g: com.example.app
9+
definitions, hooks and plugins) from
10+
e.g: com.example.app. When not
11+
provided Cucumber will search the
12+
classpath.
1113

1214
-p, --[add-]plugin PLUGIN[:PATH_OR_URL] Register a plugin.
1315
Built-in formatter PLUGIN types:
@@ -69,6 +71,9 @@ Options:
6971
META-INF/services/io.cucumber.core.backend.ObjectFactory
7072

7173
Feature path examples:
74+
When no feature path is provided
75+
cucumber will scan the classpath root
76+
and its sub directories.
7277

7378
<path> Load the files with the extension
7479
".feature" for the directory <path>

core/src/test/java/io/cucumber/core/options/RuntimeOptionsTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import static io.cucumber.core.options.Constants.FILTER_TAGS_PROPERTY_NAME;
3737
import static io.cucumber.core.options.Constants.OPTIONS_PROPERTY_NAME;
38+
import static io.cucumber.core.resource.ClasspathSupport.rootPackageUri;
3839
import static java.util.Arrays.asList;
3940
import static java.util.Collections.emptyMap;
4041
import static java.util.Collections.singleton;
@@ -734,6 +735,24 @@ void loads_no_features_when_rerun_file_specified_in_cucumber_options_property_is
734735
assertThat(options.getFeaturePaths(), emptyCollectionOf(URI.class));
735736
}
736737

738+
@Test
739+
void scans_class_path_root_for_glue_by_default() {
740+
RuntimeOptions options = new CommandlineOptionsParser()
741+
.parse()
742+
.addDefaultGlueIfAbsent()
743+
.build();
744+
assertThat(options.getGlue(), is(singletonList(rootPackageUri())));
745+
}
746+
747+
@Test
748+
void scans_class_path_root_for_features_by_default() {
749+
RuntimeOptions options = new CommandlineOptionsParser()
750+
.parse()
751+
.addDefaultFeaturePathIfAbsent()
752+
.build();
753+
assertThat(options.getFeaturePaths(), is(singletonList(rootPackageUri())));
754+
assertThat(options.getLineFilters(), is(emptyMap()));
755+
}
737756

738757
public static final class AwareFormatter implements StrictAware, ColorAware, EventListener {
739758

picocontainer/pom.xml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<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">
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
23
<modelVersion>4.0.0</modelVersion>
34

45
<parent>
@@ -66,13 +67,14 @@
6667
</goals>
6768
<configuration>
6869
<target>
69-
<echo message="Running CLI test for picocontainer" />
70-
<java classname="io.cucumber.core.cli.Main" fork="true" failonerror="true" newenvironment="true" maxmemory="512m" classpathref="maven.test.classpath">
71-
<arg value="--plugin" />
72-
<arg value="progress" />
73-
<arg value="--glue" />
74-
<arg value="io.cucumber.picocontainer" />
75-
<arg value="${basedir}/src/test/resources/io/cucumber/picocontainer" />
70+
<echo message="Running CLI test for picocontainer"/>
71+
<java classname="io.cucumber.core.cli.Main"
72+
fork="true"
73+
failonerror="true"
74+
newenvironment="true"
75+
maxmemory="512m"
76+
classpathref="maven.test.classpath"
77+
>
7678
</java>
7779
</target>
7880
</configuration>

0 commit comments

Comments
 (0)