Skip to content

Commit

Permalink
is deprecated in favour of . Closes #549
Browse files Browse the repository at this point in the history
  • Loading branch information
aslakhellesoy committed Aug 27, 2013
1 parent a5ec172 commit 1f6ff9b
Show file tree
Hide file tree
Showing 12 changed files with 297 additions and 197 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ libpeerconnection.log
ehthumbs.db
Icon?
Thumbs.db
test-json-report.json
1 change: 1 addition & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## [Git master](https://github.com/cucumber/cucumber-jvm/compare/v1.1.4...master)

* [JUnit/Core] `@cucumber.junit.api.Cucumber.Options` is deprecated in favour of `@cucumber.api.Options` ([#549](https://github.com/cucumber/cucumber-jvm/issues/549) Aslak Hellesøy)
* [JUnit] Inherit Information of @Cucumber.Options ([#568](https://github.com/cucumber/cucumber-jvm/issues/568) Klaus Bayrhammer)
* [JUnit] JUnitFormatter does not put required name attribute in testsuite root element ([#480](https://github.com/cucumber/cucumber-jvm/pull/480), [#477](https://github.com/cucumber/cucumber-jvm/issues/477) ericmaxwell2003)
* [Core] Output embedded text in HTML report ([#501](https://github.com/cucumber/cucumber-jvm/pull/501) Tom Dunstan)
Expand Down
62 changes: 62 additions & 0 deletions core/src/main/java/cucumber/api/CucumberOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package cucumber.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* This annotation provides the same options as the cucumber command line, {@link cucumber.api.cli.Main}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface CucumberOptions {
/**
* @return true if this is a dry run
*/
boolean dryRun() default false;

/**
* @return true if strict mode is enabled (fail if there are undefined or pending steps)
*/
boolean strict() default false;

/**
* @return the paths to the feature(s)
*/
String[] features() default {};

/**
* @return where to look for glue code (stepdefs and hooks)
*/
String[] glue() default {};

/**
* @return what tags in the features should be executed
*/
String[] tags() default {};

/**
* @return what formatter(s) to use
*/
String[] format() default {};

/**
* @return whether or not to use monochrome output
*/
boolean monochrome() default false;

/**
* Specify a patternfilter for features or scenarios
*
* @return a list of patterns
*/
String[] name() default {};

String dotcucumber() default "";

/**
* @return what format should the snippets use. underscore, camelcase
*/
SnippetType snippets() default SnippetType.UNDERSCORE;
}
182 changes: 182 additions & 0 deletions core/src/main/java/cucumber/runtime/RuntimeOptionsFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package cucumber.runtime;

import cucumber.api.SnippetType;
import cucumber.runtime.io.MultiLoader;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RuntimeOptionsFactory {
private final Class clazz;
private final Class<? extends Annotation>[] annotationClasses;

public RuntimeOptionsFactory(Class clazz, Class<? extends Annotation>[] annotationClasses) {
this.clazz = clazz;
this.annotationClasses = annotationClasses;
}

public RuntimeOptions create() {
List<String> args = buildArgsFromOptions();

return new RuntimeOptions(System.getProperties(), args.toArray(new String[args.size()]));
}

private List<String> buildArgsFromOptions() {
List<String> args = new ArrayList<String>();

for (Class classWithOptions = clazz; hasSuperClass(classWithOptions); classWithOptions = classWithOptions.getSuperclass()) {
Annotation[] optionsArray = getOptions(classWithOptions);
for (Annotation options : optionsArray) {
if (options != null) {
addDryRun(options, args);
addMonochrome(options, args);
addTags(options, args);
addFormats(options, args);
addStrict(options, args);
addName(options, args);
addDotCucumber(options, args);
addSnippets(options, args);
}
}
addGlue(optionsArray, args, classWithOptions);
addFeatures(optionsArray, args, classWithOptions);
}
return args;
}

private void addDotCucumber(Annotation options, List<String> args) {
String dotcucumber = this.invoke(options, "dotcucumber");
if (!dotcucumber.isEmpty()) {
args.add("--dotcucumber");
args.add(dotcucumber);
}
}

private void addName(Annotation options, List<String> args) {
for (String name : this.<String[]>invoke(options, "name")) {
args.add("--name");
args.add(name);
}
}

private void addSnippets(Annotation options, List<String> args) {
args.add("--snippets");
args.add(this.<SnippetType>invoke(options, "snippets").toString());
}

private void addDryRun(Annotation options, List<String> args) {
if (this.<Boolean>invoke(options, "dryRun")) {
args.add("--dry-run");
}
}

private void addMonochrome(Annotation options, List<String> args) {
if (this.<Boolean>invoke(options, "monochrome") || runningInEnvironmentWithoutAnsiSupport()) {
args.add("--monochrome");
}
}

private void addTags(Annotation options, List<String> args) {
for (String tags : this.<String[]>invoke(options, "tags")) {
args.add("--tags");
args.add(tags);
}
}

private void addFormats(Annotation options, List<String> args) {
if (this.<String[]>invoke(options, "format").length != 0) {
for (String format : this.<String[]>invoke(options, "format")) {
args.add("--format");
args.add(format);
}
} else {
args.add("--format");
args.add("null");
}
}

private void addFeatures(Annotation[] optionsArray, List<String> args, Class clazz) {
boolean specified = false;
for (Annotation options : optionsArray) {
if (options != null && this.<String[]>invoke(options, "features").length != 0) {
Collections.addAll(args, this.<String[]>invoke(options, "features"));
specified = true;
}
}
if (!specified) {
args.add(MultiLoader.CLASSPATH_SCHEME + packagePath(clazz));
}
}

private void addGlue(Annotation[] optionsArray, List<String> args, Class clazz) {
boolean specified = false;
for (Annotation options : optionsArray) {
if (options != null && this.<String[]>invoke(options, "glue").length != 0) {
for (String glue : this.<String[]>invoke(options, "glue")) {
args.add("--glue");
args.add(glue);
}
specified = true;
}
}
if (!specified) {
args.add("--glue");
args.add(MultiLoader.CLASSPATH_SCHEME + packagePath(clazz));
}
}


private void addStrict(Annotation options, List<String> args) {
if (this.<Boolean>invoke(options, "strict")) {
args.add("--strict");
}
}

static String packagePath(Class clazz) {
return packagePath(packageName(clazz.getName()));
}

static String packagePath(String packageName) {
return packageName.replace('.', '/');
}

static String packageName(String className) {
return className.substring(0, Math.max(0, className.lastIndexOf(".")));
}

private boolean runningInEnvironmentWithoutAnsiSupport() {
boolean intelliJidea = System.getProperty("idea.launcher.bin.path") != null;
// TODO: What does Eclipse use?
return intelliJidea;
}

private boolean hasSuperClass(Class classWithOptions) {
return classWithOptions != Object.class;
}

private Annotation[] getOptions(Class<?> clazz) {
Annotation[] annotations = new Annotation[annotationClasses.length];
for (int i = 0; i < annotations.length; i++) {
annotations[i] = clazz.getAnnotation(annotationClasses[i]);
}
return annotations;
}

private <T> T invoke(Annotation options, String name) {
try {
Method method = options.annotationType().getMethod(name);
return (T) method.invoke(options);
} catch (NoSuchMethodException e) {
throw new CucumberException(e);
} catch (InvocationTargetException e) {
throw new CucumberException(e);
} catch (IllegalAccessException e) {
throw new CucumberException(e);
}
}

}
Loading

3 comments on commit 1f6ff9b

@brasmusson
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aslakhellesoy I found some remaining Cucumber.Options in the code, I hope that it was not intentional, because I changed them in 1e917e1 (except for the ones in java-helloworld and java-gradle, which explicitly refer to 1.1.4)

@aslakhellesoy
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intentionally left a few in the code just to make sure the old style was still working. After your change it doesn't look like it's tested anywhere ;-)

Let's just be extra careful if we change anything before the old @Cucumber.Options class is completely removed. (In 1.2.0 at the earliest).

@brasmusson
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I think I'll duplicate some of the tests for CucumberOptions for Cucumber.Options, just to be on the safe side.

Please sign in to comment.