Skip to content

Commit

Permalink
Fix tagged hooks for scenario outlines. Closes #209, closes #210
Browse files Browse the repository at this point in the history
  • Loading branch information
aslakhellesoy committed Feb 19, 2012
1 parent 91e6032 commit 45d06e2
Show file tree
Hide file tree
Showing 27 changed files with 115 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import cucumber.runtime.ScenarioResult;
import cucumber.runtime.Utils;
import gherkin.TagExpression;
import gherkin.formatter.model.Tag;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -42,7 +43,7 @@ public void execute(ScenarioResult scenarioResult) throws Throwable {
}

@Override
public boolean matches(Collection<String> tags) {
public boolean matches(Collection<Tag> tags) {
return tagExpression.eval(tags);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public class FormatterFactory {

private final ClassLoader classLoader;

private static final Map<String, String> BUILTIN_FORMATTERS = new HashMap<String, String>() {{
put("progress", ProgressFormatter.class.getName());
put("html", HTMLFormatter.class.getName());
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/cucumber/runtime/FeatureBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void parse(Resource resource, List<Object> filters) {

String checksum = checksum(gherkin);
String path = pathsByChecksum.get(checksum);
if(path != null) {
if (path != null) {
throw new CucumberException(String.format("Found the same source in %s and %s", path, resource.getPath()));
}
pathsByChecksum.put(checksum, resource.getPath());
Expand Down
1 change: 0 additions & 1 deletion core/src/main/java/cucumber/runtime/Glue.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Locale;


//TODO: now that this is just basically a java bean storing values
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/java/cucumber/runtime/HookDefinition.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package cucumber.runtime;

import gherkin.formatter.model.Tag;

import java.util.Collection;

public interface HookDefinition {
void execute(ScenarioResult scenarioResult) throws Throwable;

boolean matches(Collection<String> tags);
boolean matches(Collection<Tag> tags);

int getOrder();
}
11 changes: 6 additions & 5 deletions core/src/main/java/cucumber/runtime/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import gherkin.formatter.model.Match;
import gherkin.formatter.model.Result;
import gherkin.formatter.model.Step;
import gherkin.formatter.model.Tag;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -148,21 +149,21 @@ public Glue getGlue() {
return glue;
}

public void runBeforeHooks(Reporter reporter, Set<String> tags) {
public void runBeforeHooks(Reporter reporter, Set<Tag> tags) {
runHooks(glue.getBeforeHooks(), reporter, tags);
}

public void runAfterHooks(Reporter reporter, Set<String> tags) {
public void runAfterHooks(Reporter reporter, Set<Tag> tags) {
runHooks(glue.getAfterHooks(), reporter, tags);
}

private void runHooks(List<HookDefinition> hooks, Reporter reporter, Set<String> tags) {
private void runHooks(List<HookDefinition> hooks, Reporter reporter, Set<Tag> tags) {
for (HookDefinition hook : hooks) {
runHookIfTagsMatch(hook, reporter, tags);
}
}

private void runHookIfTagsMatch(HookDefinition hook, Reporter reporter, Set<String> tags) {
private void runHookIfTagsMatch(HookDefinition hook, Reporter reporter, Set<Tag> tags) {
if (hook.matches(tags)) {
long start = System.nanoTime();
try {
Expand Down Expand Up @@ -200,7 +201,7 @@ public void runUnreportedStep(String uri, I18n i18n, String stepKeyword, String
}

public void runStep(String uri, Step step, Reporter reporter, I18n i18n) {
StepDefinitionMatch match = null;
StepDefinitionMatch match;

try {
match = glue.stepDefinitionMatch(uri, step, i18n);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package cucumber.runtime;

import cucumber.table.DataTable;
import gherkin.I18n;
import gherkin.formatter.model.DataTableRow;
import gherkin.formatter.model.DocString;

import java.util.List;
import java.util.Locale;

public interface UnreportedStepExecutor {
//TODO: Maybe this should go into the cucumber step execution model and it should return the result of that execution!
Expand Down
13 changes: 12 additions & 1 deletion core/src/main/java/cucumber/runtime/model/CucumberExamples.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import gherkin.formatter.Formatter;
import gherkin.formatter.model.Examples;
import gherkin.formatter.model.ExamplesTableRow;
import gherkin.formatter.model.Tag;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CucumberExamples {
private final CucumberScenarioOutline cucumberScenarioOutline;
Expand All @@ -20,12 +23,20 @@ public List<CucumberScenario> createExampleScenarios() {
List<CucumberScenario> exampleScenarios = new ArrayList<CucumberScenario>();

List<ExamplesTableRow> rows = examples.getRows();
List<Tag> tags = new ArrayList<Tag>(tagsAndInheritedTags());
for (int i = 1; i < rows.size(); i++) {
exampleScenarios.add(cucumberScenarioOutline.createExampleScenario(rows.get(0), rows.get(i), examples.getTags()));
exampleScenarios.add(cucumberScenarioOutline.createExampleScenario(rows.get(0), rows.get(i), tags));
}
return exampleScenarios;
}

private Set<Tag> tagsAndInheritedTags() {
Set<Tag> tags = new HashSet<Tag>();
tags.addAll(cucumberScenarioOutline.tagsAndInheritedTags());
tags.addAll(examples.getTags());
return tags;
}

public Examples getExamples() {
return examples;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static List<CucumberFeature> load(ResourceLoader resourceLoader, List<Str
builder.parse(resource, filters);
}
}
if(cucumberFeatures.isEmpty()) {
if (cucumberFeatures.isEmpty()) {
throw new CucumberException(String.format("No features found at %s", featurePaths));
}
return cucumberFeatures;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public CucumberScenario(CucumberFeature cucumberFeature, CucumberBackground cucu
@Override
public void run(Formatter formatter, Reporter reporter, Runtime runtime) {
runtime.buildBackendWorlds();
runtime.runBeforeHooks(reporter, tags());
runtime.runBeforeHooks(reporter, tagsAndInheritedTags());

runBackground(formatter, reporter, runtime);
format(formatter);
runSteps(reporter, runtime);

runtime.runAfterHooks(reporter, tags());
runtime.runAfterHooks(reporter, tagsAndInheritedTags());
runtime.disposeBackendWorlds();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ public void run(Formatter formatter, Reporter reporter, Runtime runtime) {
}
}

CucumberScenario createExampleScenario(ExamplesTableRow header, ExamplesTableRow example, List<Tag> tags) {
Scenario exampleScenario = new Scenario(example.getComments(), tags, tagStatement.getKeyword(), tagStatement.getName(), "", example.getLine(), example.getId());
CucumberScenario createExampleScenario(ExamplesTableRow header, ExamplesTableRow example, List<Tag> examplesTags) {
Scenario exampleScenario = new Scenario(example.getComments(), examplesTags, tagStatement.getKeyword(), tagStatement.getName(), "", example.getLine(), example.getId());
CucumberScenario cucumberScenario = new CucumberScenario(cucumberFeature, cucumberBackground, exampleScenario, example);
for (Step step : getSteps()) {
cucumberScenario.step(createExampleStep(step, header, example));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,10 @@ public CucumberTagStatement(CucumberFeature cucumberFeature, TagStatement tagSta
this.visualName = "| " + join(example.getCells(), " | ") + " |";
}

protected Set<String> tags() {
Set<String> tags = new HashSet<String>();
for (Tag tag : cucumberFeature.getFeature().getTags()) {
tags.add(tag.getName());
}
for (Tag tag : tagStatement.getTags()) {
tags.add(tag.getName());
}
protected Set<Tag> tagsAndInheritedTags() {
Set<Tag> tags = new HashSet<Tag>();
tags.addAll(cucumberFeature.getFeature().getTags());
tags.addAll(tagStatement.getTags());
return tags;
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/cucumber/runtime/model/StepContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

public class StepContainer {
private final List<Step> steps = new ArrayList<Step>();
private final BasicStatement statement;
protected final CucumberFeature cucumberFeature;
private final BasicStatement statement;

public StepContainer(CucumberFeature cucumberFeature, BasicStatement statement) {
this.statement = statement;
this.cucumberFeature = cucumberFeature;
this.statement = statement;
}

public List<Step> getSteps() {
Expand Down
9 changes: 5 additions & 4 deletions core/src/test/java/cucumber/runtime/HookOrderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import cucumber.io.ResourceLoader;
import gherkin.formatter.Reporter;
import gherkin.formatter.model.Tag;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
Expand Down Expand Up @@ -37,7 +38,7 @@ public void before_hooks_execute_in_order() throws Throwable {
glue.addBeforeHook(hook);
}

runtime.runBeforeHooks(mock(Reporter.class), new HashSet<String>());
runtime.runBeforeHooks(mock(Reporter.class), new HashSet<Tag>());

InOrder inOrder = inOrder(hooks.toArray());
inOrder.verify(hooks.get(2)).execute(Matchers.<ScenarioResult>any());
Expand All @@ -52,7 +53,7 @@ public void after_hooks_execute_in_reverse_order() throws Throwable {
glue.addAfterHook(hook);
}

runtime.runAfterHooks(mock(Reporter.class), new HashSet<String>());
runtime.runAfterHooks(mock(Reporter.class), new HashSet<Tag>());

InOrder inOrder = inOrder(hooks.toArray());
inOrder.verify(hooks.get(1)).execute(Matchers.<ScenarioResult>any());
Expand All @@ -71,7 +72,7 @@ public void hooks_order_across_many_backends() throws Throwable {
glue.addBeforeHook(hook);
}

runtime.runBeforeHooks(mock(Reporter.class), new HashSet<String>());
runtime.runBeforeHooks(mock(Reporter.class), new HashSet<Tag>());

List<HookDefinition> allHooks = new ArrayList<HookDefinition>();
allHooks.addAll(backend1Hooks);
Expand All @@ -91,7 +92,7 @@ private List<HookDefinition> mockHooks(int... ordering) {
for (int order : ordering) {
HookDefinition hook = mock(HookDefinition.class, "Mock number " + order);
when(hook.getOrder()).thenReturn(order);
when(hook.matches(anyListOf(String.class))).thenReturn(true);
when(hook.matches(anyListOf(Tag.class))).thenReturn(true);
hooks.add(hook);
}
return hooks;
Expand Down
2 changes: 1 addition & 1 deletion core/src/test/java/cucumber/runtime/HookTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class HookTest {
public void after_hooks_execute_before_objects_are_disposed() throws Throwable {
Backend backend = mock(Backend.class);
HookDefinition hook = mock(HookDefinition.class);
when(hook.matches(anyListOf(String.class))).thenReturn(true);
when(hook.matches(anyListOf(Tag.class))).thenReturn(true);
Scenario gherkinScenario = mock(Scenario.class);

CucumberFeature feature = mock(CucumberFeature.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,46 @@
import gherkin.formatter.model.Comment;
import gherkin.formatter.model.Examples;
import gherkin.formatter.model.ExamplesTableRow;
import gherkin.formatter.model.Feature;
import gherkin.formatter.model.ScenarioOutline;
import gherkin.formatter.model.Step;
import gherkin.formatter.model.Tag;
import org.junit.Test;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.junit.Assert.assertEquals;

public class CucumberExamplesTest {
private static final List<Comment> COMMENTS = emptyList();
private static final List<Tag> TAGS = emptyList();
private static final List<Tag> FEATURE_TAGS = asList(new Tag("@feature", 1));
private static final List<Tag> SO_TAGS = asList(new Tag("@scenario_outline", 1));
private static final List<Tag> E_TAGS = asList(new Tag("@example", 1));

@Test
public void should_create_example_scenarios() {
ScenarioOutline so = new ScenarioOutline(COMMENTS, TAGS, "Scenario Outline", "", "", 1, "");
CucumberScenarioOutline cso = new CucumberScenarioOutline(null, null, so);
cso.step(new Step(COMMENTS, "Given ", "I have 5 <what> in my <where>", 2, null, null));
Examples examples = new Examples(COMMENTS, TAGS, "Examples", "", "", 3, "", asList(
new ExamplesTableRow(COMMENTS, asList("what", "where"), 4, ""),
new ExamplesTableRow(COMMENTS, asList("cukes", "belly"), 5, ""),
new ExamplesTableRow(COMMENTS, asList("apples", "basket"), 6, "")
CucumberFeature cucumberFeature = new CucumberFeature(new Feature(COMMENTS, FEATURE_TAGS, "Feature", "", "", 2, "fid"), "f.feature");
ScenarioOutline so = new ScenarioOutline(COMMENTS, SO_TAGS, "Scenario Outline", "", "", 4, "");
CucumberScenarioOutline cso = new CucumberScenarioOutline(cucumberFeature, null, so);
cso.step(new Step(COMMENTS, "Given ", "I have 5 <what> in my <where>", 5, null, null));
Examples examples = new Examples(COMMENTS, E_TAGS, "Examples", "", "", 6, "", asList(
new ExamplesTableRow(COMMENTS, asList("what", "where"), 7, ""),
new ExamplesTableRow(COMMENTS, asList("cukes", "belly"), 8, ""),
new ExamplesTableRow(COMMENTS, asList("apples", "basket"), 9, "")
));

CucumberExamples cucumberExamples = new CucumberExamples(cso, examples);
List<CucumberScenario> exampleScenarios = cucumberExamples.createExampleScenarios();
assertEquals(2, exampleScenarios.size());
Set<Tag> expectedTags = new HashSet<Tag>();
expectedTags.addAll(FEATURE_TAGS);
expectedTags.addAll(SO_TAGS);
expectedTags.addAll(E_TAGS);
assertEquals(expectedTags, exampleScenarios.get(0).tagsAndInheritedTags());

CucumberScenario cucumberScenario = exampleScenarios.get(0);
Step step = cucumberScenario.getSteps().get(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import cucumber.runtime.HookDefinition;
import cucumber.runtime.ScenarioResult;
import gherkin.TagExpression;
import gherkin.formatter.model.Tag;
import groovy.lang.Closure;

import java.util.Collection;
Expand All @@ -24,7 +25,7 @@ public void execute(ScenarioResult scenarioResult) throws Throwable {
}

@Override
public boolean matches(Collection<String> tags) {
public boolean matches(Collection<Tag> tags) {
return tagExpression.eval(tags);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import cucumber.runtime.HookDefinition;
import cucumber.runtime.ScenarioResult;
import gherkin.TagExpression;
import gherkin.formatter.model.Tag;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -53,7 +54,7 @@ public void execute(ScenarioResult scenarioResult) throws Throwable {
}

@Override
public boolean matches(Collection<String> tags) {
public boolean matches(Collection<Tag> tags) {
return tagExpression.eval(tags);
}

Expand Down
5 changes: 3 additions & 2 deletions java/src/test/java/cucumber/runtime/java/JavaHookTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import cucumber.runtime.RuntimeGlue;
import cucumber.runtime.UndefinedStepsTracker;
import cucumber.runtime.converters.LocalizedXStreams;
import gherkin.formatter.model.Tag;
import org.junit.Test;

import java.lang.reflect.Method;
Expand Down Expand Up @@ -80,15 +81,15 @@ public void matches_matching_tags() {
backend.buildWorld();
backend.addHook(BEFORE.getAnnotation(Before.class), HasHooks.class, BEFORE);
HookDefinition before = glue.getBeforeHooks().get(0);
assertTrue(before.matches(asList("@bar", "@zap")));
assertTrue(before.matches(asList(new Tag("@bar", 0), new Tag("@zap", 0))));
}

@Test
public void does_not_match_non_matching_tags() {
backend.buildWorld();
backend.addHook(BEFORE.getAnnotation(Before.class), HasHooks.class, BEFORE);
HookDefinition before = glue.getBeforeHooks().get(0);
assertFalse(before.matches(asList("@bar")));
assertFalse(before.matches(asList(new Tag("@bar", 0))));
}

public static class HasHooks {
Expand Down
Loading

0 comments on commit 45d06e2

Please sign in to comment.