diff options
Diffstat (limited to 'src/main/java/org/junit/rules')
-rw-r--r-- | src/main/java/org/junit/rules/ErrorCollector.java | 85 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/ExpectedException.java | 136 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/ExternalResource.java | 68 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/MethodRule.java | 40 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/RuleChain.java | 99 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/RunRules.java | 27 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/TemporaryFolder.java | 113 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/TestName.java | 39 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/TestRule.java | 54 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/TestWatcher.java | 94 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/TestWatchman.java | 100 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/Timeout.java | 49 | ||||
-rw-r--r-- | src/main/java/org/junit/rules/Verifier.java | 45 |
13 files changed, 949 insertions, 0 deletions
diff --git a/src/main/java/org/junit/rules/ErrorCollector.java b/src/main/java/org/junit/rules/ErrorCollector.java new file mode 100644 index 0000000..3522a65 --- /dev/null +++ b/src/main/java/org/junit/rules/ErrorCollector.java @@ -0,0 +1,85 @@ +/** + * + */ +package org.junit.rules; + +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import org.hamcrest.Matcher; +import org.junit.runners.model.MultipleFailureException; + +/** + * The ErrorCollector rule allows execution of a test to continue after the + * first problem is found (for example, to collect _all_ the incorrect rows in a + * table, and report them all at once): + * + * <pre> + * public static class UsesErrorCollectorTwice { + * @Rule + * public ErrorCollector collector= new ErrorCollector(); + * + * @Test + * public void example() { + * collector.addError(new Throwable("first thing went wrong")); + * collector.addError(new Throwable("second thing went wrong")); + * collector.checkThat(getResult(), not(containsString("ERROR!"))); + * // all lines will run, and then a combined failure logged at the end. + * } + * } + * </pre> + */ +public class ErrorCollector extends Verifier { + private List<Throwable> errors= new ArrayList<Throwable>(); + + @Override + protected void verify() throws Throwable { + MultipleFailureException.assertEmpty(errors); + } + + /** + * Adds a Throwable to the table. Execution continues, but the test will fail at the end. + */ + public void addError(Throwable error) { + errors.add(error); + } + + /** + * Adds a failure to the table if {@code matcher} does not match {@code value}. + * Execution continues, but the test will fail at the end if the match fails. + */ + public <T> void checkThat(final T value, final Matcher<T> matcher) { + checkThat("", value, matcher); + } + + /** + * Adds a failure with the given {@code reason} + * to the table if {@code matcher} does not match {@code value}. + * Execution continues, but the test will fail at the end if the match fails. + */ + public <T> void checkThat(final String reason, final T value, final Matcher<T> matcher) { + checkSucceeds(new Callable<Object>() { + public Object call() throws Exception { + assertThat(reason, value, matcher); + return value; + } + }); + } + + /** + * Adds to the table the exception, if any, thrown from {@code callable}. + * Execution continues, but the test will fail at the end if + * {@code callable} threw an exception. + */ + public Object checkSucceeds(Callable<Object> callable) { + try { + return callable.call(); + } catch (Throwable e) { + addError(e); + return null; + } + } +}
\ No newline at end of file diff --git a/src/main/java/org/junit/rules/ExpectedException.java b/src/main/java/org/junit/rules/ExpectedException.java new file mode 100644 index 0000000..bac2fba --- /dev/null +++ b/src/main/java/org/junit/rules/ExpectedException.java @@ -0,0 +1,136 @@ +package org.junit.rules; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.matchers.JUnitMatchers.both; +import static org.junit.matchers.JUnitMatchers.containsString; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; +import org.junit.Assert; +import org.junit.internal.matchers.TypeSafeMatcher; +import org.junit.runners.model.Statement; + +/** + * The ExpectedException Rule allows in-test specification of expected exception + * types and messages: + * + * <pre> + * // These tests all pass. + * public static class HasExpectedException { + * @Rule + * public ExpectedException thrown= ExpectedException.none(); + * + * @Test + * public void throwsNothing() { + * // no exception expected, none thrown: passes. + * } + * + * @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?"); + * } + * } + * </pre> + */ +public class ExpectedException implements TestRule { + /** + * @return a Rule that expects no exception to be thrown + * (identical to behavior without this Rule) + */ + public static ExpectedException none() { + return new ExpectedException(); + } + + private Matcher<Object> fMatcher= null; + + private ExpectedException() { + + } + + public Statement apply(Statement base, + org.junit.runner.Description description) { + return new ExpectedExceptionStatement(base); + } + + /** + * Adds {@code matcher} to the list of requirements for any thrown exception. + */ + // Should be able to remove this suppression in some brave new hamcrest world. + @SuppressWarnings("unchecked") + public void expect(Matcher<?> matcher) { + if (fMatcher == null) + fMatcher= (Matcher<Object>) matcher; + else + fMatcher= both(fMatcher).and(matcher); + } + + /** + * Adds to the list of requirements for any thrown exception that it + * should be an instance of {@code type} + */ + public void expect(Class<? extends Throwable> type) { + expect(instanceOf(type)); + } + + /** + * Adds to the list of requirements for any thrown exception that it + * should <em>contain</em> string {@code substring} + */ + public void expectMessage(String substring) { + expectMessage(containsString(substring)); + } + + /** + * Adds {@code matcher} to the list of requirements for the message + * returned from any thrown exception. + */ + public void expectMessage(Matcher<String> matcher) { + expect(hasMessage(matcher)); + } + + private class ExpectedExceptionStatement extends Statement { + private final Statement fNext; + + public ExpectedExceptionStatement(Statement base) { + fNext= base; + } + + @Override + public void evaluate() throws Throwable { + try { + fNext.evaluate(); + } catch (Throwable e) { + if (fMatcher == null) + throw e; + Assert.assertThat(e, fMatcher); + return; + } + if (fMatcher != null) + throw new AssertionError("Expected test to throw " + + StringDescription.toString(fMatcher)); + } + } + + private Matcher<Throwable> hasMessage(final Matcher<String> matcher) { + return new TypeSafeMatcher<Throwable>() { + public void describeTo(Description description) { + description.appendText("exception with message "); + description.appendDescriptionOf(matcher); + } + + @Override + public boolean matchesSafely(Throwable item) { + return matcher.matches(item.getMessage()); + } + }; + } +} diff --git a/src/main/java/org/junit/rules/ExternalResource.java b/src/main/java/org/junit/rules/ExternalResource.java new file mode 100644 index 0000000..1fe3719 --- /dev/null +++ b/src/main/java/org/junit/rules/ExternalResource.java @@ -0,0 +1,68 @@ +package org.junit.rules; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * 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: + * + * <pre> + * public static class UsesExternalResource { + * Server myServer= new Server(); + * + * @Rule + * public ExternalResource resource= new ExternalResource() { + * @Override + * protected void before() throws Throwable { + * myServer.connect(); + * }; + * + * @Override + * protected void after() { + * myServer.disconnect(); + * }; + * }; + * + * @Test + * public void testFoo() { + * new Client().run(myServer); + * } + * } + * </pre> + */ +public abstract class ExternalResource implements TestRule { + public Statement apply(Statement base, Description description) { + return statement(base); + } + + private Statement statement(final Statement base) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + before(); + try { + base.evaluate(); + } finally { + after(); + } + } + }; + } + + /** + * Override to set up your specific external resource. + * @throws if setup fails (which will disable {@code after} + */ + protected void before() throws Throwable { + // do nothing + } + + /** + * Override to tear down your specific external resource. + */ + protected void after() { + // do nothing + } +} diff --git a/src/main/java/org/junit/rules/MethodRule.java b/src/main/java/org/junit/rules/MethodRule.java new file mode 100644 index 0000000..5167672 --- /dev/null +++ b/src/main/java/org/junit/rules/MethodRule.java @@ -0,0 +1,40 @@ +package org.junit.rules; + +import org.junit.Rule; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; + +/** + * A MethodRule is an alteration in how a test method is run and reported. + * Multiple {@link MethodRule}s can be applied to a test method. The + * {@link Statement} that executes the method is passed to each annotated + * {@link Rule} in turn, and each may return a substitute or modified + * {@link Statement}, which is passed to the next {@link Rule}, if any. For + * examples of how this can be useful, see these provided MethodRules, + * or write your own: + * + * <ul> + * <li>{@link ErrorCollector}: collect multiple errors in one test method</li> + * <li>{@link ExpectedException}: make flexible assertions about thrown exceptions</li> + * <li>{@link ExternalResource}: start and stop a server, for example</li> + * <li>{@link TemporaryFolder}: create fresh files, and delete after test</li> + * <li>{@link TestName}: remember the test name for use during the method</li> + * <li>{@link TestWatchman}: add logic at events during method execution</li> + * <li>{@link Timeout}: cause test to fail after a set time</li> + * <li>{@link Verifier}: fail test if object state ends up incorrect</li> + * </ul> + */ +@Deprecated +public interface MethodRule { + /** + * Modifies the method-running {@link Statement} to implement an additional + * test-running rule. + * + * @param base The {@link Statement} to be modified + * @param method The method to be run + * @param target The object on with the method will be run. + * @return a new statement, which may be the same as {@code base}, + * a wrapper around {@code base}, or a completely new Statement. + */ + Statement apply(Statement base, FrameworkMethod method, Object target); +}
\ No newline at end of file diff --git a/src/main/java/org/junit/rules/RuleChain.java b/src/main/java/org/junit/rules/RuleChain.java new file mode 100644 index 0000000..8af3c05 --- /dev/null +++ b/src/main/java/org/junit/rules/RuleChain.java @@ -0,0 +1,99 @@ +/** + * + */ +package org.junit.rules; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * The RuleChain rule allows ordering of TestRules. You create a + * {@code RuleChain} with {@link #outerRule(TestRule)} and subsequent calls of + * {@link #around(TestRule)}: + * + * <pre> + * public static class UseRuleChain { + * @Rule + * public TestRule chain= RuleChain + * .outerRule(new LoggingRule("outer rule") + * .around(new LoggingRule("middle rule") + * .around(new LoggingRule("inner rule"); + * + * @Test + * public void example() { + * assertTrue(true); + * } + * } + * </pre> + * + * writes the log + * + * <pre> + * starting outer rule + * starting middle rule + * starting inner rule + * finished inner rule + * finished middle rule + * finished outer rule + * </pre> + */ +public class RuleChain implements TestRule { + private static final RuleChain EMPTY_CHAIN= new RuleChain( + Collections.<TestRule> emptyList()); + + private List<TestRule> rulesStartingWithInnerMost; + + /** + * Returns a {@code RuleChain} without a {@link TestRule}. This method may + * be the starting point of a {@code RuleChain}. + * + * @return a {@code RuleChain} without a {@link TestRule}. + */ + public static RuleChain emptyRuleChain() { + return EMPTY_CHAIN; + } + + /** + * Returns a {@code RuleChain} with a single {@link TestRule}. This method + * is the usual starting point of a {@code RuleChain}. + * + * @param outerRule + * the outer rule of the {@code RuleChain}. + * @return a {@code RuleChain} with a single {@link TestRule}. + */ + public static RuleChain outerRule(TestRule outerRule) { + return emptyRuleChain().around(outerRule); + } + + private RuleChain(List<TestRule> rules) { + this.rulesStartingWithInnerMost= rules; + } + + /** + * Create a new {@code RuleChain}, which encloses the {@code nextRule} with + * the rules of the current {@code RuleChain}. + * + * @param enclosedRule + * the rule to enclose. + * @return a new {@code RuleChain}. + */ + public RuleChain around(TestRule enclosedRule) { + List<TestRule> rulesOfNewChain= new ArrayList<TestRule>(); + rulesOfNewChain.add(enclosedRule); + rulesOfNewChain.addAll(rulesStartingWithInnerMost); + return new RuleChain(rulesOfNewChain); + } + + /** + * {@inheritDoc} + */ + public Statement apply(Statement base, Description description) { + for (TestRule each : rulesStartingWithInnerMost) + base= each.apply(base, description); + return base; + } +}
\ No newline at end of file diff --git a/src/main/java/org/junit/rules/RunRules.java b/src/main/java/org/junit/rules/RunRules.java new file mode 100644 index 0000000..d5905b9 --- /dev/null +++ b/src/main/java/org/junit/rules/RunRules.java @@ -0,0 +1,27 @@ +package org.junit.rules; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Runs a collection of rules on a statement. + */ +public class RunRules extends Statement { + private final Statement statement; + + public RunRules(Statement base, Iterable<TestRule> rules, Description description) { + statement= applyAll(base, rules, description); + } + + @Override + public void evaluate() throws Throwable { + statement.evaluate(); + } + + private static Statement applyAll(Statement result, Iterable<TestRule> rules, + Description description) { + for (TestRule each : rules) + result= each.apply(result, description); + return result; + } +} diff --git a/src/main/java/org/junit/rules/TemporaryFolder.java b/src/main/java/org/junit/rules/TemporaryFolder.java new file mode 100644 index 0000000..a7c82aa --- /dev/null +++ b/src/main/java/org/junit/rules/TemporaryFolder.java @@ -0,0 +1,113 @@ +package org.junit.rules; + +import java.io.File; +import java.io.IOException; + +import org.junit.Rule; + +/** + * 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): + * + * <pre> + * public static class HasTempFolder { + * @Rule + * public TemporaryFolder folder= new TemporaryFolder(); + * + * @Test + * public void testUsingTempFolder() throws IOException { + * File createdFile= folder.newFile("myfile.txt"); + * File createdFolder= folder.newFolder("subfolder"); + * // ... + * } + * } + * </pre> + */ +public class TemporaryFolder extends ExternalResource { + private File folder; + + @Override + protected void before() throws Throwable { + create(); + } + + @Override + protected void after() { + delete(); + } + + // testing purposes only + /** + * for testing purposes only. Do not use. + */ + public void create() throws IOException { + folder= newFolder(); + } + + /** + * Returns a new fresh file with the given name under the temporary folder. + */ + public File newFile(String fileName) throws IOException { + File file= new File(getRoot(), fileName); + file.createNewFile(); + return file; + } + + /** + * Returns a new fresh file with a random name under the temporary folder. + */ + public File newFile() throws IOException { + return File.createTempFile("junit", null, folder); + } + + /** + * Returns a new fresh folder with the given name under the temporary folder. + */ + public File newFolder(String... folderNames) { + File file = getRoot(); + for (String folderName : folderNames) { + file = new File(file, folderName); + file.mkdir(); + } + return file; + } + + /** + * Returns a new fresh folder with a random name under the temporary + * folder. + */ + public File newFolder() throws IOException { + File createdFolder= File.createTempFile("junit", "", folder); + createdFolder.delete(); + createdFolder.mkdir(); + return createdFolder; + } + + /** + * @return the location of this temporary folder. + */ + public File getRoot() { + if (folder == null) { + throw new IllegalStateException("the temporary folder has not yet been created"); + } + return folder; + } + + /** + * Delete all files and folders under the temporary folder. + * Usually not called directly, since it is automatically applied + * by the {@link Rule} + */ + public void delete() { + recursiveDelete(folder); + } + + private void recursiveDelete(File file) { + File[] files= file.listFiles(); + if (files != null) + for (File each : files) + recursiveDelete(each); + file.delete(); + } +} diff --git a/src/main/java/org/junit/rules/TestName.java b/src/main/java/org/junit/rules/TestName.java new file mode 100644 index 0000000..c4ab9ce --- /dev/null +++ b/src/main/java/org/junit/rules/TestName.java @@ -0,0 +1,39 @@ +package org.junit.rules; + +import org.junit.runner.Description; + +/** + * The TestName Rule makes the current test name available inside test methods: + * + * <pre> + * public class TestNameTest { + * @Rule + * public TestName name= new TestName(); + * + * @Test + * public void testA() { + * assertEquals("testA", name.getMethodName()); + * } + * + * @Test + * public void testB() { + * assertEquals("testB", name.getMethodName()); + * } + * } + * </pre> + */ +public class TestName extends TestWatcher { + private String fName; + + @Override + protected void starting(Description d) { + fName= d.getMethodName(); + } + + /** + * @return the name of the currently-running test method + */ + public String getMethodName() { + return fName; + } +} diff --git a/src/main/java/org/junit/rules/TestRule.java b/src/main/java/org/junit/rules/TestRule.java new file mode 100644 index 0000000..b7760c4 --- /dev/null +++ b/src/main/java/org/junit/rules/TestRule.java @@ -0,0 +1,54 @@ +package org.junit.rules; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * A TestRule is an alteration in how a test method, or set of test methods, + * is run and reported. A {@link TestRule} may add additional checks that cause + * a test that would otherwise fail to pass, or it may perform necessary setup or + * cleanup for tests, or it may observe test execution to report it elsewhere. + * {@link TestRule}s can do everything that could be done previously with + * methods annotated with {@link org.junit.Before}, + * {@link org.junit.After}, {@link org.junit.BeforeClass}, or + * {@link org.junit.AfterClass}, but they are more powerful, and more easily + * shared + * between projects and classes. + * + * The default JUnit test runners for suites and + * individual test cases recognize {@link TestRule}s introduced in two different + * ways. {@link org.junit.Rule} annotates method-level + * {@link TestRule}s, and {@link org.junit.ClassRule} + * annotates class-level {@link TestRule}s. See Javadoc for those annotations + * for more information. + * + * Multiple {@link TestRule}s can be applied to a test or suite execution. The + * {@link Statement} that executes the method or suite is passed to each annotated + * {@link org.junit.Rule} in turn, and each may return a substitute or modified + * {@link Statement}, which is passed to the next {@link org.junit.Rule}, if any. For + * examples of how this can be useful, see these provided TestRules, + * or write your own: + * + * <ul> + * <li>{@link ErrorCollector}: collect multiple errors in one test method</li> + * <li>{@link ExpectedException}: make flexible assertions about thrown exceptions</li> + * <li>{@link ExternalResource}: start and stop a server, for example</li> + * <li>{@link TemporaryFolder}: create fresh files, and delete after test</li> + * <li>{@link TestName}: remember the test name for use during the method</li> + * <li>{@link TestWatcher}: add logic at events during method execution</li> + * <li>{@link Timeout}: cause test to fail after a set time</li> + * <li>{@link Verifier}: fail test if object state ends up incorrect</li> + * </ul> + */ +public interface TestRule { + /** + * Modifies the method-running {@link Statement} to implement this + * test-running rule. + * + * @param base The {@link Statement} to be modified + * @param description A {@link Description} of the test implemented in {@code base} + * @return a new statement, which may be the same as {@code base}, + * a wrapper around {@code base}, or a completely new Statement. + */ + Statement apply(Statement base, Description description); +} diff --git a/src/main/java/org/junit/rules/TestWatcher.java b/src/main/java/org/junit/rules/TestWatcher.java new file mode 100644 index 0000000..351b449 --- /dev/null +++ b/src/main/java/org/junit/rules/TestWatcher.java @@ -0,0 +1,94 @@ +package org.junit.rules; + +import org.junit.internal.AssumptionViolatedException; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * TestWatcher 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: + * + * <pre> + * public static class WatchmanTest { + * private static String watchedLog; + * + * @Rule + * public MethodRule watchman= new TestWatcher() { + * @Override + * protected void failed(Description d) { + * watchedLog+= d + "\n"; + * } + * + * @Override + * protected void succeeded(Description d) { + * watchedLog+= d + " " + "success!\n"; + * } + * }; + * + * @Test + * public void fails() { + * fail(); + * } + * + * @Test + * public void succeeds() { + * } + * } + * </pre> + */ +public abstract class TestWatcher implements TestRule { + public Statement apply(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + starting(description); + try { + base.evaluate(); + succeeded(description); + } catch (AssumptionViolatedException e) { + throw e; + } catch (Throwable t) { + failed(t, description); + throw t; + } finally { + finished(description); + } + } + }; + } + + /** + * Invoked when a test succeeds + * + * @param description + */ + protected void succeeded(Description description) { + } + + /** + * Invoked when a test fails + * + * @param e + * @param description + */ + protected void failed(Throwable e, Description description) { + } + + /** + * Invoked when a test is about to start + * + * @param description + */ + protected void starting(Description description) { + } + + + /** + * Invoked when a test method finishes (whether passing or failing) + * + * @param description + */ + protected void finished(Description description) { + } +} diff --git a/src/main/java/org/junit/rules/TestWatchman.java b/src/main/java/org/junit/rules/TestWatchman.java new file mode 100644 index 0000000..15daa64 --- /dev/null +++ b/src/main/java/org/junit/rules/TestWatchman.java @@ -0,0 +1,100 @@ +package org.junit.rules; + +import org.junit.internal.AssumptionViolatedException; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; + +/** + * 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: + * + * <pre> + * public static class WatchmanTest { + * private static String watchedLog; + * + * @Rule + * public MethodRule watchman= new TestWatchman() { + * @Override + * public void failed(Throwable e, FrameworkMethod method) { + * watchedLog+= method.getName() + " " + e.getClass().getSimpleName() + * + "\n"; + * } + * + * @Override + * public void succeeded(FrameworkMethod method) { + * watchedLog+= method.getName() + " " + "success!\n"; + * } + * }; + * + * @Test + * public void fails() { + * fail(); + * } + * + * @Test + * public void succeeds() { + * } + * } + * </pre> + * + * @deprecated {@link MethodRule} is deprecated. + * Use {@link TestWatcher} implements {@link TestRule} instead. + */ +@Deprecated +public class TestWatchman implements MethodRule { + public Statement apply(final Statement base, final FrameworkMethod method, + Object target) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + starting(method); + try { + base.evaluate(); + succeeded(method); + } catch (AssumptionViolatedException e) { + throw e; + } catch (Throwable t) { + failed(t, method); + throw t; + } finally { + finished(method); + } + } + }; + } + + /** + * Invoked when a test method succeeds + * + * @param method + */ + public void succeeded(FrameworkMethod method) { + } + + /** + * Invoked when a test method fails + * + * @param e + * @param method + */ + public void failed(Throwable e, FrameworkMethod method) { + } + + /** + * Invoked when a test method is about to start + * + * @param method + */ + public void starting(FrameworkMethod method) { + } + + + /** + * Invoked when a test method finishes (whether passing or failing) + * + * @param method + */ + public void finished(FrameworkMethod method) { + } +} diff --git a/src/main/java/org/junit/rules/Timeout.java b/src/main/java/org/junit/rules/Timeout.java new file mode 100644 index 0000000..85ce6d6 --- /dev/null +++ b/src/main/java/org/junit/rules/Timeout.java @@ -0,0 +1,49 @@ +/** + * + */ +package org.junit.rules; + +import org.junit.internal.runners.statements.FailOnTimeout; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * The Timeout Rule applies the same timeout to all test methods in a class: + * + * <pre> + * public static class HasGlobalTimeout { + * public static String log; + * + * @Rule + * public MethodRule globalTimeout= new Timeout(20); + * + * @Test + * public void testInfiniteLoop1() { + * log+= "ran1"; + * for (;;) { + * } + * } + * + * @Test + * public void testInfiniteLoop2() { + * log+= "ran2"; + * for (;;) { + * } + * } + * } + * </pre> + */ +public class Timeout implements TestRule { + private final int fMillis; + + /** + * @param millis the millisecond timeout + */ + public Timeout(int millis) { + fMillis= millis; + } + + public Statement apply(Statement base, Description description) { + return new FailOnTimeout(base, fMillis); + } +}
\ No newline at end of file diff --git a/src/main/java/org/junit/rules/Verifier.java b/src/main/java/org/junit/rules/Verifier.java new file mode 100644 index 0000000..be1a55e --- /dev/null +++ b/src/main/java/org/junit/rules/Verifier.java @@ -0,0 +1,45 @@ +package org.junit.rules; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * 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 + * + * <pre> + * public static class ErrorLogVerifier() { + * private ErrorLog errorLog = new ErrorLog(); + * + * @Rule + * public MethodRule verifier = new Verifier() { + * @Override public void verify() { + * assertTrue(errorLog.isEmpty()); + * } + * } + * + * @Test public void testThatMightWriteErrorLog() { + * // ... + * } + * } + * </pre> + */ +public class Verifier implements TestRule { + public Statement apply(final Statement base, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + base.evaluate(); + verify(); + } + }; + } + + /** + * Override this to add verification logic. Overrides should throw an + * exception to indicate that verification failed. + */ + protected void verify() throws Throwable { + } +} |