Update of /cvsroot/junit/junit/src/org/junit/runner In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv19867/src/org/junit/runner Added Files: Request.java package-info.java Runner.java Result.java JUnitCore.java RunWith.java Description.java Log Message: Created a separate src folder for sources, and adjusted Eclipse classpath and build file accordingly --- NEW FILE: Request.java --- package org.junit.runner; import java.util.Comparator; import org.junit.internal.requests.ClassRequest; import org.junit.internal.requests.ClassesRequest; import org.junit.internal.requests.ErrorReportingRequest; import org.junit.internal.requests.FilterRequest; import org.junit.internal.requests.SortingRequest; import org.junit.runner.manipulation.Filter; /** * <p>A <code>Request</code> is an abstract description of tests to be run. Older versions of * JUnit did not need such a concept--tests to be run were described either by classes containing * tests or a tree of {@link org.junit.Test}s. However, we want to support filtering and sorting, * so we need a more abstract specification than the tests themselves and a richer * specification than just the classes.</p> * * <p>The flow when JUnit runs tests is that a <code>Request</code> specifies some tests to be run -> * a {@link org.junit.runner.Runner} is created for each class implied by the <code>Request</code> -> * the {@link org.junit.runner.Runner} returns a detailed {@link org.junit.runner.Description} * which is a tree structure of the tests to be run.</p> */ public abstract class Request { /** * Create a <code>Request</code> that, when processed, will run a single test. * This is done by filtering out all other tests. This method is used to support rerunning * single tests. * @param clazz the class of the test * @param methodName the name of the test * @return a <code>Request</code> that will cause a single test be run */ public static Request method(Class<?> clazz, String methodName) { Description method= Description.createTestDescription(clazz, methodName); return Request.aClass(clazz).filterWith(method); } /** * Create a <code>Request</code> that, when processed, will run all the tests * in a class. The odd name is necessary because <code>class</code> is a reserved word. * @param clazz the class containing the tests * @return a <code>Request</code> that will cause all tests in the class to be run */ public static Request aClass(Class<?> clazz) { return new ClassRequest(clazz); } /** * Create a <code>Request</code> that, when processed, will run all the tests * in a set of classes. * @param collectionName a name to identify this suite of tests * @param classes the classes containing the tests * @return a <code>Request</code> that will cause all tests in the classes to be run */ public static Request classes(String collectionName, Class<?>... classes) { return new ClassesRequest(collectionName, classes); } public static Request errorReport(Class<?> klass, Throwable cause) { return new ErrorReportingRequest(klass, cause); } /** * Returns a {@link Runner} for this Request * @return corresponding {@link Runner} for this Request */ public abstract Runner getRunner(); /** * Returns a Request that only contains those tests that should run when * <code>filter</code> is applied * @param filter The {@link Filter} to apply to this Request * @return the filtered Request */ public Request filterWith(Filter filter) { return new FilterRequest(this, filter); } /** * Returns a Request that only runs contains tests whose {@link Description} * equals <code>desiredDescription</code> * @param desiredDescription {@link Description} of those tests that should be run * @return the filtered Request */ public Request filterWith(final Description desiredDescription) { return filterWith(new Filter() { @Override public boolean shouldRun(Description description) { // TODO: test for equality even if we have children? if (description.isTest()) return desiredDescription.equals(description); for (Description each : description.getChildren()) if (shouldRun(each)) return true; return false; } @Override public String describe() { return String.format("Method %s", desiredDescription.getDisplayName()); } }); } /** * Returns a Request whose Tests can be run in a certain order, defined by * <code>comparator</code> * @param comparator definition of the order of the tests in this Request * @return a Request with ordered Tests */ public Request sortWith(Comparator<Description> comparator) { return new SortingRequest(this, comparator); } } --- NEW FILE: package-info.java --- /** * Provides classes used to describe, collect, run and analyze multiple tests. * * @since 4.0 */ package org.junit.runner; --- NEW FILE: Runner.java --- package org.junit.runner; import org.junit.runner.notification.RunNotifier; /** * A <code>Runner</code> runs tests and notifies a {@link org.junit.runner.notification.RunNotifier} * of significant events as it does so. You will need to subclass <code>Runner</code> * when using {@link org.junit.runner.RunWith} to invoke a custom runner. When creating * a custom runner, in addition to implementing the abstract methods here you must * also provide a constructor that takes as an argument the {@link Class} containing * the tests. * <p/> * The default runner implementation guarantees that the instances of the test case * class will be constructed immediately before running the test and that the runner * will retain no reference to the test case instances, generally making them * available for garbage collection. * * @see org.junit.runner.Description * @see org.junit.runner.RunWith */ public abstract class Runner { /** * @return a {@link Description} showing the tests to be run by the receiver */ public abstract Description getDescription(); /** * Run the tests for this runner. * @param notifier will be notified of events while tests are being run--tests being * started, finishing, and failing */ public abstract void run(RunNotifier notifier); /** * @return the number of tests to be run by the receiver */ public int testCount() { return getDescription().testCount(); } } --- NEW FILE: Result.java --- package org.junit.runner; import java.util.ArrayList; import java.util.List; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; /** * A <code>Result</code> collects and summarizes information from running multiple * tests. Since tests are expected to run correctly, successful tests are only noted in * the count of tests that ran. */ public class Result { private int fCount= 0; private int fIgnoreCount= 0; private List<Failure> fFailures= new ArrayList<Failure>(); private long fRunTime= 0; private long fStartTime; /** * @return the number of tests run */ public int getRunCount() { return fCount; } /** * @return the number of tests that failed during the run */ public int getFailureCount() { return fFailures.size(); } /** * @return the number of milliseconds it took to run the entire suite to run */ public long getRunTime() { return fRunTime; } /** * @return the {@link Failure}s describing tests that failed and the problems they encountered */ public List<Failure> getFailures() { return fFailures; } /** * @return the number of tests ignored during the run */ public int getIgnoreCount() { return fIgnoreCount; } /** * @return <code>true</code> if all tests succeeded */ public boolean wasSuccessful() { return getFailureCount() == 0; } private class Listener extends RunListener { @Override public void testRunStarted(Description description) throws Exception { fStartTime= System.currentTimeMillis(); } @Override public void testRunFinished(Result result) throws Exception { long endTime= System.currentTimeMillis(); fRunTime+= endTime - fStartTime; } @Override public void testStarted(Description description) throws Exception { fCount++; } @Override public void testFailure(Failure failure) throws Exception { fFailures.add(failure); } @Override public void testIgnored(Description description) throws Exception { fIgnoreCount++; } } /** * Internal use only. */ public RunListener createListener() { return new Listener(); } } --- NEW FILE: JUnitCore.java --- package org.junit.runner; import java.util.ArrayList; import java.util.List; import junit.runner.Version; import org.junit.internal.runners.OldTestClassRunner; import org.junit.internal.runners.TextListener; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; /** * <code>JUnitCore</code> is a facade for running tests. It supports running JUnit 4 tests, * JUnit 3.8.x tests, and mixtures. To run tests from the command line, run * <code>java org.junit.runner.JUnitCore TestClass1 TestClass2 ...</code>. * For one-shot test runs, use the static method {@link #runClasses(Class[])}. * If you want to add special listeners, * create an instance of {@link org.junit.runner.JUnitCore} first and use it to run the tests. * * @see org.junit.runner.Result * @see org.junit.runner.notification.RunListener * @see org.junit.runner.Request */ public class JUnitCore { private RunNotifier fNotifier; /** * Create a new <code>JUnitCore</code> to run tests. */ public JUnitCore() { fNotifier= new RunNotifier(); } /** * Run the tests contained in the classes named in the <code>args</code>. * If all tests run successfully, exit with a status of 0. Otherwise exit with a status of 1. * Write feedback while tests are running and write * stack traces for all failed tests after the tests all complete. * @param args names of classes in which to find tests to run */ public static void main(String... args) { Result result= new JUnitCore().runMain(args); killAllThreads(result); } private static void killAllThreads(Result result) { System.exit(result.wasSuccessful() ? 0 : 1); } /** * Run the tests contained in <code>classes</code>. Write feedback while the tests * are running and write stack traces for all failed tests after all tests complete. This is * similar to {@link #main(String[])}, but intended to be used programmatically. * @param classes Classes in which to find tests * @return a {@link Result} describing the details of the test run and the failed tests. */ public static Result runClasses(Class<?>... classes) { return new JUnitCore().run(classes); } /** * Do not use. Testing purposes only. */ public Result runMain(String... args) { System.out.println("JUnit version " + Version.id()); List<Class<?>> classes= new ArrayList<Class<?>>(); List<Failure> missingClasses= new ArrayList<Failure>(); for (String each : args) try { classes.add(Class.forName(each)); } catch (ClassNotFoundException e) { System.out.println("Could not find class: " + each); Description description= Description.createSuiteDescription(each); Failure failure= new Failure(description, e); missingClasses.add(failure); } RunListener listener= new TextListener(); addListener(listener); Result result= run(classes.toArray(new Class[0])); for (Failure each : missingClasses) result.getFailures().add(each); return result; } /** * @return the version number of this release */ public String getVersion() { return Version.id(); } /** * Run all the tests in <code>classes</code>. * @param classes the classes containing tests * @return a {@link Result} describing the details of the test run and the failed tests. */ public Result run(Class<?>... classes) { return run(Request.classes("All", classes)); } /** * Run all the tests contained in <code>request</code>. * @param request the request describing tests * @return a {@link Result} describing the details of the test run and the failed tests. */ public Result run(Request request) { return run(request.getRunner()); } /** * Run all the tests contained in JUnit 3.8.x <code>test</code>. Here for backward compatibility. * @param test the old-style test * @return a {@link Result} describing the details of the test run and the failed tests. */ public Result run(junit.framework.Test test) { return run(new OldTestClassRunner(test)); } /** * Do not use. Testing purposes only. */ public Result run(Runner runner) { Result result= new Result(); RunListener listener= result.createListener(); addFirstListener(listener); try { fNotifier.fireTestRunStarted(runner.getDescription()); runner.run(fNotifier); fNotifier.fireTestRunFinished(result); } finally { removeListener(listener); } return result; } private void addFirstListener(RunListener listener) { fNotifier.addFirstListener(listener); } /** * Add a listener to be notified as the tests run. * @param listener the listener to add * @see org.junit.runner.notification.RunListener */ public void addListener(RunListener listener) { fNotifier.addListener(listener); } /** * Remove a listener. * @param listener the listener to remove */ public void removeListener(RunListener listener) { fNotifier.removeListener(listener); } } --- NEW FILE: RunWith.java --- package org.junit.runner; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //TODO add simple example /** * When a class is annotated with <code>@RunWith</code> or extends a class annotated * with <code>@RunWith</code>, JUnit will invoke the class it references to run the * tests in that class instead of the runner built into JUnit. We added this feature late * in development. While it seems powerful we expect the runner API to change as we learn * how people really use it. Some of the classes that are currently internal will likely * be refined and become public. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited public @interface RunWith { /** * @return a Runner class (must have a constructor that takes a single Class to run) */ Class<? extends Runner> value(); } --- NEW FILE: Description.java --- package org.junit.runner; import java.util.ArrayList; /** * <p>A <code>Description</code> describes a test which is to be run or has been run. <code>Descriptions</code> * can be atomic (a single test) or compound (containing children tests). <code>Descriptions</code> are used * to provide feedback about the tests that are about to run (for example, the tree view * visible in many IDEs) or tests that have been run (for example, the failures view).</p> * * <p><code>Descriptions</code> are implemented as a single class rather than a Composite because * they are entirely informational. They contain no logic aside from counting their tests.</p> * * <p>In the past, we used the raw {@link junit.framework.TestCase}s and {@link junit.framework.TestSuite}s * to display the tree of tests. This was no longer viable in JUnit 4 because atomic tests no longer have * a superclass below {@link Object}. We needed a way to pass a class and name together. Description * emerged from this.</p> * * @see org.junit.runner.Request * @see org.junit.runner.Runner */ public class Description { /** * Create a <code>Description</code> named <code>name</code>. * Generally, you will add children to this <code>Description</code>. * @param name the name of the <code>Description</code> * @return a <code>Description</code> named <code>name</code> */ public static Description createSuiteDescription(String name) { return new Description(name); } /** * Create a <code>Description</code> of a single test named <code>name</code> in the class <code>clazz</code>. * Generally, this will be a leaf <code>Description</code>. * @param clazz the class of the test * @param name the name of the test (a method name for test annotated with {@link org.junit.Test}) * @return a <code>Description</code> named <code>name</code> */ public static Description createTestDescription(Class<?> clazz, String name) { return new Description(String.format("%s(%s)", name, clazz.getName())); } /** * Create a generic <code>Description</code> that says there are tests in <code>testClass</code>. * This is used as a last resort when you cannot precisely describe the individual tests in the class. * @param testClass A {@link Class} containing tests * @return a <code>Description</code> of <code>testClass</code> */ public static Description createSuiteDescription(Class<?> testClass) { return new Description(testClass.getName()); } public static Description TEST_MECHANISM = new Description("Test mechanism"); private final ArrayList<Description> fChildren= new ArrayList<Description>(); private final String fDisplayName; //TODO we seem to be using the static factories exclusively protected Description(final String displayName) { fDisplayName= displayName; } /** * @return a user-understandable label */ public String getDisplayName() { return fDisplayName; } /** * Add <code>Description</code> as a child of the receiver. * @param description the soon-to-be child. */ public void addChild(Description description) { getChildren().add(description); } /** * @return the receiver's children, if any */ public ArrayList<Description> getChildren() { return fChildren; } /** * @return <code>true</code> if the receiver is a suite */ public boolean isSuite() { return !isTest(); } /** * @return <code>true</code> if the receiver is an atomic test */ public boolean isTest() { return getChildren().isEmpty(); } /** * @return the total number of atomic tests in the receiver */ public int testCount() { if (isTest()) return 1; int result= 0; for (Description child : getChildren()) result+= child.testCount(); return result; } @Override public int hashCode() { return getDisplayName().hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Description)) return false; Description d = (Description) obj; return getDisplayName().equals(d.getDisplayName()) && getChildren().equals(d.getChildren()); } @Override public String toString() { return getDisplayName(); } } |