Permalink
Browse files

Merge with master. See #295

  • Loading branch information...
2 parents 1791fdc + f0c6b9b commit fc02666dfd2cebc460bfc11658309d12a1d68def @aslakhellesoy aslakhellesoy committed Apr 19, 2012
@@ -7,6 +7,11 @@
import java.io.IOException;
import java.util.List;
+import cucumber.runtime.HookDefinition;
+import cucumber.runtime.StaticHookDefinition;
+import cucumber.runtime.StepDefinition;
+import cucumber.runtime.StepDefinitionMatch;
+
//TODO: now that this is just basically a java bean storing values
// I don't think it needs an interface anymore...
@@ -18,10 +23,18 @@
void addAfterHook(HookDefinition hookDefinition);
+ void addBeforeClassHook(StaticHookDefinition hookDefinition);
+
+ void addAfterClassHook(StaticHookDefinition hookDefinition);
+
List<HookDefinition> getBeforeHooks();
List<HookDefinition> getAfterHooks();
+ List<StaticHookDefinition> getBeforeClassHooks();
+
+ List<StaticHookDefinition> getAfterClassHooks();
+
StepDefinitionMatch stepDefinitionMatch(String uri, Step step, I18n i18n);
void writeStepdefsJson(List<String> featurePaths, File dotCucumber) throws IOException;
@@ -1,10 +1,5 @@
package cucumber.runtime;
-import cucumber.io.ClasspathResourceLoader;
-import cucumber.io.ResourceLoader;
-import cucumber.runtime.converters.LocalizedXStreams;
-import cucumber.runtime.model.CucumberFeature;
-import cucumber.runtime.snippets.SummaryPrinter;
import gherkin.I18n;
import gherkin.formatter.Formatter;
import gherkin.formatter.Reporter;
@@ -20,9 +15,16 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import cucumber.io.ClasspathResourceLoader;
+import cucumber.io.ResourceLoader;
+import cucumber.runtime.converters.LocalizedXStreams;
+import cucumber.runtime.model.CucumberFeature;
+import cucumber.runtime.snippets.SummaryPrinter;
+
/**
* This is the main entry point for running Cucumber features.
*/
@@ -79,7 +81,12 @@ public void addError(Throwable error) {
*/
public void run() {
for (CucumberFeature cucumberFeature : runtimeOptions.cucumberFeatures(resourceLoader)) {
+ Set<Tag> tags = new HashSet<Tag>();
+ tags.addAll(cucumberFeature.getFeature().getTags());
+
+ runBeforeClassHooks(runtimeOptions.reporter(classLoader), tags);
run(cucumberFeature);
+ runAfterClassHooks(runtimeOptions.reporter(classLoader), tags);
}
Formatter formatter = runtimeOptions.formatter(classLoader);
@@ -174,7 +181,15 @@ public void runBeforeHooks(Reporter reporter, Set<Tag> tags) {
public void runAfterHooks(Reporter reporter, Set<Tag> tags) {
runHooks(glue.getAfterHooks(), reporter, tags);
}
+
+ public void runBeforeClassHooks(Reporter reporter, Set<Tag> tags){
+ runStaticHooks(glue.getBeforeClassHooks(), reporter, tags);
+ }
+ public void runAfterClassHooks(Reporter reporter, Set<Tag> tags){
+ runStaticHooks(glue.getAfterClassHooks(), reporter, tags);
+ }
+
private void runHooks(List<HookDefinition> hooks, Reporter reporter, Set<Tag> tags) {
for (HookDefinition hook : hooks) {
runHookIfTagsMatch(hook, reporter, tags);
@@ -198,6 +213,26 @@ private void runHookIfTagsMatch(HookDefinition hook, Reporter reporter, Set<Tag>
}
+ private void runStaticHooks(List<StaticHookDefinition> hooks, Reporter reporter, Set<Tag> tags) {
+ for (StaticHookDefinition hook : hooks) {
+ runStaticHookIfTagsMatch(hook, reporter, tags);
+ }
+ }
+
+ private void runStaticHookIfTagsMatch(StaticHookDefinition hook, Reporter reporter, Set<Tag> tags) {
+ if (hook.matches(tags)) {
+ long start = System.nanoTime();
+ try {
+ hook.execute();
+ } catch (Throwable t) {
+ long duration = System.nanoTime() - start;
+ Result result = new Result(Result.FAILED, duration, t, DUMMY_ARG);
+ reporter.result(result);
+ }
+ }
+ }
+
+
//TODO: Maybe this should go into the cucumber step execution model and it should return the result of that execution!
@Override
public void runUnreportedStep(String uri, I18n i18n, String stepKeyword, String stepName, int line, List<DataTableRow> dataTableRows, DocString docString) throws Throwable {
@@ -1,10 +1,7 @@
package cucumber.runtime;
-import cucumber.io.FileResourceLoader;
-import cucumber.runtime.autocomplete.MetaStepdef;
-import cucumber.runtime.autocomplete.StepdefGenerator;
-import cucumber.runtime.converters.LocalizedXStreams;
-import cucumber.runtime.model.CucumberFeature;
+import static cucumber.runtime.model.CucumberFeature.load;
+import static java.util.Collections.emptyList;
import gherkin.I18n;
import gherkin.deps.com.google.gson.Gson;
import gherkin.deps.com.google.gson.GsonBuilder;
@@ -20,16 +17,21 @@
import java.util.Map;
import java.util.TreeMap;
-import static cucumber.runtime.model.CucumberFeature.load;
-import static java.util.Collections.emptyList;
+import cucumber.io.FileResourceLoader;
+import cucumber.runtime.autocomplete.MetaStepdef;
+import cucumber.runtime.autocomplete.StepdefGenerator;
+import cucumber.runtime.converters.LocalizedXStreams;
+import cucumber.runtime.model.CucumberFeature;
public class RuntimeGlue implements Glue {
private static final List<Object> NO_FILTERS = emptyList();
private final Map<String, StepDefinition> stepDefinitionsByPattern = new TreeMap<String, StepDefinition>();
private final List<HookDefinition> beforeHooks = new ArrayList<HookDefinition>();
private final List<HookDefinition> afterHooks = new ArrayList<HookDefinition>();
-
+ private final List<StaticHookDefinition> beforeClassHooks = new ArrayList<StaticHookDefinition>();
+ private final List<StaticHookDefinition> afterClassHooks = new ArrayList<StaticHookDefinition>();
+
private final UndefinedStepsTracker tracker;
private final LocalizedXStreams localizedXStreams;
@@ -58,6 +60,18 @@ public void addAfterHook(HookDefinition hookDefinition) {
afterHooks.add(hookDefinition);
Collections.sort(afterHooks, new HookComparator(false));
}
+
+ @Override
+ public void addBeforeClassHook(StaticHookDefinition hookDefinition) {
+ beforeClassHooks.add(hookDefinition);
+ Collections.sort(beforeClassHooks, new StaticHookComparator(false));
+ }
+
+ @Override
+ public void addAfterClassHook(StaticHookDefinition hookDefinition) {
+ afterClassHooks.add(hookDefinition);
+ Collections.sort(afterClassHooks, new StaticHookComparator(false));
+ }
@Override
public List<HookDefinition> getBeforeHooks() {
@@ -68,6 +82,17 @@ public void addAfterHook(HookDefinition hookDefinition) {
public List<HookDefinition> getAfterHooks() {
return afterHooks;
}
+
+
+ @Override
+ public List<StaticHookDefinition> getBeforeClassHooks() {
+ return beforeClassHooks;
+ }
+
+ @Override
+ public List<StaticHookDefinition> getAfterClassHooks() {
+ return afterClassHooks;
+ }
@Override
public StepDefinitionMatch stepDefinitionMatch(String uri, Step step, I18n i18n) {
@@ -0,0 +1,17 @@
+package cucumber.runtime;
+
+import java.util.Comparator;
+
+public final class StaticHookComparator implements Comparator<StaticHookDefinition> {
+ final boolean ascending;
+
+ public StaticHookComparator(boolean ascending) {
+ this.ascending = ascending;
+ }
+
+ @Override
+ public int compare(StaticHookDefinition hook1, StaticHookDefinition hook2) {
+ int comparison = hook1.getOrder() - hook2.getOrder();
+ return ascending ? comparison : -comparison;
+ }
+}
@@ -0,0 +1,13 @@
+package cucumber.runtime;
+
+import gherkin.formatter.model.Tag;
+
+import java.util.Collection;
+
+public interface StaticHookDefinition {
+ void execute() throws Throwable;
+
+ boolean matches(Collection<Tag> tags);
+
+ int getOrder();
+}
@@ -0,0 +1,15 @@
+package cucumber.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface AfterClass {
+ /**
+ * @return a tag expression
+ */
+ String[] value() default {};
+}
@@ -0,0 +1,15 @@
+package cucumber.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface BeforeClass {
+ /**
+ * @return a tag expression
+ */
+ String[] value() default {};
+}
@@ -1,17 +1,19 @@
package cucumber.runtime.java;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
+
import cucumber.annotation.After;
+import cucumber.annotation.AfterClass;
import cucumber.annotation.Before;
+import cucumber.annotation.BeforeClass;
import cucumber.annotation.Order;
import cucumber.io.ClasspathResourceLoader;
import cucumber.runtime.CucumberException;
import cucumber.runtime.Utils;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.List;
-
class ClasspathMethodScanner {
private final ClasspathResourceLoader resourceLoader;
@@ -73,7 +75,10 @@ public void scan(JavaBackend javaBackend, Method method) {
private boolean isHookAnnotation(Annotation annotation) {
Class<? extends Annotation> annotationClass = annotation.annotationType();
- return annotationClass.equals(Before.class) || annotationClass.equals(After.class);
+ return annotationClass.equals(Before.class) ||
+ annotationClass.equals(After.class) ||
+ annotationClass.equals(BeforeClass.class) ||
+ annotationClass.equals(AfterClass.class);
}
private boolean isStepdefAnnotation(Annotation annotation) {
@@ -1,7 +1,18 @@
package cucumber.runtime.java;
+import gherkin.formatter.model.Step;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.regex.Pattern;
+
import cucumber.annotation.After;
+import cucumber.annotation.AfterClass;
import cucumber.annotation.Before;
+import cucumber.annotation.BeforeClass;
import cucumber.annotation.Order;
import cucumber.fallback.runtime.java.DefaultJavaObjectFactory;
import cucumber.io.ClasspathResourceLoader;
@@ -11,13 +22,6 @@
import cucumber.runtime.Glue;
import cucumber.runtime.UnreportedStepExecutor;
import cucumber.runtime.snippets.SnippetGenerator;
-import gherkin.formatter.model.Step;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.regex.Pattern;
public class JavaBackend implements Backend {
private final SnippetGenerator snippetGenerator = new SnippetGenerator(new JavaSnippet());
@@ -117,9 +121,23 @@ void addHook(Annotation annotation, Method method) {
if (annotation.annotationType().equals(Before.class)) {
String[] tagExpressions = ((Before) annotation).value();
glue.addBeforeHook(new JavaHookDefinition(method, tagExpressions, hookOrder, objectFactory));
- } else {
+ } else if (annotation.annotationType().equals(After.class)) {
String[] tagExpressions = ((After) annotation).value();
glue.addAfterHook(new JavaHookDefinition(method, tagExpressions, hookOrder, objectFactory));
+ } else if (annotation.annotationType().equals(BeforeClass.class)) {
+ String[] tagExpressions = ((BeforeClass) annotation).value();
+ if (Modifier.isStatic(method.getModifiers())){
+ glue.addBeforeClassHook(new JavaStaticHookDefinition(method, tagExpressions, hookOrder));
+ } else {
+ throw new CucumberException("Methods annotated with @BeforeClass should be static: "+method.getDeclaringClass().getName()+":"+method.getName());
+ }
+ } else if (annotation.annotationType().equals(AfterClass.class)) {
+ String[] tagExpressions = ((AfterClass) annotation).value();
+ if (Modifier.isStatic(method.getModifiers())){
+ glue.addAfterClassHook(new JavaStaticHookDefinition(method, tagExpressions, hookOrder));
+ } else {
+ throw new CucumberException("Methods annotated with @AfterClass should be static: "+method.getDeclaringClass().getName()+":"+method.getName());
+ }
}
}
}
Oops, something went wrong.

0 comments on commit fc02666

Please sign in to comment.