Skip to content

Instantly share code, notes, and snippets.

@brasmusson
Last active December 18, 2015 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brasmusson/5755281 to your computer and use it in GitHub Desktop.
Save brasmusson/5755281 to your computer and use it in GitHub Desktop.
Cucumber-JVM: Cutting back on Runtime constructors. It is possible to limit them to one constructor and one factory method, but is it the right way to go? 10 files will be affected (mostly test files) in the three projects core, java and junit. To simplify the creation of Runtime in test an additional factory method is introduced in RuntimeTest …
public class Runtime implements UnreportedStepExecutor {
// the factory method is used by cucumber.api.cli.Main and cucumber.api.junit.Cucumber
public static Runtime createRuntime(ResourceLoader resourceLoader, ClassLoader classLoader, RuntimeOptions runtimeOptions) {
UndefinedStepsTracker undefinedStepsTracker = new UndefinedStepsTracker();
return new Runtime(resourceLoader, classLoader, loadBackends(resourceLoader, classLoader), runtimeOptions,
undefinedStepsTracker, new RuntimeGlue(undefinedStepsTracker, new LocalizedXStreams(classLoader)));
}
// The constructor is used in tests both in the core and in the java projects, therefore it needs to be public
public Runtime(ResourceLoader resourceLoader, ClassLoader classLoader, Collection<? extends Backend> backends,
RuntimeOptions runtimeOptions, UndefinedStepsTracker undefinedStepsTracker, RuntimeGlue glue) {
if (backends.isEmpty()) {
throw new CucumberException("No backends were found. Please make sure you have a backend module on your CLASSPATH.");
}
this.resourceLoader = resourceLoader;
this.classLoader = classLoader;
this.backends = backends;
this.runtimeOptions = runtimeOptions;
this.undefinedStepsTracker = undefinedStepsTracker;
this.glue = glue;
this.summaryCounter = new SummaryCounter(runtimeOptions.monochrome);
for (Backend backend : backends) {
backend.loadGlue(glue, runtimeOptions.glue);
backend.setUnreportedStepExecutor(this);
}
}
// <snip>
}
public class RuntimeTest {
// this factory method is duplicated in the java project, cucumber.runtime.java.JavaStepDefinitionTest
public static Runtime createRuntime(ResourceLoader resourceLoader, ClassLoader classLoader,
Collection<? extends Backend> backends, RuntimeOptions runtimeOptions) {
UndefinedStepsTracker undefinedStepsTracker = new UndefinedStepsTracker();
return new Runtime(resourceLoader, classLoader, backends, runtimeOptions, undefinedStepsTracker,
new RuntimeGlue(undefinedStepsTracker, new LocalizedXStreams(classLoader)));
}
//<snip>
}
@sebrose
Copy link

sebrose commented Jun 11, 2013

This seems fine to me.

My only query is why we need to pass UndefinedStepsTracker to the constructor. Isn't this now localised to Runtime?

@brasmusson
Copy link
Author

Yes, the UndefinedStepsTracker is localised to the Runtime, but the same instance is also sent to the RuntimeGlue (when the RuntimeGlue is created by the Runtime). To allow to inject a RuntimeGlue, and still have the normal option of using the same UndefinedStepTracker in the Runtime and RuntimeGlue, I did not come up to another solution than to create the UndefinedStepTracker in the factory method together with the RuntimeGlue and send both to the Runtime constructor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment