Skip to content

Commit

Permalink
Use the tag-expressions library.
Browse files Browse the repository at this point in the history
Use the new tag-expressions library, but support both the use of the new
tag expression syntax and the old tag expression syntax.
  • Loading branch information
brasmusson committed Sep 6, 2016
1 parent ecfc554 commit e14c980
Show file tree
Hide file tree
Showing 20 changed files with 288 additions and 68 deletions.
10 changes: 5 additions & 5 deletions clojure/src/main/clj/cucumber/runtime/clj.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
JdkPatternArgumentMatcher
StepDefinition
HookDefinition
TagExpression)
TagPredicate)
(cucumber.runtime.snippets Snippet
SnippetGenerator)
(clojure.lang RT))
Expand Down Expand Up @@ -92,7 +92,7 @@
(defmulti add-hook-definition (fn [t & _] t))

(defmethod add-hook-definition :before [_ tag-expression hook-fun location]
(let [te (TagExpression. tag-expression)]
(let [tp (TagPredicate/create tag-expression)]
(.addBeforeHook
@glue
(reify
Expand All @@ -102,12 +102,12 @@
(execute [hd scenario-result]
(hook-fun))
(matches [hd tags]
(.evaluate te tags))
(.apply tp tags))
(getOrder [hd] 0)
(isScenarioScoped [hd] false)))))

(defmethod add-hook-definition :after [_ tag-expression hook-fun location]
(let [te (TagExpression. tag-expression)
(let [tp (TagPredicate/create tag-expression)
max-parameter-count (->> hook-fun class .getDeclaredMethods
(filter #(= "invoke" (.getName %)))
(map #(count (.getParameterTypes %)))
Expand All @@ -123,7 +123,7 @@
(hook-fun)
(hook-fun scenario-result)))
(matches [hd tags]
(.evaluate te tags))
(.apply tp tags))
(getOrder [hd] 0)
(isScenarioScoped [hd] false)))))

Expand Down
4 changes: 4 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
<groupId>io.cucumber</groupId>
<artifactId>gherkin</artifactId>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>tag-expressions</artifactId>
</dependency>

<dependency>
<groupId>junit</groupId>
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/cucumber/runtime/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public Runtime(ResourceLoader resourceLoader, ClassLoader classLoader, Collectio
this.filters = new ArrayList<PicklePredicate>();
List<String> tagFilters = runtimeOptions.getTagFilters();
if (!tagFilters.isEmpty()) {
this.filters.add(new TagPredicate(tagFilters));
this.filters.add(TagPredicate.create(tagFilters));
}
List<Pattern> nameFilters = runtimeOptions.getNameFilters();
if (!nameFilters.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,21 @@
import java.util.List;
import java.util.Map;

public class TagExpression {
import static java.util.Arrays.asList;

public class TagExpressionOld {
private final Map<String, Integer> limits = new HashMap<String, Integer>();
private And and = new And();

public TagExpression(List<String> tagExpressions) {
public static boolean isOldTagExpression(String[] tagExpressions) {
return isOldTagExpression(asList(tagExpressions));
}

public static boolean isOldTagExpression(List<String> tagExpressions) {
return !tagExpressions.isEmpty() && (tagExpressions.size() > 1 || tagExpressions.get(0).contains(",") || tagExpressions.get(0).contains("~"));
}

public TagExpressionOld(List<String> tagExpressions) {
for (String tagExpression : tagExpressions) {
add(tagExpression.split("\\s*,\\s*"));
}
Expand Down
41 changes: 36 additions & 5 deletions core/src/main/java/cucumber/runtime/TagPredicate.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,37 @@

import gherkin.pickles.Pickle;
import gherkin.pickles.PickleTag;
import io.cucumber.tagexpressions.Expression;
import io.cucumber.tagexpressions.TagExpressionParser;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class TagPredicate implements PicklePredicate {
private TagExpression tagExpression;
private final Expression expression;
private final TagPredicateOld oldPredicate;

public TagPredicate(List<String> tags) {
this.tagExpression = new TagExpression(tags);
public static TagPredicate create(List<String> tagExpressions) {
if (TagExpressionOld.isOldTagExpression(tagExpressions)) {
return new TagPredicate(null, new TagPredicateOld(tagExpressions));
} else {
return new TagPredicate(tagExpressions.isEmpty() ? null : tagExpressions.get(0));
}
}
public TagPredicate(Expression expression) {
this(expression, null);
}

public TagPredicate(String tagExpression) {
this(tagExpression != null ? new TagExpressionParser().parse(tagExpression) : null);
}

private TagPredicate(Expression expression, TagPredicateOld oldPredicate) {
this.expression = expression;
this.oldPredicate = oldPredicate;
}

@Override
Expand All @@ -25,10 +46,20 @@ public boolean apply(Pickle pickle) {
} catch (Exception e) {
tags = Collections.<PickleTag>emptyList();
}
if (tagExpression.evaluate(tags)) {
return apply(tags);
}

public boolean apply(Collection<PickleTag> pickleTags) {
if (oldPredicate != null) {
return oldPredicate.apply(pickleTags);
} else if (expression == null) {
return true;
}
return false;
List<String> tags = new ArrayList<String>();
for (PickleTag pickleTag : pickleTags) {
tags.add(pickleTag.getName());
}
return expression.evaluate(tags);
}

}
39 changes: 39 additions & 0 deletions core/src/main/java/cucumber/runtime/TagPredicateOld.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cucumber.runtime;

import gherkin.pickles.Pickle;
import gherkin.pickles.PickleTag;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class TagPredicateOld implements PicklePredicate {
private TagExpressionOld tagExpression;

public TagPredicateOld(List<String> tags) {
this.tagExpression = new TagExpressionOld(tags);
}

@Override
public boolean apply(Pickle pickle) {
List<PickleTag> tags;
try { // TODO: Fix when Gherkin provide a getter for the tags.
Field f;
f = pickle.getClass().getDeclaredField("tags");
f.setAccessible(true);
tags = (List<PickleTag>) f.get(pickle);
} catch (Exception e) {
tags = Collections.<PickleTag>emptyList();
}
return apply(tags);
}

public boolean apply(Collection<PickleTag> pickleTags) {
if (tagExpression.evaluate(pickleTags)) {
return true;
}
return false;
}

}
119 changes: 119 additions & 0 deletions core/src/test/java/cucumber/runtime/TagPredicateOldTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package cucumber.runtime;

import gherkin.pickles.Pickle;
import gherkin.pickles.PickleLocation;
import gherkin.pickles.PickleStep;
import gherkin.pickles.PickleTag;
import org.junit.Test;

import java.util.Collections;
import java.util.List;

import static java.util.Arrays.asList;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

public class TagPredicateOldTest {
private static final String NAME = "pickle_name";
private static final List<PickleStep> NO_STEPS = Collections.<PickleStep>emptyList();
private static final PickleLocation MOCK_LOCATION = mock(PickleLocation.class);
private static final String FOO_TAG_VALUE = "@FOO";
private static final PickleTag FOO_TAG = new PickleTag(MOCK_LOCATION, FOO_TAG_VALUE);
private static final String BAR_TAG_VALUE = "@BAR";
private static final PickleTag BAR_TAG = new PickleTag(MOCK_LOCATION, BAR_TAG_VALUE);
private static final String NOT_FOO_TAG_VALUE = "~@FOO";
private static final String FOO_OR_BAR_TAG_VALUE = "@FOO,@BAR";

@Test
public void empty_tag_predicate_matches_pickle_with_any_tags() {
Pickle pickle = createPickleWithTags(asList(FOO_TAG));
TagPredicateOld predicate = new TagPredicateOld(Collections.<String>emptyList());

assertTrue(predicate.apply(pickle));
}

@Test
public void single_tag_predicate_does_not_match_pickle_with_no_tags() {
Pickle pickle = createPickleWithTags(Collections.<PickleTag>emptyList());
TagPredicateOld predicate = new TagPredicateOld(asList(FOO_TAG_VALUE));

assertFalse(predicate.apply(pickle));
}

@Test
public void single_tag_predicate_matches_pickle_with_same_single_tag() {
Pickle pickle = createPickleWithTags(asList(FOO_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(FOO_TAG_VALUE));

assertTrue(predicate.apply(pickle));
}

@Test
public void single_tag_predicate_matches_pickle_with_more_tags() {
Pickle pickle = createPickleWithTags(asList(FOO_TAG, BAR_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(FOO_TAG_VALUE));

assertTrue(predicate.apply(pickle));
}

@Test
public void single_tag_predicate_does_not_match_pickle_with_different_single_tag() {
Pickle pickle = createPickleWithTags(asList(BAR_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(FOO_TAG_VALUE));

assertFalse(predicate.apply(pickle));
}

@Test
public void not_tag_predicate_matches_pickle_with_no_tags() {
Pickle pickle = createPickleWithTags(Collections.<PickleTag>emptyList());
TagPredicateOld predicate = new TagPredicateOld(asList(NOT_FOO_TAG_VALUE));

assertTrue(predicate.apply(pickle));
}

@Test
public void not_tag_predicate_does_not_match_pickle_with_same_single_tag() {
Pickle pickle = createPickleWithTags(asList(FOO_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(NOT_FOO_TAG_VALUE));

assertFalse(predicate.apply(pickle));
}

@Test
public void not_tag_predicate_matches_pickle_with_different_single_tag() {
Pickle pickle = createPickleWithTags(asList(BAR_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(NOT_FOO_TAG_VALUE));

assertTrue(predicate.apply(pickle));
}

@Test
public void and_tag_predicate_matches_pickle_with_all_tags() {
Pickle pickle = createPickleWithTags(asList(FOO_TAG, BAR_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(FOO_TAG_VALUE, BAR_TAG_VALUE));

assertTrue(predicate.apply(pickle));
}

@Test
public void and_tag_predicate_does_not_match_pickle_with_one_of_the_tags() {
Pickle pickle = createPickleWithTags(asList(FOO_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(FOO_TAG_VALUE, BAR_TAG_VALUE));

assertFalse(predicate.apply(pickle));
}

@Test
public void or_tag_predicate_matches_pickle_with_one_of_the_tags() {
Pickle pickle = createPickleWithTags(asList(FOO_TAG));
TagPredicateOld predicate = new TagPredicateOld(asList(FOO_OR_BAR_TAG_VALUE));

assertTrue(predicate.apply(pickle));
}

private Pickle createPickleWithTags(List<PickleTag> tags) {
return new Pickle(NAME, NO_STEPS, tags, asList(MOCK_LOCATION));
}
}
Loading

0 comments on commit e14c980

Please sign in to comment.