Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #386 from matthewfarwell/sortwith

SortMethodsWith allows the user to choose the order of execution of the methods within a test class
  • Loading branch information...
commit 560322d742f0862a27f53a51cb67a17dd69e2f2f 2 parents 3639784 + 7924760
David Saff authored
View
41 src/main/java/org/junit/FixMethodOrder.java
@@ -0,0 +1,41 @@
+package org.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.runners.MethodSorters;
+
+/**
+ * This class allows the user to choose the order of execution of the methods within a test class.
+ * <br/>
+ * <br/>
+ * The default order of execution of JUnit tests within a class is deterministic but not predictable.
+ * The order of execution is not guaranteed for Java 7 (and some previous versions), and can even change
+ * from run to run, so the order of execution was changed to be deterministic (in JUnit 4.11)
+ * <br/>
+ * It is recommended that test methods be written so that they are independent of the order that they are executed.
+ * However, there may be a number of dependent tests either through error or by design.
+ * This class allows the user to specify the order of execution of test methods.
+ * <br/>
+ * For possibilities, see {@link MethodSorters}
+ *
+ * Here is an example:
+ *
+ * <pre>
+ * &#064;FixMethodOrder(MethodSorters.NAME_ASCENDING)
+ * public class MyTest {
+ * }
+ * </pre>
+ *
+ * @see org.junit.runners.MethodSorters
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface FixMethodOrder {
+ /**
+ * Optionally specify <code>value</code> to have the methods executed in a particular order
+ */
+ MethodSorters value() default MethodSorters.DEFAULT;
+}
View
52 src/main/java/org/junit/internal/MethodSorter.java
@@ -4,32 +4,64 @@
import java.util.Arrays;
import java.util.Comparator;
+import org.junit.FixMethodOrder;
+
public class MethodSorter {
+ /**
+ * DEFAULT sort order
+ */
+ public static Comparator<Method> DEFAULT= new Comparator<Method>() {
+ public int compare(Method m1, Method m2) {
+ int i1 = m1.getName().hashCode();
+ int i2 = m2.getName().hashCode();
+ return i1 != i2 ? i1 - i2 : MethodSorter.compare(m1.toString(), m2.toString());
+ }
+ };
+
+ /**
+ * Method name ascending lexicograhic sort order
+ */
+ public static Comparator<Method> NAME_ASCENDING= new Comparator<Method>() {
+ public int compare(Method m1, Method m2) {
+ return MethodSorter.compare(m1.getName(), m2.getName());
+ }
+ };
+ private static int compare(String s1, String s2) {
+ return s1.compareTo(s2);
+ }
+
/**
- * Gets declared methods of a class in a predictable order.
+ * Gets declared methods of a class in a predictable order, unless @FixMethodOrder(MethodSorters.JVM) is specified.
+ *
* Using the JVM order is unwise since the Java platform does not
* specify any particular order, and in fact JDK 7 returns a more or less
* random order; well-written test code would not assume any order, but some
* does, and a predictable failure is better than a random failure on
- * certain platforms. Uses an unspecified but deterministic order.
+ * certain platforms. By default, uses an unspecified but deterministic order.
* @param clazz a class
* @return same as {@link Class#getDeclaredMethods} but sorted
* @see <a href="http://bugs.sun.com/view_bug.do?bug_id=7023180">JDK
* (non-)bug #7023180</a>
*/
public static Method[] getDeclaredMethods(Class<?> clazz) {
- Method[] methods = clazz.getDeclaredMethods();
- Arrays.sort(methods, new Comparator<Method>() {
- @Override public int compare(Method m1, Method m2) {
- int i1 = m1.getName().hashCode();
- int i2 = m2.getName().hashCode();
- return i1 != i2 ? i1 - i2 : m1.toString().compareTo(m2.toString());
- }
- });
+ Comparator<Method> comparator= getSorter(clazz.getAnnotation(FixMethodOrder.class));
+
+ Method[] methods= clazz.getDeclaredMethods();
+ if (comparator != null) {
+ Arrays.sort(methods, comparator);
+ }
+
return methods;
}
private MethodSorter() {}
+ private static Comparator<Method> getSorter(FixMethodOrder fixMethodOrder) {
+ if (fixMethodOrder == null) {
+ return DEFAULT;
+ }
+
+ return fixMethodOrder.value().getComparator();
+ }
}
View
29 src/main/java/org/junit/runners/MethodSorters.java
@@ -0,0 +1,29 @@
+package org.junit.runners;
+
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+import org.junit.internal.MethodSorter;
+
+/**
+ * Sort the methods into a specified execution order.
+ * Defines common {@link MethodSorter} implementations.
+ */
+public enum MethodSorters {
+ /** Sorts the test methods by the method name, in lexicographic order */
+ NAME_ASCENDING(MethodSorter.NAME_ASCENDING),
+ /** Sorts the test methods by the method name, in reverse lexicographic order */
+ JVM(null),
+ /** the default value, deterministic, but not predictable */
+ DEFAULT(MethodSorter.DEFAULT);
+
+ private final Comparator<Method> fComparator;
+
+ private MethodSorters(Comparator<Method> comparator) {
+ this.fComparator= comparator;
+ }
+
+ public Comparator<Method> getComparator() {
+ return fComparator;
+ }
+}
View
81 src/test/java/org/junit/internal/MethodSorterTest.java
@@ -1,22 +1,68 @@
package org.junit.internal;
+import java.lang.reflect.Method;
import java.util.Arrays;
+
+import org.junit.FixMethodOrder;
import org.junit.Test;
+import org.junit.runners.MethodSorters;
import static org.junit.Assert.*;
public class MethodSorterTest {
+ private static final String ALPHA= "java.lang.Object alpha(int,double,java.lang.Thread)";
+ private static final String BETA= "void beta(int[][])";
+ private static final String GAMMA_VOID= "int gamma()";
+ private static final String GAMMA_BOOLEAN= "void gamma(boolean)";
+ private static final String DELTA= "void delta()";
+ private static final String EPSILON= "void epsilon()";
+
+ private static class Dummy {
+ Object alpha(int i, double d, Thread t) {return null;}
+ void beta(int[][] x) {}
+ int gamma() {return 0;}
+ void gamma(boolean b) {}
+ void delta() {}
+ void epsilon() {}
+ }
+ private static class Super {
+ void testOne() {}
+ }
+ private static class Sub extends Super {
+ void testTwo() {}
+ }
+
+ private String toString(Class<?> clazz, Method[] methods) {
+ return Arrays.toString(methods).replace(clazz.getName() + '.', "");
+ }
+
+ private String declaredMethods(Class<?> clazz) {
+ return toString(clazz, MethodSorter.getDeclaredMethods(clazz));
+ }
- @Test public void getDeclaredMethods() throws Exception {
- assertEquals("[void epsilon(), void beta(int[][]), java.lang.Object alpha(int,double,java.lang.Thread), void delta(), int gamma(), void gamma(boolean)]", declaredMethods(Dummy.class));
+ @Test public void getMethodsNullSorter() throws Exception {
+ String[] expected= new String[] { EPSILON, BETA, ALPHA, DELTA, GAMMA_VOID, GAMMA_BOOLEAN };
+ assertEquals(Arrays.asList(expected).toString(), declaredMethods(Dummy.class));
assertEquals("[void testOne()]", declaredMethods(Super.class));
assertEquals("[void testTwo()]", declaredMethods(Sub.class));
}
-
- private static String declaredMethods(Class<?> c) {
- return Arrays.toString(MethodSorter.getDeclaredMethods(c)).replace(c.getName() + '.', "");
+
+ @FixMethodOrder(MethodSorters.DEFAULT)
+ private static class DummySortWithDefault {
+ Object alpha(int i, double d, Thread t) {return null;}
+ void beta(int[][] x) {}
+ int gamma() {return 0;}
+ void gamma(boolean b) {}
+ void delta() {}
+ void epsilon() {}
}
- private static class Dummy {
+ @Test public void testDefaultSorter() {
+ String[] expected= new String[] { EPSILON, BETA, ALPHA, DELTA, GAMMA_VOID, GAMMA_BOOLEAN };
+ assertEquals(Arrays.asList(expected).toString(), declaredMethods(DummySortWithDefault.class));
+ }
+
+ @FixMethodOrder(MethodSorters.JVM)
+ private static class DummySortJvm {
Object alpha(int i, double d, Thread t) {return null;}
void beta(int[][] x) {}
int gamma() {return 0;}
@@ -24,11 +70,26 @@ void gamma(boolean b) {}
void delta() {}
void epsilon() {}
}
- private static class Super {
- void testOne() {}
+
+ @Test public void testSortWithJvm() {
+ Class<?> clazz= DummySortJvm.class;
+ String actual= toString(clazz, clazz.getDeclaredMethods());
+
+ assertEquals(actual, declaredMethods(clazz));
}
- private static class Sub extends Super {
- void testTwo() {}
+
+ @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+ private static class DummySortWithNameAsc {
+ Object alpha(int i, double d, Thread t) {return null;}
+ void beta(int[][] x) {}
+ int gamma() {return 0;}
+ void gamma(boolean b) {}
+ void delta() {}
+ void epsilon() {}
}
+ @Test public void testNameAsc() {
+ String[] expected= new String[] { ALPHA, BETA, DELTA, EPSILON, GAMMA_VOID, GAMMA_BOOLEAN };
+ assertEquals(Arrays.asList(expected).toString(), declaredMethods(DummySortWithNameAsc.class));
+ }
}
View
4 src/test/java/org/junit/tests/AllTests.java
@@ -2,6 +2,7 @@
import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
+import org.junit.internal.MethodSorterTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -158,7 +159,8 @@
BlockJUnit4ClassRunnerOverrideTest.class,
RuleFieldValidatorTest.class,
RuleChainTest.class,
- BlockJUnit4ClassRunnerTest.class
+ BlockJUnit4ClassRunnerTest.class,
+ MethodSorterTest.class
})
public class AllTests {
public static Test suite() {
Please sign in to comment.
Something went wrong with that request. Please try again.