From 8e80a2a7b89329f95cb41e8b2981044362478c04 Mon Sep 17 00:00:00 2001
From: Pete Bentley To use it, add the following to a test class:
+ *
* A final option is to do the same for a large array of test classes.
*
- * A good example of using assumptions is in Theories where they are needed to exclude certain datapoints that aren't suitable or allowed for a certain test case.
+ * A good example of using assumptions is in Theories where they are needed to exclude certain datapoints that aren't suitable or allowed for a certain test case.
* null
*/
- static public void assertNull(Object object) {
+ public static void assertNull(Object object) {
if (object != null) {
assertNull("Expected:
+ public static Test suite() {
+ return new JUnit4TestAdapter(YourJUnit4TestClass.class);
+ }
+
+ */
+public class JUnit4TestAdapter implements Test, Filterable, Orderable, Describable {
private final Class> fNewTestClass;
private final Runner fRunner;
@@ -83,4 +95,13 @@ public class JUnit4TestAdapter implements Test, Filterable, Sortable, Describabl
public void sort(Sorter sorter) {
sorter.apply(fRunner);
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 4.13
+ */
+ public void order(Orderer orderer) throws InvalidOrderingException {
+ orderer.apply(fRunner);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/junit/framework/Protectable.java b/src/main/java/junit/framework/Protectable.java
index 9f30b10..c5ceb16 100644
--- a/src/main/java/junit/framework/Protectable.java
+++ b/src/main/java/junit/framework/Protectable.java
@@ -8,7 +8,7 @@ package junit.framework;
public interface Protectable {
/**
- * Run the the following method protected.
+ * Run the following method protected.
*/
public abstract void protect() throws Throwable;
-}
\ No newline at end of file
+}
diff --git a/src/main/java/junit/framework/TestCase.java b/src/main/java/junit/framework/TestCase.java
index b89ce71..e474a64 100644
--- a/src/main/java/junit/framework/TestCase.java
+++ b/src/main/java/junit/framework/TestCase.java
@@ -73,6 +73,7 @@ import java.lang.reflect.Modifier;
* @see TestResult
* @see TestSuite
*/
+@SuppressWarnings("deprecation")
public abstract class TestCase extends Assert implements Test {
/**
* the name of the test case
@@ -102,7 +103,7 @@ public abstract class TestCase extends Assert implements Test {
}
/**
- * Creates a default TestResult object
+ * Creates a default TestResult object.
*
* @see TestResult
*/
@@ -187,7 +188,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that a condition is true. If it isn't it throws
* an AssertionFailedError with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertTrue(String message, boolean condition) {
Assert.assertTrue(message, condition);
}
@@ -196,7 +196,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that a condition is true. If it isn't it throws
* an AssertionFailedError.
*/
- @SuppressWarnings("deprecation")
public static void assertTrue(boolean condition) {
Assert.assertTrue(condition);
}
@@ -205,7 +204,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that a condition is false. If it isn't it throws
* an AssertionFailedError with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertFalse(String message, boolean condition) {
Assert.assertFalse(message, condition);
}
@@ -214,7 +212,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that a condition is false. If it isn't it throws
* an AssertionFailedError.
*/
- @SuppressWarnings("deprecation")
public static void assertFalse(boolean condition) {
Assert.assertFalse(condition);
}
@@ -222,7 +219,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Fails a test with the given message.
*/
- @SuppressWarnings("deprecation")
public static void fail(String message) {
Assert.fail(message);
}
@@ -230,7 +226,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Fails a test with no message.
*/
- @SuppressWarnings("deprecation")
public static void fail() {
Assert.fail();
}
@@ -239,7 +234,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two objects are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, Object expected, Object actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -248,7 +242,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two objects are equal. If they are not
* an AssertionFailedError is thrown.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(Object expected, Object actual) {
Assert.assertEquals(expected, actual);
}
@@ -256,7 +249,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two Strings are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, String expected, String actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -264,7 +256,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two Strings are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String expected, String actual) {
Assert.assertEquals(expected, actual);
}
@@ -274,7 +265,6 @@ public abstract class TestCase extends Assert implements Test {
* an AssertionFailedError is thrown with the given message. If the expected
* value is infinity then the delta value is ignored.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, double expected, double actual, double delta) {
Assert.assertEquals(message, expected, actual, delta);
}
@@ -283,7 +273,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two doubles are equal concerning a delta. If the expected
* value is infinity then the delta value is ignored.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(double expected, double actual, double delta) {
Assert.assertEquals(expected, actual, delta);
}
@@ -293,7 +282,6 @@ public abstract class TestCase extends Assert implements Test {
* are not an AssertionFailedError is thrown with the given message. If the
* expected value is infinity then the delta value is ignored.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, float expected, float actual, float delta) {
Assert.assertEquals(message, expected, actual, delta);
}
@@ -302,7 +290,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two floats are equal concerning a delta. If the expected
* value is infinity then the delta value is ignored.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(float expected, float actual, float delta) {
Assert.assertEquals(expected, actual, delta);
}
@@ -311,7 +298,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two longs are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, long expected, long actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -319,7 +305,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two longs are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(long expected, long actual) {
Assert.assertEquals(expected, actual);
}
@@ -328,7 +313,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two booleans are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, boolean expected, boolean actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -336,7 +320,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two booleans are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(boolean expected, boolean actual) {
Assert.assertEquals(expected, actual);
}
@@ -345,7 +328,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two bytes are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, byte expected, byte actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -353,7 +335,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two bytes are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(byte expected, byte actual) {
Assert.assertEquals(expected, actual);
}
@@ -362,7 +343,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two chars are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, char expected, char actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -370,7 +350,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two chars are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(char expected, char actual) {
Assert.assertEquals(expected, actual);
}
@@ -379,7 +358,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two shorts are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, short expected, short actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -387,7 +365,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two shorts are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(short expected, short actual) {
Assert.assertEquals(expected, actual);
}
@@ -396,7 +373,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two ints are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(String message, int expected, int actual) {
Assert.assertEquals(message, expected, actual);
}
@@ -404,7 +380,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that two ints are equal.
*/
- @SuppressWarnings("deprecation")
public static void assertEquals(int expected, int actual) {
Assert.assertEquals(expected, actual);
}
@@ -412,7 +387,6 @@ public abstract class TestCase extends Assert implements Test {
/**
* Asserts that an object isn't null.
*/
- @SuppressWarnings("deprecation")
public static void assertNotNull(Object object) {
Assert.assertNotNull(object);
}
@@ -421,7 +395,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that an object isn't null. If it is
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertNotNull(String message, Object object) {
Assert.assertNotNull(message, object);
}
@@ -433,7 +406,6 @@ public abstract class TestCase extends Assert implements Test {
*
* @param object Object to check or null
*/
- @SuppressWarnings("deprecation")
public static void assertNull(Object object) {
Assert.assertNull(object);
}
@@ -442,7 +414,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that an object is null. If it is not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertNull(String message, Object object) {
Assert.assertNull(message, object);
}
@@ -451,7 +422,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two objects refer to the same object. If they are not
* an AssertionFailedError is thrown with the given message.
*/
- @SuppressWarnings("deprecation")
public static void assertSame(String message, Object expected, Object actual) {
Assert.assertSame(message, expected, actual);
}
@@ -460,7 +430,6 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two objects refer to the same object. If they are not
* the same an AssertionFailedError is thrown.
*/
- @SuppressWarnings("deprecation")
public static void assertSame(Object expected, Object actual) {
Assert.assertSame(expected, actual);
}
@@ -470,7 +439,6 @@ public abstract class TestCase extends Assert implements Test {
* refer to the same object an AssertionFailedError is thrown with the
* given message.
*/
- @SuppressWarnings("deprecation")
public static void assertNotSame(String message, Object expected, Object actual) {
Assert.assertNotSame(message, expected, actual);
}
@@ -479,27 +447,22 @@ public abstract class TestCase extends Assert implements Test {
* Asserts that two objects do not refer to the same object. If they do
* refer to the same object an AssertionFailedError is thrown.
*/
- @SuppressWarnings("deprecation")
public static void assertNotSame(Object expected, Object actual) {
Assert.assertNotSame(expected, actual);
}
- @SuppressWarnings("deprecation")
public static void failSame(String message) {
Assert.failSame(message);
}
- @SuppressWarnings("deprecation")
public static void failNotSame(String message, Object expected, Object actual) {
Assert.failNotSame(message, expected, actual);
}
- @SuppressWarnings("deprecation")
public static void failNotEquals(String message, Object expected, Object actual) {
Assert.failNotEquals(message, expected, actual);
}
- @SuppressWarnings("deprecation")
public static String format(String message, Object expected, Object actual) {
return Assert.format(message, expected, actual);
}
@@ -519,7 +482,7 @@ public abstract class TestCase extends Assert implements Test {
}
/**
- * Returns a string representation of the test case
+ * Returns a string representation of the test case.
*/
@Override
public String toString() {
@@ -527,7 +490,7 @@ public abstract class TestCase extends Assert implements Test {
}
/**
- * Gets the name of a TestCase
+ * Gets the name of a TestCase.
*
* @return the name of the TestCase
*/
@@ -536,7 +499,7 @@ public abstract class TestCase extends Assert implements Test {
}
/**
- * Sets the name of a TestCase
+ * Sets the name of a TestCase.
*
* @param name the name to set
*/
diff --git a/src/main/java/junit/framework/TestFailure.java b/src/main/java/junit/framework/TestFailure.java
index 6168b58..d1ddfbc 100644
--- a/src/main/java/junit/framework/TestFailure.java
+++ b/src/main/java/junit/framework/TestFailure.java
@@ -1,7 +1,6 @@
package junit.framework;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import org.junit.internal.Throwables;
/**
@@ -49,10 +48,7 @@ public class TestFailure {
* thrown by TestFailure.
*/
public String trace() {
- StringWriter stringWriter = new StringWriter();
- PrintWriter writer = new PrintWriter(stringWriter);
- thrownException().printStackTrace(writer);
- return stringWriter.toString();
+ return Throwables.getStacktrace(thrownException());
}
/**
diff --git a/src/main/java/junit/framework/TestResult.java b/src/main/java/junit/framework/TestResult.java
index 8332542..e01a2b0 100644
--- a/src/main/java/junit/framework/TestResult.java
+++ b/src/main/java/junit/framework/TestResult.java
@@ -52,14 +52,14 @@ public class TestResult {
}
/**
- * Registers a TestListener
+ * Registers a TestListener.
*/
public synchronized void addListener(TestListener listener) {
fListeners.add(listener);
}
/**
- * Unregisters a TestListener
+ * Unregisters a TestListener.
*/
public synchronized void removeListener(TestListener listener) {
fListeners.remove(listener);
@@ -91,7 +91,7 @@ public class TestResult {
}
/**
- * Returns an Enumeration for the errors
+ * Returns an Enumeration for the errors.
*/
public synchronized EnumerationTestSuite
is a Composite
of Tests.
@@ -35,7 +34,7 @@ import org.junit.internal.MethodSorter;
*
- * Class[] testClasses = { MathTest.class, AnotherTest.class }
+ * Class[] testClasses = { MathTest.class, AnotherTest.class };
* TestSuite suite= new TestSuite(testClasses);
*
*
@@ -65,11 +64,11 @@ public class TestSuite implements Test {
test = constructor.newInstance(new Object[]{name});
}
} catch (InstantiationException e) {
- return (warning("Cannot instantiate test case: " + name + " (" + exceptionToString(e) + ")"));
+ return (warning("Cannot instantiate test case: " + name + " (" + Throwables.getStacktrace(e) + ")"));
} catch (InvocationTargetException e) {
- return (warning("Exception in constructor: " + name + " (" + exceptionToString(e.getTargetException()) + ")"));
+ return (warning("Exception in constructor: " + name + " (" + Throwables.getStacktrace(e.getTargetException()) + ")"));
} catch (IllegalAccessException e) {
- return (warning("Cannot access test case: " + name + " (" + exceptionToString(e) + ")"));
+ return (warning("Cannot access test case: " + name + " (" + Throwables.getStacktrace(e) + ")"));
}
return (Test) test;
}
@@ -99,16 +98,6 @@ public class TestSuite implements Test {
};
}
- /**
- * Converts the stack trace into a string
- */
- private static String exceptionToString(Throwable e) {
- StringWriter stringWriter = new StringWriter();
- PrintWriter writer = new PrintWriter(stringWriter);
- e.printStackTrace(writer);
- return stringWriter.toString();
- }
-
private String fName;
private Vectorexpected
*/
- static public void assertEquals(Object expected, Object actual) {
+ public static void assertEquals(Object expected, Object actual) {
assertEquals(null, expected, actual);
}
@@ -155,7 +157,7 @@ public class Assert {
* @param unexpected unexpected value to check
* @param actual the value to check against unexpected
*/
- static public void assertNotEquals(String message, Object unexpected,
+ public static void assertNotEquals(String message, Object unexpected,
Object actual) {
if (equalsRegardingNull(unexpected, actual)) {
failEquals(message, actual);
@@ -171,7 +173,7 @@ public class Assert {
* @param unexpected unexpected value to check
* @param actual the value to check against unexpected
*/
- static public void assertNotEquals(Object unexpected, Object actual) {
+ public static void assertNotEquals(Object unexpected, Object actual) {
assertNotEquals(null, unexpected, actual);
}
@@ -194,7 +196,7 @@ public class Assert {
* @param unexpected unexpected value to check
* @param actual the value to check against unexpected
*/
- static public void assertNotEquals(String message, long unexpected, long actual) {
+ public static void assertNotEquals(String message, long unexpected, long actual) {
if (unexpected == actual) {
failEquals(message, Long.valueOf(actual));
}
@@ -207,7 +209,7 @@ public class Assert {
* @param unexpected unexpected value to check
* @param actual the value to check against unexpected
*/
- static public void assertNotEquals(long unexpected, long actual) {
+ public static void assertNotEquals(long unexpected, long actual) {
assertNotEquals(null, unexpected, actual);
}
@@ -226,7 +228,7 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
- static public void assertNotEquals(String message, double unexpected,
+ public static void assertNotEquals(String message, double unexpected,
double actual, double delta) {
if (!doubleIsDifferent(unexpected, actual, delta)) {
failEquals(message, Double.valueOf(actual));
@@ -245,7 +247,7 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
- static public void assertNotEquals(double unexpected, double actual, double delta) {
+ public static void assertNotEquals(double unexpected, double actual, double delta) {
assertNotEquals(null, unexpected, actual, delta);
}
@@ -261,7 +263,7 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
- static public void assertNotEquals(float unexpected, float actual, float delta) {
+ public static void assertNotEquals(float unexpected, float actual, float delta) {
assertNotEquals(null, unexpected, actual, delta);
}
@@ -297,7 +299,7 @@ public class Assert {
public static void assertArrayEquals(Object[] expecteds, Object[] actuals) {
assertArrayEquals(null, expecteds, actuals);
}
-
+
/**
* Asserts that two boolean arrays are equal. If they are not, an
* {@link AssertionError} is thrown with the given message. If
@@ -312,8 +314,8 @@ public class Assert {
public static void assertArrayEquals(String message, boolean[] expecteds,
boolean[] actuals) throws ArrayComparisonFailure {
internalArrayEquals(message, expecteds, actuals);
- }
-
+ }
+
/**
* Asserts that two boolean arrays are equal. If they are not, an
* {@link AssertionError} is thrown. If expected
and
@@ -547,7 +549,7 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
- static public void assertEquals(String message, double expected,
+ public static void assertEquals(String message, double expected,
double actual, double delta) {
if (doubleIsDifferent(expected, actual, delta)) {
failNotEquals(message, Double.valueOf(expected), Double.valueOf(actual));
@@ -569,7 +571,7 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
- static public void assertEquals(String message, float expected,
+ public static void assertEquals(String message, float expected,
float actual, float delta) {
if (floatIsDifferent(expected, actual, delta)) {
failNotEquals(message, Float.valueOf(expected), Float.valueOf(actual));
@@ -591,14 +593,14 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
- static public void assertNotEquals(String message, float unexpected,
+ public static void assertNotEquals(String message, float unexpected,
float actual, float delta) {
if (!floatIsDifferent(unexpected, actual, delta)) {
failEquals(message, Float.valueOf(actual));
}
}
- static private boolean doubleIsDifferent(double d1, double d2, double delta) {
+ private static boolean doubleIsDifferent(double d1, double d2, double delta) {
if (Double.compare(d1, d2) == 0) {
return false;
}
@@ -609,7 +611,7 @@ public class Assert {
return true;
}
- static private boolean floatIsDifferent(float f1, float f2, float delta) {
+ private static boolean floatIsDifferent(float f1, float f2, float delta) {
if (Float.compare(f1, f2) == 0) {
return false;
}
@@ -627,7 +629,7 @@ public class Assert {
* @param expected expected long value.
* @param actual actual long value
*/
- static public void assertEquals(long expected, long actual) {
+ public static void assertEquals(long expected, long actual) {
assertEquals(null, expected, actual);
}
@@ -640,7 +642,7 @@ public class Assert {
* @param expected long expected value.
* @param actual long actual value
*/
- static public void assertEquals(String message, long expected, long actual) {
+ public static void assertEquals(String message, long expected, long actual) {
if (expected != actual) {
failNotEquals(message, Long.valueOf(expected), Long.valueOf(actual));
}
@@ -652,7 +654,7 @@ public class Assert {
* instead
*/
@Deprecated
- static public void assertEquals(double expected, double actual) {
+ public static void assertEquals(double expected, double actual) {
assertEquals(null, expected, actual);
}
@@ -662,7 +664,7 @@ public class Assert {
* instead
*/
@Deprecated
- static public void assertEquals(String message, double expected,
+ public static void assertEquals(String message, double expected,
double actual) {
fail("Use assertEquals(expected, actual, delta) to compare floating-point numbers");
}
@@ -679,7 +681,7 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
- static public void assertEquals(double expected, double actual, double delta) {
+ public static void assertEquals(double expected, double actual, double delta) {
assertEquals(null, expected, actual, delta);
}
@@ -695,8 +697,7 @@ public class Assert {
* actual
for which both numbers are still
* considered equal.
*/
-
- static public void assertEquals(float expected, float actual, float delta) {
+ public static void assertEquals(float expected, float actual, float delta) {
assertEquals(null, expected, actual, delta);
}
@@ -708,7 +709,7 @@ public class Assert {
* okay)
* @param object Object to check or null
*/
- static public void assertNotNull(String message, Object object) {
+ public static void assertNotNull(String message, Object object) {
assertTrue(message, object != null);
}
@@ -718,7 +719,7 @@ public class Assert {
*
* @param object Object to check or null
*/
- static public void assertNotNull(Object object) {
+ public static void assertNotNull(Object object) {
assertNotNull(null, object);
}
@@ -730,7 +731,7 @@ public class Assert {
* okay)
* @param object Object to check or null
*/
- static public void assertNull(String message, Object object) {
+ public static void assertNull(String message, Object object) {
if (object == null) {
return;
}
@@ -743,11 +744,11 @@ public class Assert {
*
* @param object Object to check or null
*/
- static public void assertNull(Object object) {
+ public static void assertNull(Object object) {
assertNull(null, object);
}
- static private void failNotNull(String message, Object actual) {
+ private static void failNotNull(String message, Object actual) {
String formatted = "";
if (message != null) {
formatted = message + " ";
@@ -764,7 +765,7 @@ public class Assert {
* @param expected the expected object
* @param actual the object to compare to expected
*/
- static public void assertSame(String message, Object expected, Object actual) {
+ public static void assertSame(String message, Object expected, Object actual) {
if (expected == actual) {
return;
}
@@ -778,7 +779,7 @@ public class Assert {
* @param expected the expected object
* @param actual the object to compare to expected
*/
- static public void assertSame(Object expected, Object actual) {
+ public static void assertSame(Object expected, Object actual) {
assertSame(null, expected, actual);
}
@@ -792,7 +793,7 @@ public class Assert {
* @param unexpected the object you don't expect
* @param actual the object to compare to unexpected
*/
- static public void assertNotSame(String message, Object unexpected,
+ public static void assertNotSame(String message, Object unexpected,
Object actual) {
if (unexpected == actual) {
failSame(message);
@@ -807,11 +808,11 @@ public class Assert {
* @param unexpected the object you don't expect
* @param actual the object to compare to unexpected
*/
- static public void assertNotSame(Object unexpected, Object actual) {
+ public static void assertNotSame(Object unexpected, Object actual) {
assertNotSame(null, unexpected, actual);
}
- static private void failSame(String message) {
+ private static void failSame(String message) {
String formatted = "";
if (message != null) {
formatted = message + " ";
@@ -819,7 +820,7 @@ public class Assert {
fail(formatted + "expected not same");
}
- static private void failNotSame(String message, Object expected,
+ private static void failNotSame(String message, Object expected,
Object actual) {
String formatted = "";
if (message != null) {
@@ -829,19 +830,19 @@ public class Assert {
+ ">");
}
- static private void failNotEquals(String message, Object expected,
+ private static void failNotEquals(String message, Object expected,
Object actual) {
fail(format(message, expected, actual));
}
static String format(String message, Object expected, Object actual) {
String formatted = "";
- if (message != null && !message.equals("")) {
+ if (message != null && !"".equals(message)) {
formatted = message + " ";
}
String expectedString = String.valueOf(expected);
String actualString = String.valueOf(actual);
- if (expectedString.equals(actualString)) {
+ if (equalsRegardingNull(expectedString, actualString)) {
return formatted + "expected: "
+ formatClassAndValue(expected, expectedString)
+ " but was: " + formatClassAndValue(actual, actualString);
@@ -851,6 +852,11 @@ public class Assert {
}
}
+ private static String formatClass(Class> value) {
+ String className = value.getCanonicalName();
+ return className == null ? value.getName() : className;
+ }
+
private static String formatClassAndValue(Object value, String valueString) {
String className = value == null ? "null" : value.getClass().getName();
return className + "<" + valueString + ">";
@@ -917,8 +923,9 @@ public class Assert {
* @param matcher an expression, built of {@link Matcher}s, specifying allowed
* values
* @see org.hamcrest.CoreMatchers
- * @see org.hamcrest.MatcherAssert
+ * @deprecated use {@code org.hamcrest.MatcherAssert.assertThat()}
*/
+ @Deprecated
public static null
+ * okay)
+ * @param expectedThrowable the expected type of the exception
+ * @param runnable a function that is expected to throw an exception when executed
+ * @return the exception thrown by {@code runnable}
+ * @since 4.13
+ */
+ public static
objects
, the test will halt and be ignored.
+ * If called with a {@code null} array or one or more {@code null} elements in {@code objects},
+ * the test will halt and be ignored.
*/
public static void assumeNotNull(Object... objects) {
+ assumeThat(objects, notNullValue());
assumeThat(asList(objects), everyItem(notNullValue()));
}
diff --git a/src/main/java/org/junit/AssumptionViolatedException.java b/src/main/java/org/junit/AssumptionViolatedException.java
index e48ddf0..1d62190 100644
--- a/src/main/java/org/junit/AssumptionViolatedException.java
+++ b/src/main/java/org/junit/AssumptionViolatedException.java
@@ -40,7 +40,7 @@ public class AssumptionViolatedException extends org.junit.internal.AssumptionVi
/**
* An assumption exception with the given message and a cause.
*/
- public AssumptionViolatedException(String assumption, Throwable t) {
- super(assumption, t);
+ public AssumptionViolatedException(String message, Throwable t) {
+ super(message, t);
}
}
diff --git a/src/main/java/org/junit/ClassRule.java b/src/main/java/org/junit/ClassRule.java
index 02c40a7..94ee29f 100644
--- a/src/main/java/org/junit/ClassRule.java
+++ b/src/main/java/org/junit/ClassRule.java
@@ -28,7 +28,10 @@ import java.lang.annotation.Target;
* annotated {@link ClassRule}s on a class, they will be applied in an order
* that depends on your JVM's implementation of the reflection API, which is
* undefined, in general. However, Rules defined by fields will always be applied
- * before Rules defined by methods.
+ * after Rules defined by methods, i.e. the Statements returned by the former will
+ * be executed around those returned by the latter.
+ *
+ * * For example, here is a test suite that connects to a server once before * all the test classes run, and disconnects after they are finished: @@ -79,9 +82,37 @@ import java.lang.annotation.Target; *
* For more information and more examples, see {@link org.junit.rules.TestRule}. * + *
+ * You can use {@link #order()} if you want to have control over the order in + * which the Rules are applied. + * + *
+ * public class ThreeClassRules { + * @ClassRule(order = 0) + * public static LoggingRule outer = new LoggingRule("outer rule"); + * + * @ClassRule(order = 1) + * public static LoggingRule middle = new LoggingRule("middle rule"); + * + * @ClassRule(order = 2) + * public static LoggingRule inner = new LoggingRule("inner rule"); + * + * // ... + * } + *+ * * @since 4.9 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface ClassRule { + + /** + * Specifies the order in which rules are applied. The rules with a higher value are inner. + * + * @since 4.13 + */ + int order() default Rule.DEFAULT_ORDER; + } diff --git a/src/main/java/org/junit/ComparisonFailure.java b/src/main/java/org/junit/ComparisonFailure.java index 9563e61..d1daa86 100644 --- a/src/main/java/org/junit/ComparisonFailure.java +++ b/src/main/java/org/junit/ComparisonFailure.java @@ -21,7 +21,7 @@ public class ComparisonFailure extends AssertionError { /* * We have to use the f prefix until the next major release to ensure * serialization compatibility. - * See https://github.com/junit-team/junit/issues/976 + * See https://github.com/junit-team/junit4/issues/976 */ private String fExpected; private String fActual; diff --git a/src/main/java/org/junit/Rule.java b/src/main/java/org/junit/Rule.java index 711235c..9370e94 100644 --- a/src/main/java/org/junit/Rule.java +++ b/src/main/java/org/junit/Rule.java @@ -16,12 +16,14 @@ import java.lang.annotation.Target; * to the {@link org.junit.rules.TestRule} will run any {@link Before} methods, * then the {@link Test} method, and finally any {@link After} methods, * throwing an exception if any of these fail. If there are multiple - * annotated {@link Rule}s on a class, they will be applied in order of fields first, then methods. + * annotated {@link Rule}s on a class, they will be applied in order of methods first, then fields. * However, if there are multiple fields (or methods) they will be applied in an order * that depends on your JVM's implementation of the reflection API, which is * undefined, in general. Rules defined by fields will always be applied - * before Rules defined by methods. You can use a {@link org.junit.rules.RuleChain} if you want - * to have control over the order in which the Rules are applied. + * after Rules defined by methods, i.e. the Statements returned by the former will + * be executed around those returned by the latter. + * + *
* For example, here is a test class that creates a temporary folder before * each test method, and deletes it after each: @@ -61,10 +63,39 @@ import java.lang.annotation.Target; * For more information and more examples, see * {@link org.junit.rules.TestRule}. * + *
+ * You can use {@link #order()} if you want to have control over the order in + * which the Rules are applied. + * + *
+ * public class ThreeRules { + * @Rule(order = 0) + * public LoggingRule outer = new LoggingRule("outer rule"); + * + * @Rule(order = 1) + * public LoggingRule middle = new LoggingRule("middle rule"); + * + * @Rule(order = 2) + * public LoggingRule inner = new LoggingRule("inner rule"); + * + * // ... + * } + *+ * * @since 4.7 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface Rule { -} \ No newline at end of file + int DEFAULT_ORDER = -1; + + /** + * Specifies the order in which rules are applied. The rules with a higher value are inner. + * + * @since 4.13 + */ + int order() default DEFAULT_ORDER; + +} diff --git a/src/main/java/org/junit/Test.java b/src/main/java/org/junit/Test.java index 71ac428..1db6fc7 100644 --- a/src/main/java/org/junit/Test.java +++ b/src/main/java/org/junit/Test.java @@ -1,5 +1,7 @@ package org.junit; +import org.junit.function.ThrowingRunnable; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -23,24 +25,40 @@ import java.lang.annotation.Target; * } * *
- * The Test
annotation supports two optional parameters.
- * The first, expected
, declares that a test method should throw
+ * The Test
annotation supports two optional parameters for
+ * exception testing and for limiting test execution time.
+ *
+ *
+ * The parameter expected
declares that a test method should throw
* an exception. If it doesn't throw an exception or if it throws a different exception
* than the one declared, the test fails. For example, the following test succeeds:
*
- * @Test(expected=IndexOutOfBoundsException.class) public void outOfBounds() { + * @Test(expected=IndexOutOfBoundsException.class) + * public void outOfBounds() { * new ArrayList<Object>().get(1); * } *- * If the exception's message or one of its properties should be verified, the - * {@link org.junit.rules.ExpectedException ExpectedException} rule can be used. Further + * + * Using the parameter
expected
for exception testing comes with
+ * some limitations: only the exception's type can be checked and it is not
+ * possible to precisely specify the code that throws the exception. Therefore
+ * JUnit 4 has improved its support for exception testing with
+ * {@link Assert#assertThrows(Class, ThrowingRunnable)} and the
+ * {@link org.junit.rules.ExpectedException ExpectedException} rule.
+ * With assertThrows
the code that throws the exception can be
+ * precisely specified. If the exception's message or one of its properties
+ * should be verified, the ExpectedException
rule can be used. Further
* information about exception testing can be found at the
- * JUnit Wiki.
+ * JUnit Wiki.
+ *
+ *
- * The second optional parameter, timeout
, causes a test to fail if it takes
+ * The parameter timeout
causes a test to fail if it takes
* longer than a specified amount of clock time (measured in milliseconds). The following test fails:
*
- * @Test(timeout=100) public void infinity() { + * @Test(timeout=100) + * public void infinity() { * while(true); * } *@@ -49,7 +67,8 @@ import java.lang.annotation.Target; * following test may or may not fail depending on how the operating system * schedules threads: *
- * @Test(timeout=100) public void sleep100() { + * @Test(timeout=100) + * public void sleep100() { * Thread.sleep(100); * } *@@ -66,7 +85,7 @@ import java.lang.annotation.Target; public @interface Test { /** - * Default empty exception + * Default empty exception. */ static class None extends Throwable { private static final long serialVersionUID = 1L; diff --git a/src/main/java/org/junit/TestCouldNotBeSkippedException.java b/src/main/java/org/junit/TestCouldNotBeSkippedException.java new file mode 100644 index 0000000..4804493 --- /dev/null +++ b/src/main/java/org/junit/TestCouldNotBeSkippedException.java @@ -0,0 +1,19 @@ +package org.junit; + +/** + * Indicates that a test that indicated that it should be skipped could not be skipped. + * This can be thrown if a test uses the methods in {@link Assume} to indicate that + * it should be skipped, but before processing of the test was completed, other failures + * occured. + * + * @see org.junit.Assume + * @since 4.13 + */ +public class TestCouldNotBeSkippedException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** Creates an instance using the given assumption failure. */ + public TestCouldNotBeSkippedException(org.junit.internal.AssumptionViolatedException cause) { + super("Test could not be skipped due to other failures", cause); + } +} diff --git a/src/main/java/org/junit/experimental/categories/Categories.java b/src/main/java/org/junit/experimental/categories/Categories.java index 290c180..0c73ed8 100644 --- a/src/main/java/org/junit/experimental/categories/Categories.java +++ b/src/main/java/org/junit/experimental/categories/Categories.java @@ -2,8 +2,10 @@ package org.junit.experimental.categories; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import org.junit.runner.Description; @@ -76,7 +78,7 @@ import org.junit.runners.model.RunnerBuilder; * * * @version 4.12 - * @see Categories at JUnit wiki + * @see Categories at JUnit wiki */ public class Categories extends Suite { @@ -86,13 +88,13 @@ public class Categories extends Suite { * Determines the tests to run that are annotated with categories specified in * the value of this annotation or their subtypes unless excluded with {@link ExcludeCategory}. */ - public Class>[] value() default {}; + Class>[] value() default {}; /** * If true, runs tests annotated with any of the categories in * {@link IncludeCategory#value()}. Otherwise, runs tests only if annotated with all of the categories. */ - public boolean matchAny() default true; + boolean matchAny() default true; } @Retention(RetentionPolicy.RUNTIME) @@ -101,13 +103,13 @@ public class Categories extends Suite { * Determines the tests which do not run if they are annotated with categories specified in the * value of this annotation or their subtypes regardless of being included in {@link IncludeCategory#value()}. */ - public Class>[] value() default {}; + Class>[] value() default {}; /** * If true, the tests annotated with any of the categories in {@link ExcludeCategory#value()} * do not run. Otherwise, the tests do not run if and only if annotated with all categories. */ - public boolean matchAny() default true; + boolean matchAny() default true; } public static class CategoryFilter extends Filter { @@ -117,10 +119,7 @@ public class Categories extends Suite { private final boolean excludedAny; public static CategoryFilter include(boolean matchAny, Class>... categories) { - if (hasNull(categories)) { - throw new NullPointerException("has null category"); - } - return categoryFilter(matchAny, createSet(categories), true, null); + return new CategoryFilter(matchAny, categories, true, null); } public static CategoryFilter include(Class> category) { @@ -132,10 +131,7 @@ public class Categories extends Suite { } public static CategoryFilter exclude(boolean matchAny, Class>... categories) { - if (hasNull(categories)) { - throw new NullPointerException("has null category"); - } - return categoryFilter(true, null, matchAny, createSet(categories)); + return new CategoryFilter(true, null, matchAny, categories); } public static CategoryFilter exclude(Class> category) { @@ -151,14 +147,30 @@ public class Categories extends Suite { return new CategoryFilter(matchAnyInclusions, inclusions, matchAnyExclusions, exclusions); } + @Deprecated + public CategoryFilter(Class> includedCategory, Class> excludedCategory) { + includedAny = true; + excludedAny = true; + included = nullableClassToSet(includedCategory); + excluded = nullableClassToSet(excludedCategory); + } + protected CategoryFilter(boolean matchAnyIncludes, Set
diff --git a/src/main/java/org/junit/experimental/theories/Theories.java b/src/main/java/org/junit/experimental/theories/Theories.java index 817f553..ac88a36 100644 --- a/src/main/java/org/junit/experimental/theories/Theories.java +++ b/src/main/java/org/junit/experimental/theories/Theories.java @@ -51,11 +51,11 @@ import org.junit.runners.model.TestClass; * } * } *- * This makes it clear that the user's filename should be included in the config file name, + * This makes it clear that the username should be included in the config file name, * only if it doesn't contain a slash. Another test or theory might define what happens when a username does contain * a slash.
UserTest
will attempt to run filenameIncludesUsername
on every compatible data
* point defined in the class. If any of the assumptions fail, the data point is silently ignored. If all of the
- * assumptions pass, but an assertion fails, the test fails.
+ * assumptions pass, but an assertion fails, the test fails. If no parameters can be found that satisfy all assumptions, the test fails.
*
* Defining general statements as theories allows data point reuse across a bunch of functionality tests and also
* allows automated tools to search for new, unexpected data points that expose bugs.
@@ -73,6 +73,11 @@ public class Theories extends BlockJUnit4ClassRunner {
super(klass);
}
+ /** @since 4.13 */
+ protected Theories(TestClass testClass) throws InitializationError {
+ super(testClass);
+ }
+
@Override
protected void collectInitializationErrors(List Always returns an empty list.
+ */
+ public List Always throws an {@link UnsupportedOperationException}
+ */
+ public long getThreadCpuTime(long id) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Always returns false.
+ */
+ public boolean isThreadCpuTimeSupported() {
+ return false;
+ }
+
+}
+
diff --git a/src/main/java/org/junit/internal/management/ManagementFactory.java b/src/main/java/org/junit/internal/management/ManagementFactory.java
new file mode 100644
index 0000000..5be1447
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ManagementFactory.java
@@ -0,0 +1,77 @@
+package org.junit.internal.management;
+
+import org.junit.internal.Classes;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Reflective wrapper around {@link java.lang.management.ManagementFactory}
+ */
+public class ManagementFactory {
+ private static final class FactoryHolder {
+ private static final Class> MANAGEMENT_FACTORY_CLASS;
+
+ static {
+ Class> managementFactoryClass = null;
+ try {
+ managementFactoryClass = Classes.getClass("java.lang.management.ManagementFactory");
+ } catch (ClassNotFoundException e) {
+ // do nothing, managementFactoryClass will be none on failure
+ }
+ MANAGEMENT_FACTORY_CLASS = managementFactoryClass;
+ }
+
+ static Object getBeanObject(String methodName) {
+ if (MANAGEMENT_FACTORY_CLASS != null) {
+ try {
+ return MANAGEMENT_FACTORY_CLASS.getMethod(methodName).invoke(null);
+ } catch (IllegalAccessException e) {
+ // fallthrough
+ } catch (IllegalArgumentException e) {
+ // fallthrough
+ } catch (InvocationTargetException e) {
+ // fallthrough
+ } catch (NoSuchMethodException e) {
+ // fallthrough
+ } catch (SecurityException e) {
+ // fallthrough
+ }
+ }
+ return null;
+ }
+ }
+
+ private static final class RuntimeHolder {
+ private static final RuntimeMXBean RUNTIME_MX_BEAN =
+ getBean(FactoryHolder.getBeanObject("getRuntimeMXBean"));
+
+ private static final RuntimeMXBean getBean(Object runtimeMxBean) {
+ return runtimeMxBean != null
+ ? new ReflectiveRuntimeMXBean(runtimeMxBean) : new FakeRuntimeMXBean();
+ }
+ }
+
+ private static final class ThreadHolder {
+ private static final ThreadMXBean THREAD_MX_BEAN =
+ getBean(FactoryHolder.getBeanObject("getThreadMXBean"));
+
+ private static final ThreadMXBean getBean(Object threadMxBean) {
+ return threadMxBean != null
+ ? new ReflectiveThreadMXBean(threadMxBean) : new FakeThreadMXBean();
+ }
+ }
+
+ /**
+ * @see java.lang.management.ManagementFactory#getRuntimeMXBean()
+ */
+ public static RuntimeMXBean getRuntimeMXBean() {
+ return RuntimeHolder.RUNTIME_MX_BEAN;
+ }
+
+ /**
+ * @see java.lang.management.ManagementFactory#getThreadMXBean()
+ */
+ public static ThreadMXBean getThreadMXBean() {
+ return ThreadHolder.THREAD_MX_BEAN;
+ }
+}
diff --git a/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java b/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java
new file mode 100644
index 0000000..289587a
--- /dev/null
+++ b/src/main/java/org/junit/internal/management/ReflectiveRuntimeMXBean.java
@@ -0,0 +1,61 @@
+package org.junit.internal.management;
+
+import org.junit.internal.Classes;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Implementation of {@link RuntimeMXBean} using the JVM reflectively.
+ */
+final class ReflectiveRuntimeMXBean implements RuntimeMXBean {
+ private final Object runtimeMxBean;
+
+ private static final class Holder {
+ private static final Method getInputArgumentsMethod;
+ static {
+ Method inputArguments = null;
+ try {
+ Class> threadMXBeanClass = Classes.getClass("java.lang.management.RuntimeMXBean");
+ inputArguments = threadMXBeanClass.getMethod("getInputArguments");
+ } catch (ClassNotFoundException e) {
+ // do nothing, input arguments will be null on failure
+ } catch (NoSuchMethodException e) {
+ // do nothing, input arguments will be null on failure
+ } catch (SecurityException e) {
+ // do nothing, input arguments will be null on failure
+ }
+ getInputArgumentsMethod = inputArguments;
+ }
+ }
+
+ ReflectiveRuntimeMXBean(Object runtimeMxBean) {
+ super();
+ this.runtimeMxBean = runtimeMxBean;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ public List
+ * The most illustrative use case is for tests that make use of the
+ * {@link Timeout} rule, when ran in debug mode the test may terminate on
+ * timeout abruptly during debugging. Developers may disable the timeout, or
+ * increase the timeout by making a code change on tests that need debugging and
+ * remember revert the change afterwards or rules such as {@link Timeout} that
+ * may be disabled during debugging may be wrapped in a {@code DisableOnDebug}.
+ *
+ * The important benefit of this feature is that you can disable such rules
+ * without any making any modifications to your test class to remove them during
+ * debugging.
+ *
+ * This does nothing to tackle timeouts or time sensitive code under test when
+ * debugging and may make this less useful in such circumstances.
+ *
+ * Example usage:
+ *
+ *
+ * Options specified in:
+ *
- * You have to add the {@code ExpectedException} rule to your test.
+ * You have to add the {@code ExpectedException} rule to your test.
* This doesn't affect your existing tests (see {@code throwsNothing()}).
- * After specifiying the type of the expected exception your test is
+ * After specifying the type of the expected exception your test is
* successful when such an exception is thrown and it fails if a
* different or no exception is thrown.
*
- *
- * Instead of specifying the exception's type you can characterize the
- * expected exception based on other criterias, too:
+ * This rule does not perform any special magic to make execution continue
+ * as if the exception had not been thrown. So it is nearly always a mistake
+ * for a test method to have statements after the one that is expected to
+ * throw the exception.
+ *
+ * Instead of specifying the exception's type you can characterize the
+ * expected exception based on other criteria, too:
*
*
- * You can combine any of the presented expect-methods. The test is
+ * You can combine any of the presented expect-methods. The test is
* successful if all specifications are met.
* It is recommended to set the {@link org.junit.Rule#order() order} of the
+ * {@code ExpectedException} to {@code Integer.MAX_VALUE} if it is used together
+ * with another rule that handles exceptions, e.g. {@link ErrorCollector}.
+ * Otherwise failing tests may be successful.
+ *
- * JUnit uses {@link AssumptionViolatedException}s for indicating that a test
+ * JUnit uses {@link AssumptionViolatedException}s for indicating that a test
* provides no useful information. (See {@link org.junit.Assume} for more
* information.) You have to call {@code assume} methods before you set
* expectations of the {@code ExpectedException} rule. In this case the rule
@@ -80,8 +87,7 @@ import org.junit.runners.model.Statement;
*
*
- * JUnit uses {@link AssertionError}s for indicating that a test is failing. You
+ * JUnit uses {@link AssertionError}s for indicating that a test is failing. You
* have to call {@code assert} methods before you set expectations of the
* {@code ExpectedException} rule, if they should be handled by the framework.
* E.g. the following test fails because of the {@code assertTrue} statement.
@@ -93,8 +99,7 @@ import org.junit.runners.model.Statement;
* }
*
*
- * By default missing exceptions are reported with an error message
+ * By default missing exceptions are reported with an error message
* like "Expected test to throw an instance of foo". You can configure a different
* message by means of {@link #reportMissingExceptionWithMessage(String)}. You
* can use a {@code %s} placeholder for the description of the expected
@@ -107,7 +112,13 @@ public class ExpectedException implements TestRule {
/**
* Returns a {@linkplain TestRule rule} that expects no exception to
* be thrown (identical to behavior without this rule).
+ *
+ * @deprecated Since 4.13
+ * {@link org.junit.Assert#assertThrows(Class, org.junit.function.ThrowingRunnable)
+ * Assert.assertThrows} can be used to verify that your code throws a specific
+ * exception.
*/
+ @Deprecated
public static ExpectedException none() {
return new ExpectedException();
}
@@ -222,10 +233,18 @@ public class ExpectedException implements TestRule {
* throw new IllegalArgumentException("What happened?", cause);
* }
*/
- public void expectCause(Matcher extends Throwable> expectedCause) {
+ public void expectCause(Matcher> expectedCause) {
expect(hasCause(expectedCause));
}
+ /**
+ * Check if any Exception is expected.
+ * @since 4.13
+ */
+ public final boolean isAnyExceptionExpected() {
+ return matcherBuilder.expectsThrowable();
+ }
+
private class ExpectedExceptionStatement extends Statement {
private final Statement next;
@@ -255,10 +274,6 @@ public class ExpectedException implements TestRule {
}
}
- private boolean isAnyExceptionExpected() {
- return matcherBuilder.expectsThrowable();
- }
-
private void failDueToMissingException() throws AssertionError {
fail(missingExceptionMessage());
}
diff --git a/src/main/java/org/junit/rules/ExternalResource.java b/src/main/java/org/junit/rules/ExternalResource.java
index 71ca287..71fc842 100644
--- a/src/main/java/org/junit/rules/ExternalResource.java
+++ b/src/main/java/org/junit/rules/ExternalResource.java
@@ -1,6 +1,10 @@
package org.junit.rules;
+import java.util.ArrayList;
+import java.util.List;
+
import org.junit.runner.Description;
+import org.junit.runners.model.MultipleFailureException;
import org.junit.runners.model.Statement;
/**
@@ -44,11 +48,20 @@ public abstract class ExternalResource implements TestRule {
@Override
public void evaluate() throws Throwable {
before();
+
+ List Note that {@link MethodRule} has been replaced by {@link TestRule},
* which has the added benefit of supporting class rules.
*
* @since 4.7
diff --git a/src/main/java/org/junit/rules/RuleChain.java b/src/main/java/org/junit/rules/RuleChain.java
index f43d8f5..bf93aae 100644
--- a/src/main/java/org/junit/rules/RuleChain.java
+++ b/src/main/java/org/junit/rules/RuleChain.java
@@ -4,26 +4,34 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.junit.Rule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
- * The RuleChain rule allows ordering of TestRules. You create a
+ * The {@code RuleChain} can be used for creating composite rules. You create a
* {@code RuleChain} with {@link #outerRule(TestRule)} and subsequent calls of
* {@link #around(TestRule)}:
*
* Example of usage:
* TemporaryFolder rule supports assured deletion mode, which
+ * will fail the test in case deletion fails with {@link AssertionError}.
+ *
+ * Creating TemporaryFolder with assured deletion:
+ * It is recommended to always set the {@link Rule#order() order} of the
+ * {@code TestWatcher} to {@code Integer.MIN_VALUE} so that it encloses all
+ * other rules. Otherwise it may see failed tests as successful and vice versa
+ * if some rule changes the result of a test (e.g. {@link ErrorCollector} or
+ * {@link ExpectedException}).
*
* @since 4.9
*/
@@ -54,7 +60,7 @@ public abstract class TestWatcher implements TestRule {
try {
base.evaluate();
succeededQuietly(description, errors);
- } catch (@SuppressWarnings("deprecation") org.junit.internal.AssumptionViolatedException e) {
+ } catch (org.junit.internal.AssumptionViolatedException e) {
errors.add(e);
skippedQuietly(e, description, errors);
} catch (Throwable e) {
@@ -87,7 +93,6 @@ public abstract class TestWatcher implements TestRule {
}
}
- @SuppressWarnings("deprecation")
private void skippedQuietly(
org.junit.internal.AssumptionViolatedException e, Description description,
List Returns an empty {@code Request} if {@code desiredDescription} is not a single test and filters all but the single
+ * test if {@code desiredDescription} is a single test.
+ * For example, here is code to run a test suite in reverse order:
+ * Beware of using this interface to cope with order dependencies between tests.
+ * Tests that are isolated from each other are less expensive to maintain and
+ * can be run individually.
+ *
+ * @since 4.13
+ */
+public interface Orderable extends Sortable {
+
+ /**
+ * Orders the tests using In general you will not need to use a For a factory to be used with {@code @OrderWith} it needs to have a public no-arg
+ * constructor.
+ */
+ public interface Factory {
+ /**
+ * Creates an Ordering instance using the given context. Implementations
+ * of this method that do not need to use the context can return the
+ * same instance every time.
+ */
+ Ordering create(Context context);
+ }
+}
diff --git a/src/main/java/org/junit/runner/manipulation/Sortable.java b/src/main/java/org/junit/runner/manipulation/Sortable.java
index 9ac864c..0c59f33 100644
--- a/src/main/java/org/junit/runner/manipulation/Sortable.java
+++ b/src/main/java/org/junit/runner/manipulation/Sortable.java
@@ -15,6 +15,6 @@ public interface Sortable {
*
* @param sorter the {@link Sorter} to use for sorting the tests
*/
- public void sort(Sorter sorter);
+ void sort(Sorter sorter);
}
diff --git a/src/main/java/org/junit/runner/manipulation/Sorter.java b/src/main/java/org/junit/runner/manipulation/Sorter.java
index 20192d0..4b5274c 100644
--- a/src/main/java/org/junit/runner/manipulation/Sorter.java
+++ b/src/main/java/org/junit/runner/manipulation/Sorter.java
@@ -1,16 +1,21 @@
package org.junit.runner.manipulation;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
import org.junit.runner.Description;
/**
* A Note that not all runners will call this method, so runners should
+ * be prepared to handle {@link #testStarted(Description)} calls for tests
+ * where there was no corresponding {@code testSuiteStarted()} call for
+ * the parent {@code Description}.
+ *
+ * @param description the description of the test suite that is about to be run
+ * (generally a class name)
+ * @since 4.13
+ */
+ public void testSuiteStarted(Description description) throws Exception {
+ }
+
+ /**
+ * Called when a test suite has finished, whether the test suite succeeds or fails.
+ * This method will not be called for a given {@link Description} unless
+ * {@link #testSuiteStarted(Description)} was called for the same @code Description}.
+ *
+ * @param description the description of the test suite that just ran
+ * @since 4.13
+ */
+ public void testSuiteFinished(Description description) throws Exception {
+ }
+
/**
* Called when an atomic test is about to be started.
*
diff --git a/src/main/java/org/junit/runner/notification/RunNotifier.java b/src/main/java/org/junit/runner/notification/RunNotifier.java
index 6875f76..752fa3b 100644
--- a/src/main/java/org/junit/runner/notification/RunNotifier.java
+++ b/src/main/java/org/junit/runner/notification/RunNotifier.java
@@ -65,8 +65,8 @@ public class RunNotifier {
void run() {
int capacity = currentListeners.size();
- ArrayList This class synchronizes all listener calls on a RunNotifier instance. This is done because
* prior to JUnit 4.12, all listeners were called in a synchronized block in RunNotifier,
* so no two listeners were ever called concurrently. If we instead made the methods here
- * sychronized, clients that added multiple listeners that called common code might see
+ * synchronized, clients that added multiple listeners that called common code might see
* issues due to the reduced synchronization.
*
* @author Tibor Digana (tibor17)
@@ -43,6 +43,37 @@ final class SynchronizedRunListener extends RunListener {
}
}
+ /**
+ * {@inheritDoc}
+ *
- * For example, to test a Fibonacci function, write:
+ * For example, to test the
- * Each instance of
* In order that you can easily identify the individual tests, you may provide a
@@ -69,33 +79,36 @@ import org.junit.runners.parameterized.TestWithParameters;
*
*
* In the example given above, the
* You can also write:
*
- * Each instance of
+ * If your test needs to perform some preparation or cleanup based on the
+ * parameters, this can be done by adding public static methods annotated with
+ * {@code @BeforeParam}/{@code @AfterParam}. Such methods should either have no
+ * parameters or the same parameters as the test.
+ *
* By default the {@code Parameterized} runner creates a slightly modified
@@ -141,7 +166,7 @@ import org.junit.runners.parameterized.TestWithParameters;
* The factory must have a public zero-arg constructor.
*
* With {@link org.junit.Assume assumptions} you can dynamically skip tests.
+ * Assumptions are also supported by the ArrayComparisonFailure
with an error text and the array's
@@ -32,7 +33,8 @@ public class ArrayComparisonFailure extends AssertionError {
*/
public ArrayComparisonFailure(String message, AssertionError cause, int index) {
this.fMessage = message;
- initCause(cause);
+ this.fCause = cause;
+ initCause(fCause);
addDimension(index);
}
@@ -40,6 +42,11 @@ public class ArrayComparisonFailure extends AssertionError {
fIndices.add(0, index);
}
+ @Override
+ public synchronized Throwable getCause() {
+ return super.getCause() == null ? fCause : super.getCause();
+ }
+
@Override
public String getMessage() {
StringBuilder sb = new StringBuilder();
diff --git a/src/main/java/org/junit/internal/AssumptionViolatedException.java b/src/main/java/org/junit/internal/AssumptionViolatedException.java
index 880d73f..0e79b56 100644
--- a/src/main/java/org/junit/internal/AssumptionViolatedException.java
+++ b/src/main/java/org/junit/internal/AssumptionViolatedException.java
@@ -1,5 +1,8 @@
package org.junit.internal;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.SelfDescribing;
@@ -18,7 +21,7 @@ public class AssumptionViolatedException extends RuntimeException implements Sel
/*
* We have to use the f prefix until the next major release to ensure
* serialization compatibility.
- * See https://github.com/junit-team/junit/issues/976
+ * See https://github.com/junit-team/junit4/issues/976
*/
private final String fAssumption;
private final boolean fValueMatcher;
@@ -108,4 +111,29 @@ public class AssumptionViolatedException extends RuntimeException implements Sel
}
}
}
+
+ /**
+ * Override default Java object serialization to correctly deal with potentially unserializable matchers or values.
+ * By not implementing readObject, we assure ourselves of backwards compatibility and compatibility with the
+ * standard way of Java serialization.
+ *
+ * @param objectOutputStream The outputStream to write our representation to
+ * @throws IOException When serialization fails
+ */
+ private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
+ ObjectOutputStream.PutField putField = objectOutputStream.putFields();
+ putField.put("fAssumption", fAssumption);
+ putField.put("fValueMatcher", fValueMatcher);
+
+ // We have to wrap the matcher into a serializable form.
+ putField.put("fMatcher", SerializableMatcherDescription.asSerializableMatcher(fMatcher));
+
+ // We have to wrap the value inside a non-String class (instead of serializing the String value directly) as
+ // A Description will handle a String and non-String object differently (1st is surrounded by '"' while the
+ // latter will be surrounded by '<' '>'. Wrapping it makes sure that the description of a serialized and
+ // non-serialized instance produce the exact same description
+ putField.put("fValue", SerializableValueDescription.asSerializableValue(fValue));
+
+ objectOutputStream.writeFields();
+ }
}
diff --git a/src/main/java/org/junit/internal/Checks.java b/src/main/java/org/junit/internal/Checks.java
new file mode 100644
index 0000000..9724947
--- /dev/null
+++ b/src/main/java/org/junit/internal/Checks.java
@@ -0,0 +1,37 @@
+package org.junit.internal;
+
+/** @since 4.13 */
+public final class Checks {
+
+ private Checks() {}
+
+ /**
+ * Checks that the given value is not {@code null}.
+ *
+ * @param value object reference to check
+ * @return the passed-in value, if not {@code null}
+ * @throws NullPointerException if {@code value} is {@code null}
+ */
+ public static
+ * public static class DisableTimeoutOnDebugSampleTest {
+ *
+ * @Rule
+ * public TestRule timeout = new DisableOnDebug(new Timeout(20));
+ *
+ * @Test
+ * public void myTest() {
+ * int i = 0;
+ * assertEquals(0, i); // suppose you had a break point here to inspect i
+ * }
+ * }
+ *
+ *
+ * @since 4.12
+ */
+public class DisableOnDebug implements TestRule {
+ private final TestRule rule;
+ private final boolean debugging;
+
+ /**
+ * Create a {@code DisableOnDebug} instance with the timeout specified in
+ * milliseconds.
+ *
+ * @param rule to disable during debugging
+ */
+ public DisableOnDebug(TestRule rule) {
+ this(rule, ManagementFactory.getRuntimeMXBean()
+ .getInputArguments());
+ }
+
+ /**
+ * Visible for testing purposes only.
+ *
+ * @param rule the rule to disable during debugging
+ * @param inputArguments
+ * arguments provided to the Java runtime
+ */
+ DisableOnDebug(TestRule rule, List
+ *
public class SimpleExpectedExceptionTest {
* @Rule
- * public ExpectedException thrown= ExpectedException.none();
+ * public ExpectedException thrown = ExpectedException.none();
*
* @Test
* public void throwsNothing() {
@@ -35,16 +34,19 @@ import org.junit.runners.model.Statement;
* }
* }
*
- *
*
*
- * @Test
* public void throwsException() {
@@ -63,9 +64,15 @@ import org.junit.runners.model.Statement;
* throw new NullPointerException("What happened?");
* }
*
+ * @Rule(order = Integer.MAX_VALUE)
+ * public ExpectedException thrown = ExpectedException.none();
+ *
* AssumptionViolatedExceptions
- * AssertionErrors
*
- * Missing Exceptions
- *
- *
- *
- * Note that {@link MethodRule} has been replaced by {@link TestRule},
+ *
- * public static class UseRuleChain {
- * @Rule
- * public RuleChain chain= RuleChain
- * .outerRule(new LoggingRule("outer rule")
- * .around(new LoggingRule("middle rule")
- * .around(new LoggingRule("inner rule");
+ * public abstract class CompositeRules {
+ * public static TestRule extendedLogging() {
+ * return RuleChain.outerRule(new LoggingRule("outer rule"))
+ * .around(new LoggingRule("middle rule"))
+ * .around(new LoggingRule("inner rule"));
+ * }
+ * }
+ *
+ *
+ *
+ * public class UseRuleChain {
+ * @Rule
+ * public final TestRule extendedLogging = CompositeRules.extendedLogging();
*
- * @Test
- * public void example() {
- * assertTrue(true);
- * }
+ * @Test
+ * public void example() {
+ * assertTrue(true);
+ * }
* }
*
*
@@ -38,6 +46,13 @@ import org.junit.runners.model.Statement;
* finished outer rule
*
*
+ * In older versions of JUnit (before 4.13) {@code RuleChain} was used for
+ * ordering rules. We recommend to not use it for this purpose anymore. You can
+ * use the attribute {@code order} of the annotation {@link Rule#order() Rule}
+ * or {@link org.junit.ClassRule#order() ClassRule} for ordering rules.
+ *
+ * @see org.junit.Rule#order()
+ * @see org.junit.ClassRule#order()
* @since 4.10
*/
public class RuleChain implements TestRule {
@@ -72,13 +87,17 @@ public class RuleChain implements TestRule {
}
/**
- * Create a new {@code RuleChain}, which encloses the {@code nextRule} with
+ * Create a new {@code RuleChain}, which encloses the given {@link TestRule} with
* the rules of the current {@code RuleChain}.
*
- * @param enclosedRule the rule to enclose.
+ * @param enclosedRule the rule to enclose; must not be {@code null}.
* @return a new {@code RuleChain}.
+ * @throws NullPointerException if the argument {@code enclosedRule} is {@code null}
*/
public RuleChain around(TestRule enclosedRule) {
+ if (enclosedRule == null) {
+ throw new NullPointerException("The enclosed rule must not be null");
+ }
List
@@ -26,18 +31,104 @@ import org.junit.Rule;
* }
*
*
+ *
+ * @Rule
+ * public TemporaryFolder folder= TemporaryFolder.builder().assureDeletion().build();
+ *
+ *
* @since 4.7
*/
public class TemporaryFolder extends ExternalResource {
private final File parentFolder;
+ private final boolean assureDeletion;
private File folder;
+ private static final int TEMP_DIR_ATTEMPTS = 10000;
+ private static final String TMP_PREFIX = "junit";
+
+ /**
+ * Create a temporary folder which uses system default temporary-file
+ * directory to create temporary resources.
+ */
public TemporaryFolder() {
- this(null);
+ this((File) null);
}
+ /**
+ * Create a temporary folder which uses the specified directory to create
+ * temporary resources.
+ *
+ * @param parentFolder folder where temporary resources will be created.
+ * If {@code null} then system default temporary-file directory is used.
+ */
public TemporaryFolder(File parentFolder) {
this.parentFolder = parentFolder;
+ this.assureDeletion = false;
+ }
+
+ /**
+ * Create a {@link TemporaryFolder} initialized with
+ * values from a builder.
+ */
+ protected TemporaryFolder(Builder builder) {
+ this.parentFolder = builder.parentFolder;
+ this.assureDeletion = builder.assureDeletion;
+ }
+
+ /**
+ * Returns a new builder for building an instance of {@link TemporaryFolder}.
+ *
+ * @since 4.13
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builds an instance of {@link TemporaryFolder}.
+ *
+ * @since 4.13
+ */
+ public static class Builder {
+ private File parentFolder;
+ private boolean assureDeletion;
+
+ protected Builder() {}
+
+ /**
+ * Specifies which folder to use for creating temporary resources.
+ * If {@code null} then system default temporary-file directory is
+ * used.
+ *
+ * @return this
+ */
+ public Builder parentFolder(File parentFolder) {
+ this.parentFolder = parentFolder;
+ return this;
+ }
+
+ /**
+ * Setting this flag assures that no resources are left undeleted. Failure
+ * to fulfill the assurance results in failure of tests with an
+ * {@link AssertionError}.
+ *
+ * @return this
+ */
+ public Builder assureDeletion() {
+ this.assureDeletion = true;
+ return this;
+ }
+
+ /**
+ * Builds a {@link TemporaryFolder} instance using the values in this builder.
+ */
+ public TemporaryFolder build() {
+ return new TemporaryFolder(this);
+ }
}
@Override
@@ -75,52 +166,63 @@ public class TemporaryFolder extends ExternalResource {
* Returns a new fresh file with a random name under the temporary folder.
*/
public File newFile() throws IOException {
- return File.createTempFile("junit", null, getRoot());
+ return File.createTempFile(TMP_PREFIX, null, getRoot());
}
/**
- * Returns a new fresh folder with the given name under the temporary
+ * Returns a new fresh folder with the given path under the temporary
* folder.
*/
- public File newFolder(String folder) throws IOException {
- return newFolder(new String[]{folder});
+ public File newFolder(String path) throws IOException {
+ return newFolder(new String[]{path});
}
/**
- * Returns a new fresh folder with the given name(s) under the temporary
- * folder.
+ * Returns a new fresh folder with the given paths under the temporary
+ * folder. For example, if you pass in the strings {@code "parent"} and {@code "child"}
+ * then a directory named {@code "parent"} will be created under the temporary folder
+ * and a directory named {@code "child"} will be created under the newly-created
+ * {@code "parent"} directory.
*/
- public File newFolder(String... folderNames) throws IOException {
- File file = getRoot();
- for (int i = 0; i < folderNames.length; i++) {
- String folderName = folderNames[i];
- validateFolderName(folderName);
- file = new File(file, folderName);
- if (!file.mkdir() && isLastElementInArray(i, folderNames)) {
- throw new IOException(
- "a folder with the name \'" + folderName + "\' already exists");
- }
+ public File newFolder(String... paths) throws IOException {
+ if (paths.length == 0) {
+ throw new IllegalArgumentException("must pass at least one path");
}
- return file;
- }
-
- /**
- * Validates if multiple path components were used while creating a folder.
- *
- * @param folderName
- * Name of the folder being created
- */
- private void validateFolderName(String folderName) throws IOException {
- File tempFile = new File(folderName);
- if (tempFile.getParent() != null) {
- String errorMsg = "Folder name cannot consist of multiple path components separated by a file separator."
- + " Please use newFolder('MyParentFolder','MyFolder') to create hierarchies of folders";
- throw new IOException(errorMsg);
+
+ /*
+ * Before checking if the paths are absolute paths, check if create() was ever called,
+ * and if it wasn't, throw IllegalStateException.
+ */
+ File root = getRoot();
+ for (String path : paths) {
+ if (new File(path).isAbsolute()) {
+ throw new IOException("folder path \'" + path + "\' is not a relative path");
+ }
}
- }
- private boolean isLastElementInArray(int index, String[] array) {
- return index == array.length - 1;
+ File relativePath = null;
+ File file = root;
+ boolean lastMkdirsCallSuccessful = true;
+ for (String path : paths) {
+ relativePath = new File(relativePath, path);
+ file = new File(root, relativePath.getPath());
+
+ lastMkdirsCallSuccessful = file.mkdirs();
+ if (!lastMkdirsCallSuccessful && !file.isDirectory()) {
+ if (file.exists()) {
+ throw new IOException(
+ "a file with the path \'" + relativePath.getPath() + "\' exists");
+ } else {
+ throw new IOException(
+ "could not create a folder with the path \'" + relativePath.getPath() + "\'");
+ }
+ }
+ }
+ if (!lastMkdirsCallSuccessful) {
+ throw new IOException(
+ "a folder with the path \'" + relativePath.getPath() + "\' already exists");
+ }
+ return file;
}
/**
@@ -130,11 +232,63 @@ public class TemporaryFolder extends ExternalResource {
return createTemporaryFolderIn(getRoot());
}
- private File createTemporaryFolderIn(File parentFolder) throws IOException {
- File createdFolder = File.createTempFile("junit", "", parentFolder);
- createdFolder.delete();
- createdFolder.mkdir();
- return createdFolder;
+ private static File createTemporaryFolderIn(File parentFolder) throws IOException {
+ try {
+ return createTemporaryFolderWithNioApi(parentFolder);
+ } catch (ClassNotFoundException ignore) {
+ // Fallback for Java 5 and 6
+ return createTemporaryFolderWithFileApi(parentFolder);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof IOException) {
+ throw (IOException) cause;
+ }
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ }
+ IOException exception = new IOException("Failed to create temporary folder in " + parentFolder);
+ exception.initCause(cause);
+ throw exception;
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create temporary folder in " + parentFolder, e);
+ }
+ }
+
+ private static File createTemporaryFolderWithNioApi(File parentFolder) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ Class> filesClass = Class.forName("java.nio.file.Files");
+ Object fileAttributeArray = Array.newInstance(Class.forName("java.nio.file.attribute.FileAttribute"), 0);
+ Class> pathClass = Class.forName("java.nio.file.Path");
+ Object tempDir;
+ if (parentFolder != null) {
+ Method createTempDirectoryMethod = filesClass.getDeclaredMethod("createTempDirectory", pathClass, String.class, fileAttributeArray.getClass());
+ Object parentPath = File.class.getDeclaredMethod("toPath").invoke(parentFolder);
+ tempDir = createTempDirectoryMethod.invoke(null, parentPath, TMP_PREFIX, fileAttributeArray);
+ } else {
+ Method createTempDirectoryMethod = filesClass.getDeclaredMethod("createTempDirectory", String.class, fileAttributeArray.getClass());
+ tempDir = createTempDirectoryMethod.invoke(null, TMP_PREFIX, fileAttributeArray);
+ }
+ return (File) pathClass.getDeclaredMethod("toFile").invoke(tempDir);
+ }
+
+ private static File createTemporaryFolderWithFileApi(File parentFolder) throws IOException {
+ File createdFolder = null;
+ for (int i = 0; i < TEMP_DIR_ATTEMPTS; ++i) {
+ // Use createTempFile to get a suitable folder name.
+ String suffix = ".tmp";
+ File tmpFile = File.createTempFile(TMP_PREFIX, suffix, parentFolder);
+ String tmpName = tmpFile.toString();
+ // Discard .tmp suffix of tmpName.
+ String folderName = tmpName.substring(0, tmpName.length() - suffix.length());
+ createdFolder = new File(folderName);
+ if (createdFolder.mkdir()) {
+ tmpFile.delete();
+ return createdFolder;
+ }
+ tmpFile.delete();
+ }
+ throw new IOException("Unable to create temporary directory in: "
+ + parentFolder.toString() + ". Tried " + TEMP_DIR_ATTEMPTS + " times. "
+ + "Last attempted to create: " + createdFolder.toString());
}
/**
@@ -150,21 +304,48 @@ public class TemporaryFolder extends ExternalResource {
/**
* Delete all files and folders under the temporary folder. Usually not
- * called directly, since it is automatically applied by the {@link Rule}
+ * called directly, since it is automatically applied by the {@link Rule}.
+ *
+ * @throws AssertionError if unable to clean up resources
+ * and deletion of resources is assured.
*/
public void delete() {
- if (folder != null) {
- recursiveDelete(folder);
+ if (!tryDelete()) {
+ if (assureDeletion) {
+ fail("Unable to clean up temporary folder " + folder);
+ }
+ }
+ }
+
+ /**
+ * Tries to delete all files and folders under the temporary folder and
+ * returns whether deletion was successful or not.
+ *
+ * @return {@code true} if all resources are deleted successfully,
+ * {@code false} otherwise.
+ */
+ private boolean tryDelete() {
+ if (folder == null) {
+ return true;
}
+
+ return recursiveDelete(folder);
}
- private void recursiveDelete(File file) {
+ private boolean recursiveDelete(File file) {
+ // Try deleting file before assuming file is a directory
+ // to prevent following symbolic links.
+ if (file.delete()) {
+ return true;
+ }
File[] files = file.listFiles();
if (files != null) {
for (File each : files) {
- recursiveDelete(each);
+ if (!recursiveDelete(each)) {
+ return false;
+ }
}
}
- file.delete();
+ return file.delete();
}
}
diff --git a/src/main/java/org/junit/rules/TestName.java b/src/main/java/org/junit/rules/TestName.java
index bf72602..e2ebc2e 100644
--- a/src/main/java/org/junit/rules/TestName.java
+++ b/src/main/java/org/junit/rules/TestName.java
@@ -25,7 +25,7 @@ import org.junit.runner.Description;
* @since 4.7
*/
public class TestName extends TestWatcher {
- private String name;
+ private volatile String name;
@Override
protected void starting(Description d) {
diff --git a/src/main/java/org/junit/rules/TestWatcher.java b/src/main/java/org/junit/rules/TestWatcher.java
index 5492b6b..a28514d 100644
--- a/src/main/java/org/junit/rules/TestWatcher.java
+++ b/src/main/java/org/junit/rules/TestWatcher.java
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.junit.AssumptionViolatedException;
+import org.junit.Rule;
import org.junit.runner.Description;
import org.junit.runners.model.MultipleFailureException;
import org.junit.runners.model.Statement;
@@ -17,7 +18,7 @@ import org.junit.runners.model.Statement;
* public static class WatchmanTest {
* private static String watchedLog;
*
- * @Rule
+ * @Rule(order = Integer.MIN_VALUE)
* public TestWatcher watchman= new TestWatcher() {
* @Override
* protected void failed(Throwable e, Description description) {
@@ -40,6 +41,11 @@ import org.junit.runners.model.Statement;
* }
* }
*
+ * Description
named after testClass
+ *
+ * @param testClass A not null {@link Class} containing tests
+ * @param annotations meta-data about the test, for downstream interpreters
+ * @return a Description
of testClass
+ */
+ public static Description createSuiteDescription(Class> testClass, Annotation... annotations) {
+ return new Description(testClass, testClass.getName(), annotations);
+ }
+
/**
* Describes a Runner which runs no tests
*/
@@ -139,7 +150,7 @@ public class Description implements Serializable {
/*
* We have to use the f prefix until the next major release to ensure
* serialization compatibility.
- * See https://github.com/junit-team/junit/issues/976
+ * See https://github.com/junit-team/junit4/issues/976
*/
private final Collection@OrderWith
or extends a class annotated
+ * with @OrderWith
, JUnit will order the tests in the test class (and child
+ * test classes, if any) using the ordering defined by the {@link Ordering} class.
+ *
+ * @since 4.13
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Inherited
+@ValidateWith(OrderWithValidator.class)
+public @interface OrderWith {
+ /**
+ * Gets a class that extends {@link Ordering}. The class must have a public no-arg constructor.
+ */
+ Class extends Ordering.Factory> value();
+}
diff --git a/src/main/java/org/junit/runner/OrderWithValidator.java b/src/main/java/org/junit/runner/OrderWithValidator.java
new file mode 100644
index 0000000..f8eab25
--- /dev/null
+++ b/src/main/java/org/junit/runner/OrderWithValidator.java
@@ -0,0 +1,38 @@
+package org.junit.runner;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
+import java.util.List;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.model.TestClass;
+import org.junit.validator.AnnotationValidator;
+
+/**
+ * Validates that there are no errors in the use of the {@code OrderWith}
+ * annotation. If there is, a {@code Throwable} object will be added to the list
+ * of errors.
+ *
+ * @since 4.13
+ */
+public final class OrderWithValidator extends AnnotationValidator {
+
+ /**
+ * Adds to {@code errors} a throwable for each problem detected. Looks for
+ * {@code FixMethodOrder} annotations.
+ *
+ * @param testClass that is being validated
+ * @return A list of exceptions detected
+ *
+ * @since 4.13
+ */
+ @Override
+ public ListdesiredDescription
+ * Returns a Request that only runs tests whose {@link Description}
+ * matches the given description.
*
- * @param desiredDescription {@link Description} of those tests that should be run
+ *
* private static Comparator<Description> forward() {
- * return new Comparator<Description>() {
- * public int compare(Description o1, Description o2) {
- * return o1.getDisplayName().compareTo(o2.getDisplayName());
- * }
- * };
+ * return new Comparator<Description>() {
+ * public int compare(Description o1, Description o2) {
+ * return o1.getDisplayName().compareTo(o2.getDisplayName());
+ * }
+ * };
* }
*
* public static main() {
- * new JUnitCore().run(Request.aClass(AllTests.class).sortWith(forward()));
+ * new JUnitCore().run(Request.aClass(AllTests.class).sortWith(forward()));
* }
*
*
@@ -167,4 +171,32 @@ public abstract class Request {
public Request sortWith(Comparatorordering
+ *
+ * private static Ordering reverse() {
+ * return new Ordering() {
+ * public List<Description> orderItems(Collection<Description> descriptions) {
+ * List<Description> ordered = new ArrayList<>(descriptions);
+ * Collections.reverse(ordered);
+ * return ordered;
+ * }
+ * }
+ * }
+ *
+ * public static main() {
+ * new JUnitCore().run(Request.aClass(AllTests.class).orderWith(reverse()));
+ * }
+ *
+ *
+ * @return a Request with ordered Tests
+ * @since 4.13
+ */
+ public Request orderWith(Ordering ordering) {
+ return new OrderingRequest(this, ordering);
+ }
}
diff --git a/src/main/java/org/junit/runner/Result.java b/src/main/java/org/junit/runner/Result.java
index 73ad059..4b5f4a4 100644
--- a/src/main/java/org/junit/runner/Result.java
+++ b/src/main/java/org/junit/runner/Result.java
@@ -28,6 +28,7 @@ public class Result implements Serializable {
ObjectStreamClass.lookup(SerializedForm.class).getFields();
private final AtomicInteger count;
private final AtomicInteger ignoreCount;
+ private final AtomicInteger assumptionFailureCount;
private final CopyOnWriteArrayListtrue
if all tests succeeded
*/
@@ -137,7 +154,7 @@ public class Result implements Serializable {
@Override
public void testAssumptionFailure(Failure failure) {
- // do nothing: same as passing (for 4.5; may change in 4.6)
+ assumptionFailureCount.getAndIncrement();
}
}
@@ -156,6 +173,7 @@ public class Result implements Serializable {
private static final long serialVersionUID = 1L;
private final AtomicInteger fCount;
private final AtomicInteger fIgnoreCount;
+ private final AtomicInteger assumptionFailureCount;
private final Listorderer
+ *
+ * @throws InvalidOrderingException if orderer does something invalid (like remove or add
+ * children)
+ */
+ void order(Orderer orderer) throws InvalidOrderingException;
+}
diff --git a/src/main/java/org/junit/runner/manipulation/Orderer.java b/src/main/java/org/junit/runner/manipulation/Orderer.java
new file mode 100644
index 0000000..eb13054
--- /dev/null
+++ b/src/main/java/org/junit/runner/manipulation/Orderer.java
@@ -0,0 +1,62 @@
+package org.junit.runner.manipulation;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.runner.Description;
+
+/**
+ * Orders tests.
+ *
+ * @since 4.13
+ */
+public final class Orderer {
+ private final Ordering ordering;
+
+ Orderer(Ordering delegate) {
+ this.ordering = delegate;
+ }
+
+ /**
+ * Orders the descriptions.
+ *
+ * @return descriptions in order
+ */
+ public Listtarget
.
+ *
+ * @throws InvalidOrderingException if ordering does something invalid (like remove or add
+ * children)
+ */
+ public void apply(Object target) throws InvalidOrderingException {
+ if (target instanceof Orderable) {
+ Orderable orderable = (Orderable) target;
+ orderable.order(this);
+ }
+ }
+}
diff --git a/src/main/java/org/junit/runner/manipulation/Ordering.java b/src/main/java/org/junit/runner/manipulation/Ordering.java
new file mode 100644
index 0000000..0d0ce93
--- /dev/null
+++ b/src/main/java/org/junit/runner/manipulation/Ordering.java
@@ -0,0 +1,172 @@
+package org.junit.runner.manipulation;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import org.junit.runner.Description;
+import org.junit.runner.OrderWith;
+
+/**
+ * Reorders tests. An {@code Ordering} can reverse the order of tests, sort the
+ * order or even shuffle the order.
+ *
+ * Ordering
directly.
+ * Instead, use {@link org.junit.runner.Request#orderWith(Ordering)}.
+ *
+ * @since 4.13
+ */
+public abstract class Ordering {
+ private static final String CONSTRUCTOR_ERROR_FORMAT
+ = "Ordering class %s should have a public constructor with signature "
+ + "%s(Ordering.Context context)";
+
+ /**
+ * Creates an {@link Ordering} that shuffles the items using the given
+ * {@link Random} instance.
+ */
+ public static Ordering shuffledBy(final Random random) {
+ return new Ordering() {
+ @Override
+ boolean validateOrderingIsCorrect() {
+ return false;
+ }
+
+ @Override
+ protected Listtarget
using this ordering.
+ *
+ * @throws InvalidOrderingException if ordering does something invalid (like remove or add
+ * children)
+ */
+ public void apply(Object target) throws InvalidOrderingException {
+ /*
+ * Note that some subclasses of Ordering override apply(). The Sorter
+ * subclass of Ordering overrides apply() to apply the sort (this is
+ * done because sorting is more efficient than ordering).
+ */
+ if (target instanceof Orderable) {
+ Orderable orderable = (Orderable) target;
+ orderable.order(new Orderer(this));
+ }
+ }
+
+ /**
+ * Returns {@code true} if this ordering could produce invalid results (i.e.
+ * if it could add or remove values).
+ */
+ boolean validateOrderingIsCorrect() {
+ return true;
+ }
+
+ /**
+ * Implemented by sub-classes to order the descriptions.
+ *
+ * @return descriptions in order
+ */
+ protected abstract ListSorter
orders tests. In general you will not need
- * to use a Sorter
directly. Instead, use {@link org.junit.runner.Request#sortWith(Comparator)}.
+ * to use a Sorter
directly. Instead, use
+ * {@link org.junit.runner.Request#sortWith(Comparator)}.
*
* @since 4.0
*/
-public class Sorter implements ComparatorSorter
that leaves elements in an undefined order
*/
@@ -27,17 +32,26 @@ public class Sorter implements Comparatorrunner
using comparator
+ * Sorts the tests in target
using comparator
.
+ *
+ * @since 4.0
*/
- public void apply(Object object) {
- if (object instanceof Sortable) {
- Sortable sortable = (Sortable) object;
+ @Override
+ public void apply(Object target) {
+ /*
+ * Note that all runners that are Orderable are also Sortable (because
+ * Orderable extends Sortable). Sorting is more efficient than ordering,
+ * so we override the parent behavior so we sort instead.
+ */
+ if (target instanceof Sortable) {
+ Sortable sortable = (Sortable) target;
sortable.sort(this);
}
}
@@ -45,4 +59,32 @@ public class Sorter implements Comparator
- *
+
operator, write:
*
* @RunWith(Parameterized.class)
- * public class FibonacciTest {
- * @Parameters(name= "{index}: fib[{0}]={1}")
+ * public class AdditionTest {
+ * @Parameters(name = "{index}: {0} + {1} = {2}")
* public static Iterable<Object[]> data() {
- * return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
- * { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
+ * return Arrays.asList(new Object[][] { { 0, 0, 0 }, { 1, 1, 2 },
+ * { 3, 2, 5 }, { 4, 3, 7 } });
* }
*
- * private int fInput;
+ * private int firstSummand;
*
- * private int fExpected;
+ * private int secondSummand;
*
- * public FibonacciTest(int input, int expected) {
- * fInput= input;
- * fExpected= expected;
+ * private int sum;
+ *
+ * public AdditionTest(int firstSummand, int secondSummand, int sum) {
+ * this.firstSummand = firstSummand;
+ * this.secondSummand = secondSummand;
+ * this.sum = sum;
* }
*
* @Test
* public void test() {
- * assertEquals(fExpected, Fibonacci.compute(fInput));
+ * assertEquals(sum, firstSummand + secondSummand);
* }
* }
*
* FibonacciTest
will be constructed using the
- * two-argument constructor and the data values in the
+ * Each instance of AdditionTest
will be constructed using the
+ * three-argument constructor and the data values in the
* @Parameters
method.
* Parameterized
runner creates
- * names like [1: fib(3)=2]
. If you don't use the name parameter,
+ * names like [2: 3 + 2 = 5]
. If you don't use the name parameter,
* then the current parameter index is used as name.
*
* @RunWith(Parameterized.class)
- * public class FibonacciTest {
- * @Parameters
- * public static Iterable<Object[]> data() {
- * return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
- * { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
- * }
- *
- * @Parameter(0)
- * public int fInput;
+ * public class AdditionTest {
+ * @Parameters(name = "{index}: {0} + {1} = {2}")
+ * public static Iterable<Object[]> data() {
+ * return Arrays.asList(new Object[][] { { 0, 0, 0 }, { 1, 1, 2 },
+ * { 3, 2, 5 }, { 4, 3, 7 } });
+ * }
+ *
+ * @Parameter(0)
+ * public int firstSummand;
*
- * @Parameter(1)
- * public int fExpected;
+ * @Parameter(1)
+ * public int secondSummand;
*
- * @Test
- * public void test() {
- * assertEquals(fExpected, Fibonacci.compute(fInput));
- * }
+ * @Parameter(2)
+ * public int sum;
+ *
+ * @Test
+ * public void test() {
+ * assertEquals(sum, firstSummand + secondSummand);
+ * }
* }
*
* FibonacciTest
will be constructed with the default constructor
+ * Each instance of AdditionTest
will be constructed with the default constructor
* and fields annotated by @Parameter
will be initialized
* with the data values in the @Parameters
method.
*
@@ -105,8 +118,7 @@ import org.junit.runners.parameterized.TestWithParameters;
*
* @Parameters
* public static Object[][] data() {
- * return new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 },
- * { 5, 5 }, { 6, 8 } };
+ * return new Object[][] { { 0, 0, 0 }, { 1, 1, 2 }, { 3, 2, 5 }, { 4, 3, 7 } } };
* }
*
*
@@ -130,6 +142,19 @@ import org.junit.runners.parameterized.TestWithParameters;
* }
*
*
+ * Executing code before/after executing tests for specific parameters
+ *
+ * @BeforeParam
+ * public static void beforeTestsForParameter(String onlyParameter) {
+ * System.out.println("Testing " + onlyParameter);
+ * }
+ *
+ *
* Create different runners
*
- * public class YourRunnerFactory implements ParameterizedRunnerFactory {
+ * public class YourRunnerFactory implements ParametersRunnerFactory {
* public Runner createRunnerForTestWithParameters(TestWithParameters test)
* throws InitializationError {
* return YourRunner(test);
@@ -160,6 +185,21 @@ import org.junit.runners.parameterized.TestWithParameters;
* }
*
*
+ * Avoid creating parameters
+ * @Parameters
method.
+ * Creating parameters is stopped when the assumption fails and none of the
+ * tests in the test class is executed. JUnit reports a
+ * {@link Result#getAssumptionFailureCount() single assumption failure} for the
+ * whole test class in this case.
+ *
+ * @Parameters
+ * public static Iterable<? extends Object> data() {
+ * String os = System.getProperty("os.name").toLowerCase()
+ * Assume.assumeTrue(os.contains("win"));
+ * return Arrays.asList("first test", "second test");
+ * }
+ *
* @since 4.0
*/
public class Parameterized extends Suite {
@@ -170,7 +210,7 @@ public class Parameterized extends Suite {
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
- public static @interface Parameters {
+ public @interface Parameters {
/**
* Optional pattern to derive the test's name from the parameters. Use
* numbers in braces to refer to the parameters or the additional data
@@ -201,7 +241,7 @@ public class Parameterized extends Suite {
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
- public static @interface Parameter {
+ public @interface Parameter {
/**
* Method that returns the index of the parameter in the array
* returned by the method annotated by Parameters
.
@@ -230,122 +270,235 @@ public class Parameterized extends Suite {
Class extends ParametersRunnerFactory> value() default BlockJUnit4ClassRunnerWithParametersFactory.class;
}
- private static final ParametersRunnerFactory DEFAULT_FACTORY = new BlockJUnit4ClassRunnerWithParametersFactory();
-
- private static final List