Skip to content

Commit

Permalink
Fixes issue junit-team#39, by having multiple calls to ParentRunner.f…
Browse files Browse the repository at this point in the history
…ilter

result in the intersection of filters, rather than just the last
one used.
  • Loading branch information
dsaff committed Apr 15, 2011
1 parent d3de607 commit 669bb57
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 7 deletions.
25 changes: 25 additions & 0 deletions src/main/java/org/junit/runner/manipulation/Filter.java
Expand Up @@ -26,6 +26,11 @@ public boolean shouldRun(Description description) {
public String describe() {
return "all tests";
}

@Override
public void apply(Object child) throws NoTestsRemainException {
// do nothing
};
};

/**
Expand Down Expand Up @@ -78,4 +83,24 @@ public void apply(Object child) throws NoTestsRemainException {
Filterable filterable= (Filterable) child;
filterable.filter(this);
}

/**
* Returns a new Filter that accepts the intersection of the tests accepted
* by this Filter and {@code second}
*/
public Filter intersect(final Filter second) {
final Filter first= this;
return new Filter() {
@Override
public boolean shouldRun(Description description) {
return first.shouldRun(description)
&& second.shouldRun(description);
}

@Override
public String describe() {
return first.describe() + " and " + second.describe();
}
};
}
}
11 changes: 5 additions & 6 deletions src/main/java/org/junit/runners/ParentRunner.java
Expand Up @@ -29,10 +29,10 @@
import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.MultipleFailureException;
import org.junit.runners.model.RunnerScheduler;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;
import org.junit.runners.model.MultipleFailureException;

/**
* Provides most of the functionality specific to a Runner that implements a
Expand All @@ -49,7 +49,7 @@ public abstract class ParentRunner<T> extends Runner implements Filterable,
Sortable {
private final TestClass fTestClass;

private Filter fFilter= null;
private Filter fFilter= Filter.ALL;

private Sorter fSorter= Sorter.NULL;

Expand Down Expand Up @@ -316,7 +316,7 @@ public void run(final RunNotifier notifier) {
//

public void filter(Filter filter) throws NoTestsRemainException {
fFilter= filter;
fFilter= fFilter.intersect(filter);

for (T each : getChildren())
if (shouldRun(each))
Expand Down Expand Up @@ -359,12 +359,11 @@ private void sortChild(T child) {
}

private void filterChild(T child) throws NoTestsRemainException {
if (fFilter != null)
fFilter.apply(child);
fFilter.apply(child);
}

private boolean shouldRun(T each) {
return fFilter == null || fFilter.shouldRun(describeChild(each));
return fFilter.shouldRun(describeChild(each));
}

private Comparator<? super T> comparator() {
Expand Down
1 change: 0 additions & 1 deletion src/test/java/junit/tests/framework/AssertTest.java
@@ -1,6 +1,5 @@
package junit.tests.framework;

import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import junit.framework.ComparisonFailure;
import junit.framework.TestCase;
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/org/junit/tests/AllTests.java
Expand Up @@ -47,6 +47,7 @@
import org.junit.tests.listening.TestListenerTest;
import org.junit.tests.listening.TextListenerTest;
import org.junit.tests.listening.UserStopTest;
import org.junit.tests.manipulation.FilterTest;
import org.junit.tests.manipulation.FilterableTest;
import org.junit.tests.manipulation.SingleMethodTest;
import org.junit.tests.manipulation.SortableTest;
Expand Down Expand Up @@ -128,6 +129,7 @@
JUnit4ClassRunnerTest.class,
UseSuiteAsASuperclassTest.class,
FilterableTest.class,
FilterTest.class,
MaxStarterTest.class,
JUnit38SortingTest.class,
MethodRulesTest.class,
Expand Down
68 changes: 68 additions & 0 deletions src/test/java/org/junit/tests/ParentRunnerTest.java
@@ -1,7 +1,18 @@
package org.junit.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

import java.util.List;

import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.internal.matchers.TypeSafeMatcher;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.ParentRunner;
Expand Down Expand Up @@ -42,4 +53,61 @@ public void finished() {
runner.run(new RunNotifier());
assertEquals("before apple after before banana after afterAll ", log);
}

@Test
public void testMultipleFilters() throws Exception {
JUnitCore junitCore= new JUnitCore();
Request request= Request.aClass(ExampleTest.class);
Request requestFiltered= request.filterWith(new Exclude("test1"));
Request requestFilteredFiltered= requestFiltered
.filterWith(new Exclude("test2"));
Result result= junitCore.run(requestFilteredFiltered);
assertThat(result.getFailures(), isEmpty());
assertEquals(1, result.getRunCount()); // Fails here: actual 2
}

private Matcher<List<?>> isEmpty() {
return new TypeSafeMatcher<List<?>>() {
public void describeTo(org.hamcrest.Description description) {
description.appendText("is empty");
}

@Override
public boolean matchesSafely(List<?> item) {
return item.size() == 0;
}
};
}

private static class Exclude extends Filter {
private String methodName;

public Exclude(String methodName) {
this.methodName= methodName;
}

@Override
public boolean shouldRun(Description description) {
return !description.getMethodName().equals(methodName);
}

@Override
public String describe() {
return "filter method name: " + methodName;
}
}

public static class ExampleTest {
@Test
public void test1() throws Exception {
}

@Test
public void test2() throws Exception {
}

@Test
public void test3() throws Exception {
}
}
}
34 changes: 34 additions & 0 deletions src/test/java/org/junit/tests/manipulation/FilterTest.java
@@ -0,0 +1,34 @@
package org.junit.tests.manipulation;

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.manipulation.Filter;

public class FilterTest {
public static class NamedFilter extends Filter {
private final String fName;

public NamedFilter(String name) {
fName= name;
}

@Override
public boolean shouldRun(Description description) {
return false;
}

@Override
public String describe() {
return fName;
}
}

@Test
public void intersectionText() {
NamedFilter a= new NamedFilter("a");
NamedFilter b= new NamedFilter("b");
assertEquals("a and b", a.intersect(b).describe());
assertEquals("b and a", b.intersect(a).describe());
}
}

0 comments on commit 669bb57

Please sign in to comment.