Skip to content

Commit

Permalink
[Core] Refactor runtime options parsing (#1670)
Browse files Browse the repository at this point in the history
Re-factoring of the runtime options parsing. Tried to achieve several goals:
 * Use a builder rather then CLI arguments to represents options in parsing
 * Pull default behaviour setting up into the runners
 * Pull the different runtime option sources into the runners
 * Run JUnit and TestNG with zero output by default

## Motivation and Context

Cucumber was build with hexagonal architecture in mind. Unfortunately one of the ports that was frequently reused was the command line interface. This resulted in a complex and complicated chain of methods that construct and then parse CLI arguments. This system was hard to understand and change.

On top of this Cucumber accepts commandline options from both the CLI and the environment. This however happened in the bowels of option parsing. Making it non obvious and again hard to follow.

Because the command line interface was used as a port it also imposed the command line defaults on all runners. However for JUnit and TesstNG the default progress formatter nor summary plug-in are particularly useful. Ideal tests are quite.

Finally this structure also forces us to pull in implementation defaults from different runners into the core (e.g. `junitOptions`). This re factoring will allow JUnit and TestNG to define their own `@CucumberOptions` annotation. 

## Related stuff

 * #1476
 * #1537
 * #1135
 * #1029
  • Loading branch information
mpkorstanje committed Jun 22, 2019
1 parent 48d3202 commit 312039f
Show file tree
Hide file tree
Showing 68 changed files with 2,187 additions and 979 deletions.
18 changes: 13 additions & 5 deletions CHANGELOG.md
Expand Up @@ -9,17 +9,25 @@ Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CO
* [Java] Use ServiceLoader for Guice, Needle, OpenEJB, Pico, Spring and Weld `ObjectFactory` implementations. * [Java] Use ServiceLoader for Guice, Needle, OpenEJB, Pico, Spring and Weld `ObjectFactory` implementations.
- Removes spurious deprecation warning. - Removes spurious deprecation warning.
- Moves `ObjectFactory` implements to `io.cucumber.<module-name>` package. - Moves `ObjectFactory` implements to `io.cucumber.<module-name>` package.
* [JUnit] JUnit will no longer run in verbose mode by default ([#1670](https://github.com/cucumber/cucumber-jvm/pull/1670) M.P. Korstanje)
- Add `summary` and/or `progress` plugins to restore output
* [TestNG] TestNG will no longer run in verbose mode by default ([#1670](https://github.com/cucumber/cucumber-jvm/pull/1670) M.P. Korstanje)
- Add `summary` and/or `progress` plugins to restore output


### Deprecated ### Deprecated
* [JUnit] Deprecate `cucumber.api.junit.Cucumber` * [JUnit] Deprecate `cucumber.api.junit.Cucumber`
- Use `io.cucumber.junit.Cucumber` instead. - Use `io.cucumber.junit.Cucumber` instead.
* [TestNG] Deprecate `cucumber.api.testng.TestNGCucumberRunner` * [TestNG] Deprecate `cucumber.api.testng.TestNGCucumberRunner`
- Use `io.cucumber.testng.TestNGCucumberRunner` instead. - Use `io.cucumber.testng.TestNGCucumberRunner` instead.
* [Needle] Deprecate `cucumber.api.needle.*` * [Needle] Deprecate `cucumber.api.needle.*`
- Use `io.cucumber.needle.*` instead. - Use `io.cucumber.needle.*` instead.
* [Spring] Deprecate `cucumber.api.spring.SpringTransactionHooks` * [Spring] Deprecate `cucumber.api.spring.SpringTransactionHooks`
- It is recommended to implement your own transaction hooks. - It is recommended to implement your own transaction hooks.
- Will allow the dependency on `spring-txn` to be removed. - Will allow the dependency on `spring-txn` to be removed.
* [Core] Deprecate `cucumber.api.CucumberOptions` ([#1670](https://github.com/cucumber/cucumber-jvm/pull/1670) M.P. Korstanje)
- Use `io.cucumber.junit.CucumberOptions` or `io.cucumber.testng.CucumberOptions` instead
* [Core] Deprecate `cucumber.api.cli.Main` ([#1670](https://github.com/cucumber/cucumber-jvm/pull/1670) M.P. Korstanje)
- Use `io.cucumber.core.cli.Main` instead


### Removed ### Removed


Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/cucumber/api/CucumberOptions.java
Expand Up @@ -7,9 +7,12 @@


/** /**
* Configure Cucumbers options. * Configure Cucumbers options.
*
* @deprecated use either {@code io.cucumber.junit.CucumberOptions} or {@code io.cucumber.testng.CucumberOptions}.
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE}) @Target({ElementType.TYPE})
@Deprecated
public @interface CucumberOptions { public @interface CucumberOptions {


/** /**
Expand Down
19 changes: 10 additions & 9 deletions core/src/main/java/cucumber/api/cli/Main.java
@@ -1,9 +1,16 @@
package cucumber.api.cli; package cucumber.api.cli;


import cucumber.runtime.Runtime; import io.cucumber.core.logging.Logger;
import io.cucumber.core.logging.LoggerFactory;


/**
* @deprecated use {@link io.cucumber.core.cli.Main} instead.
*/
@Deprecated
public class Main { public class Main {


private static final Logger log = LoggerFactory.getLogger(Main.class);

public static void main(String[] argv) { public static void main(String[] argv) {
byte exitStatus = run(argv, Thread.currentThread().getContextClassLoader()); byte exitStatus = run(argv, Thread.currentThread().getContextClassLoader());
System.exit(exitStatus); System.exit(exitStatus);
Expand All @@ -17,13 +24,7 @@ public static void main(String[] argv) {
* @return 0 if execution was successful, 1 if it was not (test failures) * @return 0 if execution was successful, 1 if it was not (test failures)
*/ */
public static byte run(String[] argv, ClassLoader classLoader) { public static byte run(String[] argv, ClassLoader classLoader) {

log.warn("You are using deprecated Main class. Please use io.cucumber.core.api.cli.Main");
final Runtime runtime = Runtime.builder() return io.cucumber.core.cli.Main.run(argv, classLoader);
.withArgs(argv)
.withClassLoader(classLoader)
.build();

runtime.run();
return runtime.exitStatus();
} }
} }
1 change: 1 addition & 0 deletions core/src/main/java/cucumber/runtime/ExitStatus.java
Expand Up @@ -5,6 +5,7 @@
import cucumber.api.event.EventListener; import cucumber.api.event.EventListener;
import cucumber.api.event.EventPublisher; import cucumber.api.event.EventPublisher;
import cucumber.api.event.TestCaseFinished; import cucumber.api.event.TestCaseFinished;
import io.cucumber.core.options.RuntimeOptions;


import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
Expand Down
17 changes: 2 additions & 15 deletions core/src/main/java/cucumber/runtime/Runtime.java
Expand Up @@ -22,6 +22,7 @@
import gherkin.events.PickleEvent; import gherkin.events.PickleEvent;
import io.cucumber.core.logging.Logger; import io.cucumber.core.logging.Logger;
import io.cucumber.core.logging.LoggerFactory; import io.cucumber.core.logging.LoggerFactory;
import io.cucumber.core.options.RuntimeOptions;


import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
Expand Down Expand Up @@ -140,7 +141,7 @@ public static class Builder {


private EventBus eventBus = new TimeServiceEventBus(TimeService.SYSTEM); private EventBus eventBus = new TimeServiceEventBus(TimeService.SYSTEM);
private ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
private RuntimeOptions runtimeOptions = new RuntimeOptions(""); private RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
private BackendSupplier backendSupplier; private BackendSupplier backendSupplier;
private ResourceLoader resourceLoader; private ResourceLoader resourceLoader;
private ClassFinder classFinder; private ClassFinder classFinder;
Expand All @@ -150,20 +151,6 @@ public static class Builder {
private Builder() { private Builder() {
} }


public Builder withArg(final String arg) {
this.runtimeOptions = new RuntimeOptions(arg);
return this;
}

public Builder withArgs(final String... args) {
return withArgs(Arrays.asList(args));
}

public Builder withArgs(final List<String> args) {
this.runtimeOptions = new RuntimeOptions(args);
return this;
}

public Builder withRuntimeOptions(final RuntimeOptions runtimeOptions) { public Builder withRuntimeOptions(final RuntimeOptions runtimeOptions) {
this.runtimeOptions = runtimeOptions; this.runtimeOptions = runtimeOptions;
return this; return this;
Expand Down

0 comments on commit 312039f

Please sign in to comment.