<h2>Summary of Changes in version 4.7</h2> <h3>Rules</h3> <ul> <li><p>Rules allow very flexible addition or redefinition of the behavior of each test method in a test class. Testers can reuse or extend one of the provided Rules below, or write their own.</p> <p>For more on this feature, see http://www.threeriversinstitute.org/blog/?p=155</p></li> <li><p>The TemporaryFolder Rule allows creation of files and folders that are guaranteed to be deleted when the test method finishes (whether it passes or fails):</p> <p>public static class HasTempFolder { @Rule public TemporaryFolder folder= new TemporaryFolder();</p> <pre><code>@Test public void testUsingTempFolder() throws IOException { File createdFile= folder.newFile("myfile.txt"); File createdFolder= folder.newFolder("subfolder"); // ... } </code></pre> <p>}</p></li> <li><p>ExternalResource is a base class for Rules (like TemporaryFolder) that set up an external resource before a test (a file, socket, server, database connection, etc.), and guarantee to tear it down afterward:</p> <p>public static class UsesExternalResource { Server myServer = new Server();</p> <pre><code>@Rule public ExternalResource resource = new ExternalResource() { @Override protected void before() throws Throwable { myServer.connect(); }; <pre><code>@Override protected void after() { myServer.disconnect(); }; </code></pre> }; @Test public void testFoo() { new Client().run(myServer); } </code></pre> <p>}</p></li> <li><p>The ErrorCollector Rule allows execution of a test to continue after the first problem is found (for example, to collect <em>all</em> the incorrect rows in a table, and report them all at once):</p> <p>public static class UsesErrorCollectorTwice { @Rule public ErrorCollector collector= new ErrorCollector();</p> <pre><code>@Test public void example() { collector.addError(new Throwable("first thing went wrong")); collector.addError(new Throwable("second thing went wrong")); } </code></pre> <p>}</p></li> <li><p>Verifier is a base class for Rules like ErrorCollector, which can turn otherwise passing test methods into failing tests if a verification check is failed</p> <p>public static class ErrorLogVerifier() { private ErrorLog errorLog = new ErrorLog();</p> <p>@Rule public MethodRule verifier = new Verifier() { @Override public void verify() { assertTrue(errorLog.isEmpty()); } }</p> <p>@Test public void testThatMightWriteErrorLog() { // ... } }</p></li> <li><p>TestWatchman is a base class for Rules that take note of the testing action, without modifying it. For example, this class will keep a log of each passing and failing test:</p> <p>public static class WatchmanTest { private static String watchedLog;</p> <pre><code>@Rule public MethodRule watchman= new TestWatchman() { @Override public void failed(Throwable e, FrameworkMethod method) { watchedLog+= method.getName() + " " + e.getClass().getSimpleName() + "\n"; } <pre><code>@Override public void succeeded(FrameworkMethod method) { watchedLog+= method.getName() + " " + "success!\n"; } </code></pre> }; @Test public void fails() { fail(); } @Test public void succeeds() { } </code></pre> <p>}</p></li> <li><p>The TestName Rule makes the current test name available inside test methods:</p> <p>public class NameRuleTest { @Rule public TestName name = new TestName();</p> <pre><code>@Test public void testA() { assertEquals("testA", name.getMethodName()); } @Test public void testB() { assertEquals("testB", name.getMethodName()); } </code></pre> <p>}</p></li> <li><p>The Timeout Rule applies the same timeout to all test methods in a class:</p> <p>public static class HasGlobalTimeout { public static String log;</p> <pre><code>@Rule public MethodRule globalTimeout = new Timeout(20); @Test public void testInfiniteLoop1() { log+= "ran1"; for(;;) {} } @Test public void testInfiniteLoop2() { log+= "ran2"; for(;;) {} } </code></pre> <p>}</p></li> <li><p>The ExpectedException Rule allows in-test specification of expected exception types and messages:</p> <p>public static class HasExpectedException { @Rule public ExpectedException thrown= ExpectedException.none();</p> <pre><code>@Test public void throwsNothing() { } @Test public void throwsNullPointerException() { thrown.expect(NullPointerException.class); throw new NullPointerException(); } @Test public void throwsNullPointerExceptionWithMessage() { thrown.expect(NullPointerException.class); thrown.expectMessage("happened?"); thrown.expectMessage(startsWith("What")); throw new NullPointerException("What happened?"); } </code></pre> <p>}</p></li> </ul> <h3>Timeouts</h3> <ul> <li>Tests that time out now show the stack trace of the test thread.</li> </ul> <h3>Matchers</h3> <ul> <li>Due to typing incompatibilities, JUnit is still including the 1.1 release of hamcrest. This is not a change from 4.6, but is a change from pre-beta releases of 4.7. Due to this incompatibility, tests using Hamcrest 1.2 must still use the MatcherAssert.assertThat method from Hamcrest, not Assert.assertThat from JUnit.</li> </ul> <h3>Docs</h3> <ul> <li>Javadocs now link to online JDK javadocs (bug 2090230)</li> <li>Parameterized runner javadocs improved (bug 2186792)</li> <li>Fixed Javadoc code sample for AfterClass (2126279)</li> <li>Fixed Javadoc for assertArraysEqual(float[], float[])</li> </ul> <h3>Bug fixes</h3> <ul> <li>Fixed: BaseTestRunner.getTest() requires class to extend TestCase (1812200)</li> <li>Fixed: Suite does not allow for inheritance in annotations (2783118)</li> <li>Fixed: ParallelComputer skipped tests that took longer than 2 seconds</li> </ul>