pax_global_header 0000666 0000000 0000000 00000000064 12163402652 0014513 g ustar 00root root 0000000 0000000 52 comment=17a94641942546e21f4c6b300a3360be2d2888f6
test-interface-1.0/ 0000775 0000000 0000000 00000000000 12163402652 0014270 5 ustar 00root root 0000000 0000000 test-interface-1.0/.gitattributes 0000664 0000000 0000000 00000000340 12163402652 0017160 0 ustar 00root root 0000000 0000000 # Set default behaviour, in case users don't have core.autocrlf set.
* text=auto
# Explicitly declare text files we want to always be normalized and converted
# to native line endings on checkout.
*.scala text
*.java text
test-interface-1.0/LICENSE 0000664 0000000 0000000 00000002602 12163402652 0015275 0 ustar 00root root 0000000 0000000 Copyright (c) 2009, 2010 Josh Cough, Mark Harrah
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
test-interface-1.0/README 0000664 0000000 0000000 00000000400 12163402652 0015142 0 ustar 00root root 0000000 0000000 To build, run 'sbt package'
For test framework authors, the interfaces to implement are:
* Framework
* Runner2
* Fingerprint (one of SubclassFingerprint or AnnotatedFingerprint)
For test framework clients, Logger and EventHandler must be implemented.
test-interface-1.0/build.sbt 0000664 0000000 0000000 00000003352 12163402652 0016104 0 ustar 00root root 0000000 0000000 name := "test-interface"
organization := "org.scala-sbt"
version := "1.0"
description := "Uniform test interface to Scala/Java test frameworks (specs, ScalaCheck, ScalaTest, JUnit and other)"
scalaVersion := "2.10.2"
// disable using the Scala version in output paths and artifacts
crossPaths := false
autoScalaLibrary := false
resolvers ++= Seq("releases" at "http://oss.sonatype.org/content/repositories/releases",
"snapshots" at "http://oss.sonatype.org/content/repositories/snapshots",
"localmaven" at "file://"+Path.userHome+"/.m2/repository")
publishTo <<= version { v: String =>
val nexus = "https://oss.sonatype.org/"
if (v.trim.endsWith("SNAPSHOT")) Some("publish-snapshots" at nexus + "content/repositories/snapshots")
else Some("publish-releases" at nexus + "service/local/staging/deploy/maven2")
}
libraryDependencies += "org.scalatest" % "scalatest_2.10" % "2.0.M6-SNAP24" % "test"
publishMavenStyle := true
publishArtifact in Test := false
pomIncludeRepository := { _ => false }
pomExtra := (
* If a test framework allows both classes and modules, they should return two different
* fingerprints from Framework.fingerprints
, one that returns false
for
* isModule
and another that returns true
.
*
fullyQualifiedName
* method on this Event
. If the isModule
method of the fingerprint indicates that the
* fullyQualifiedName
refers to a module (singleton object), the
* fullyQualifiedName
string does not include the trailing dollar sign.
*/
Fingerprint fingerprint();
/**
* Additional information identifying the suite or test about which an event was fired.
*/
Selector selector();
/**
* Indicates whether the event represents a test success, failure, error, skipped, ignored, canceled, pending.
*/
Status status();
/**
* An OptionalThrowable
associated with this Event
.
*/
OptionalThrowable throwable();
/**
* An amount of time, in milliseconds, that was required to complete the action reported by this event, or -1, if no duration was available.
*/
long duration();
}
test-interface-1.0/src/main/java/sbt/testing/EventHandler.java 0000664 0000000 0000000 00000000661 12163402652 0024416 0 ustar 00root root 0000000 0000000 package sbt.testing;
/**
* Interface implemented by clients that handle events fired by the test framework
* during a run.
*
*
* An event handler is passed to the test framework via the execute
method
* of Task
s.
*
Fingerprint
s that specify how to identify test classes during
* discovery.
*/
public Fingerprint[] fingerprints();
/**
* Initiates a run.
*
*
* If a client invokes this method before a previously initiated run has completed,
* the test framework may throw IllegalStateException
to indicate it
* cannot perform the two runs concurrently.
*
Runner
representing the newly started run.
* @throws IllegalStateException if the test framework is unable to initiate a run because it is
* already performing a previously initiated run that has not yet completed.
*/
public Runner runner(String[] args, String[] remoteArgs, ClassLoader testClassLoader);
}
test-interface-1.0/src/main/java/sbt/testing/Logger.java 0000664 0000000 0000000 00000002303 12163402652 0023251 0 ustar 00root root 0000000 0000000 package sbt.testing;
/**
* A logger through which to provide feedback to the user about a run.
*
* * The difference between the event handler and the logger is that the event handler is * for events intended to be consumed by the client software whereas the logger is * for messages intended to be consumed by the client *user* (i.e., a human). *
* ** Implementations of this interface must be thread-safe. *
*/ public interface Logger { /** * True if ANSI color codes are understood by this instance. */ public boolean ansiCodesSupported(); /** * Provide an error message. * * @param msg the error message */ public void error(String msg); /** * Provide an warning message. * * @param msg the warning message */ public void warn(String msg); /** * Provide an info message. * * @param msg the info message */ public void info(String msg); /** * Provide a debug message. * * @param msg the debug message */ public void debug(String msg); /** * Provide a stack trace * * @param t theThrowable
containing the stack trace being logged
*/
public void trace(Throwable t);
}
test-interface-1.0/src/main/java/sbt/testing/NestedSuiteSelector.java 0000664 0000000 0000000 00000002335 12163402652 0025774 0 ustar 00root root 0000000 0000000 package sbt.testing;
import java.io.Serializable;
/**
* Information in addition to a test class name that identifies a nested suite about which an
* event was fired.
*/
public final class NestedSuiteSelector extends Selector implements Serializable {
private String _suiteId;
/**
* Constructs a new NestedSuiteSelector
with given suiteId
.
*
* @param suiteId the id of the nested suite
*/
public NestedSuiteSelector(String suiteId) {
if (suiteId == null) {
throw new NullPointerException("suiteId was null");
}
_suiteId = suiteId;
}
/**
* An id that, in addition to a test class name, identifies a nested suite about which an
* event was fired.
*
* @return the id of the nested suite
*/
public String suiteId() {
return _suiteId;
}
@Override public boolean equals(Object o) {
boolean retVal = false;
if (o instanceof NestedSuiteSelector) {
NestedSuiteSelector nss = (NestedSuiteSelector) o;
retVal = nss._suiteId == _suiteId;
}
return retVal;
}
@Override public int hashCode() {
return _suiteId.hashCode();
}
@Override public String toString() {
return "NestedSuiteSelector(" + _suiteId + ")";
}
}
test-interface-1.0/src/main/java/sbt/testing/NestedTestSelector.java 0000664 0000000 0000000 00000003675 12163402652 0025632 0 ustar 00root root 0000000 0000000 package sbt.testing;
import java.io.Serializable;
/**
* Information in addition to a test class name that identifies a test in a nested suite about which an
* event was fired.
*/
public final class NestedTestSelector extends Selector implements Serializable {
private String _suiteId;
private String _testName;
/**
* Constructs a new NestedSuiteSelector
with given suiteId
and testName
.
*
* @param suiteId the id of the nested suite containing the test
* @param testName the name of the test
*/
public NestedTestSelector(String suiteId, String testName) {
if (suiteId == null) {
throw new NullPointerException("suiteId was null");
}
if (testName == null) {
throw new NullPointerException("testName was null");
}
_suiteId = suiteId;
_testName = testName;
}
/**
* An id that, in addition to a test class name, identifies a nested suite that contains a test
* about which an event was fired.
*
* @return the id of the nested suite containing the test
*/
public String suiteId() {
return _suiteId;
}
/**
* The name of the test in a nested suite about which an event was fired.
*
* @return the name of the test in the nested suite identified by the id returned by suiteId
.
*/
public String testName() {
return _testName;
}
@Override public boolean equals(Object o) {
boolean retVal = false;
if (o instanceof NestedTestSelector) {
NestedTestSelector nts = (NestedTestSelector) o;
retVal =
nts._suiteId.equals(_suiteId) &&
nts._testName.equals(_testName);
}
return retVal;
}
@Override public int hashCode() {
int retVal = 17;
retVal = 31 * retVal + _suiteId.hashCode();
retVal = 31 * retVal + _testName.hashCode();
return retVal;
}
@Override public String toString() {
return "NestedTestSelector(" + _suiteId + ", " + _testName + ")";
}
}
test-interface-1.0/src/main/java/sbt/testing/OptionalThrowable.java 0000664 0000000 0000000 00000004654 12163402652 0025502 0 ustar 00root root 0000000 0000000 package sbt.testing;
import java.io.Serializable;
/**
* An optional Throwable
.
*/
public final class OptionalThrowable implements Serializable {
private Throwable exception;
/**
* Constructs an OptionalThrowable
containing a Throwable
.
*/
public OptionalThrowable(Throwable exception) {
if (exception == null) {
throw new NullPointerException("Cannot pass a null exception to OptionalThrowable's constructor.");
}
this.exception = exception;
}
/**
* Constructs an OptionalThrowable
containing no Throwable
.
*/
public OptionalThrowable() {
}
/**
* Indicates whether this OptionalThrowable
is "defined," i.e., contains a Throwable
.
*
* @return true if this OptionalThrowable
contains a Throwable
*/
public boolean isDefined() {
return exception != null;
}
/**
* Indicates whether this OptionalThrowable
is "empty," i.e., contains no Throwable
.
*
* @return true if this OptionalThrowable
contains no Throwable
*/
public boolean isEmpty() {
return exception == null;
}
/**
* Returns the Throwable
contained in this OptionalThrowable
if defined, else throws IllegalStateException
.
*
*
* To avoid the IllegalStateException
, ensure isDefined
returns true
before calling this method.
*
Throwable
, if this OptionalThrowable
is defined
* @throws IllegalStateException if this OptionalThrowable
is not defined.
*/
public Throwable get() {
if (exception == null) {
throw new IllegalStateException("This OptionalThrowable is not defined");
}
return exception;
}
@Override public boolean equals(Object o) {
boolean retVal = false;
if (o instanceof OptionalThrowable) {
OptionalThrowable ot = (OptionalThrowable) o;
retVal = ot.exception == exception;
}
return retVal;
}
@Override public int hashCode() {
return (exception == null) ? 0 : exception.hashCode();
}
@Override public String toString() {
String retVal = "OptionalThrowable()";
if (exception != null) {
retVal = "OptionalThrowable(" + exception + ")";
}
return retVal;
}
}
test-interface-1.0/src/main/java/sbt/testing/Runner.java 0000664 0000000 0000000 00000011104 12163402652 0023302 0 ustar 00root root 0000000 0000000 package sbt.testing;
/**
* Represents one run of a suite of tests.
*
*
* The run represented by a Runner
has a lifecycle. The run begins when the
* Runner
is instantiated by the framework and returned to the client during
* a Framework.runner
invocation. The run continues until the client
* invokes done
on the Runner
. Before invoking done
,
* the client can invoke the tasks
method as many times at it wants, but once
* done
has been invoked, the Runner
enters "spent" mode. Any
* subsequent invocations of tasks
will be met with an
* IllegalStateException
.
*
TaskDef
s.
*
*
* Each returned task, when executed, will run tests and suites determined by the
* test class name, fingerprints, "explicitly specified" field, and selectors of one of the passed TaskDef
s.
*
* This tasks
method may be called with TaskDef
s containing the same value for testClassName
but
* different fingerprints. For example, if both a class and its companion object were test classes, the tasks
method could be
* passed an array containing TaskDef
s with the same name but with a different value for fingerprint.isModule
.
*
* A test framework may "reject" a requested task by returning no Task
for that TaskDef
.
*
TaskDef
s for requested tasks
* @return an array of Task
s
* @throws IllegalStateException if invoked after done
has been invoked.
*/
public Task[] tasks(TaskDef[] taskDefs);
/**
* Indicates the client is done with this Runner
instance.
*
*
* After invoking the done
method on a Runner
instance, the client should no
* longer invoke the task
methods on that instance. (If the client does invoke task
* after done
, it will be rewarded with an IllegalStateException
.)
*
* Similarly, after returning from done
, the test framework should no longer write
* any messages to the Logger
, nor fire any more events to the EventHandler
,
* passed to Framework.runner
. If the test framework has not completed writing log messages
* or firing events when the client invokes done
, the framework should not return from
* done
until it is finished sending messages and events, and may block the thread
* that invoked done
until it is actually done.
*
* In short, by invoking done
, the client indicates it is done invoking the task
* methods for this run. By returning from done
, the test framework indicates it is done writing
* log messages and firing events for this run.
*
* If the client invokes done
more than once on the same Runner
instance, the test
* framework should on subsequent invocations should throw IllegalStateException
.
*
* The test framework may send a summary (i.e., a message giving total tests succeeded, failed, and
* so on) to the user via a log message. If so, it should return the summary from done
.
* If not, it should return an empty string. The client may use the return value of done
* to decide whether to display its own summary message.
*
* The test framework may return a multi-lines string (i.e., a message giving total tests succeeded, failed and * so on) to the client. *
* * @return a possibly multi-line summary string, or the enpty string if no summary is provided */ public String done(); /** * Remote args that will be passed toRunner
in a sub-process as remoteArgs.
*
* @return an array of strings that will be passed to Runner
in a sub-process as remoteArgs
.
*/
public String[] remoteArgs();
/**
* Returns thge arguments that were used to create this Runner
.
*
* @return an array of argument that is used to create this Runner.
*/
public String[] args();
}
test-interface-1.0/src/main/java/sbt/testing/Selector.java 0000664 0000000 0000000 00000002421 12163402652 0023613 0 ustar 00root root 0000000 0000000 package sbt.testing;
/**
* Information in addition to a test class name that identifies the suite or test about which an
* event was fired.
*
* * This class has five subtypes: *
* *SuiteSelector
- indicates an event is about an entire suite of tests whose
* class was reported as fullyQualifiedName
in the Event
TestSelector
- indicates an event is about a single test directly contained
* in the suite whose class was reported as fullyQualifiedName
in the Event
NestedSuiteSelector
- indicates an event is about an entire nested suite of tests whose
* top-level, "nesting" class was reported as fullyQualifiedName
in the Event
NestedTestSelector
- indicates an event is about a single test contained
* in a nested suite whose top-level, "nesting" class was reported as fullyQualifiedName
in the Event
TestWildcardSelector
- indicates an event is about zero to many tests directly contained
* in the suite whose class was reported as fullyQualifiedName
in the Event
* The difference between errors and failures, if any, is determined by the test frameworks. * JUnit and specs2 differentiate between errors and failures. ScalaTest reports everything (both assertion failures and unexpected errors) as failures. * JUnit and ScalaTest support ignored tests. ScalaTest and specs2 support a notion of pending tests. ScalaTest differentiates between ignored and * canceled tests, whereas specs2 only supports skipped tests, which are implemented like ScalaTest's canceled tests. TestNG uses "skipped" to report tests * that were not executed because of failures in dependencies, which is also similar to canceled tests in ScalaTest. *
*/ public enum Status { /** * Indicates a test succeeded. */ Success, /** * Indicates an "error" occurred. */ Error, /** * Indicates a "failure" occurred. */ Failure, /** * Indicates a test was skipped. */ Skipped, /** * Indicates a test was ignored. */ Ignored, /** * Indicates a test was canceled. */ Canceled, /** * Indicates a test was declared as pending. */ Pending } test-interface-1.0/src/main/java/sbt/testing/SubclassFingerprint.java 0000664 0000000 0000000 00000002402 12163402652 0026021 0 ustar 00root root 0000000 0000000 package sbt.testing; /** * Indicates that classes (and possibly modules) that extend a particular superclass, * or mix in a particular supertrait, should be discovered as test classes. */ public interface SubclassFingerprint extends Fingerprint { /** * Indicates whether modules (singleton objects) that extend the superclass or * supertrait should be considered during discovery, or just classes. * *
* If modules are not allowed by the test framework, they should return false
for
* isModule
. Returning false
will speed up discovery because
* classes for modules can be quickly bypassed.
*
* If this method returns true
, the client should not discover any subclass of
* the given superClassName
that does not declare a no-arg constructor, i.e.,
* a constructor that takes no arguments.
*
fullyQualifiedName
attribute the event.
*/
public final class SuiteSelector extends Selector implements Serializable {
@Override public boolean equals(Object o) {
return o instanceof SuiteSelector;
}
@Override public int hashCode() {
return 29;
}
@Override public String toString() {
return "SuiteSelector";
}
}
test-interface-1.0/src/main/java/sbt/testing/Task.java 0000664 0000000 0000000 00000002666 12163402652 0022750 0 ustar 00root root 0000000 0000000 package sbt.testing;
/**
* A task to execute.
*
* * The client may decide when or how to execute the task based on its tags. * A task can be any job, but is primarily intended for running tests and/or supplying more tasks * to the client. A framework can supply more tasks * to the client in the returned an array of Tasks (which can be empty if there's * no more work to do.) *
*/ public interface Task { /** * A possibly zero-length array of string tags associated with this task. * ** A task may be tagged, for example, with a string that indicates it consumes a lot * of CPU time. Users can configure the client to only run, say, three such CPU-intensive * tasks concurrently. *
* * @return a possibly zero-length string array of this task's tags */ String[] tags(); /** * Executes this task, possibly returning to the client new tasks to execute. * * @param eventHandler an event handler to which to fire events during the run * @param loggers an array of loggers to which to emit log messages during the run * @return a possibly empty array of new tasks for the client to execute */ Task[] execute(EventHandler eventHandler, Logger[] loggers); /** * Returns theTaskDef
that was used to request this Task
.
*
* @return the TaskDef
that was used to request this Task
.
*/
TaskDef taskDef();
}
test-interface-1.0/src/main/java/sbt/testing/TaskDef.java 0000664 0000000 0000000 00000012450 12163402652 0023357 0 ustar 00root root 0000000 0000000 package sbt.testing;
import java.util.Arrays;
import java.io.Serializable;
/**
* A bundle of information used to request a Task
from a test framework.
*
*
* An array of TaskDef
is passed to Runner
's tasks
method, which returns
* an array of Tasks
. Each returned task, when executed, will run tests and suites determined by the
* test class name, fingerprints, "explicitly specified" field, and selectors of one of the passed TaskDef
s.
*
* The "Explicitly specified" field means the user supplied a complete fully qualified test name, such as with the command: *
* *
* > test-only com.mycompany.myproject.WholeNameSpec
*
*
* * as opposed to commands like: *
* *
* > test-only *WholeNameSpec
*
*
* * or simply: *
* ** > test ** *
* The explicitlySpecified
field will be true for in the first case, and false in the last two cases, because only
* in the first case was the fully qualified test class name completely specified by the user. The test framework can use this information
* to decide whether to ignore an annotation requesting a class not be discovered.
*
* The fingerprint
parameter indicates how the test suite was identified as a test suite. This tasks
* method may be called with TaskDef
s containing the same value for testClassName
but different fingerprints.
* For example, if both a class and its companion object were test classes, the tasks
method could be passed an array containing
* TaskDef
s with the same name but with a different value for fingerprint.isModule
.
*
* A test framework may "reject" a requested task by returning no Task
for that TaskDef
.
*
TaskDef
with the given fully qualified name, fingerprint, "explicitly specified" fag, and array
* of selectors.
*
* @param fullyQualifiedName the fully qualified name of the test class to be run by the requested task
* @param fingerprint indicates how the test suite was identified as a test suite.
* @param explicitlySpecified indicates whether the test class was explicitly specified by user.
* @param selectors a possibly empty array of Selectors
determining suites and tests to run
*/
public TaskDef(String fullyQualifiedName, Fingerprint fingerprint, boolean explicitlySpecified, Selector[] selectors) {
if (fullyQualifiedName == null) {
throw new NullPointerException("fullyQualifiedName was null");
}
if (fingerprint == null) {
throw new NullPointerException("fingerprint was null");
}
if (selectors == null) {
throw new NullPointerException("selectors was null");
}
_fullyQualifiedName = fullyQualifiedName;
_fingerprint = fingerprint;
_explicitlySpecified = explicitlySpecified;
_selectors = selectors;
}
/**
* The fully qualified name of the test class requested by this TaskDef
.
*/
public String fullyQualifiedName() {
return _fullyQualifiedName;
}
/**
* The fingerprint that the test class requested by this TaskDef
matches.
*/
public Fingerprint fingerprint() {
return _fingerprint;
}
/**
* Indicates whether or not the test class requested by this TaskDef
was "explicitly specified."
*
* * For more information on what explicitly specified means, see the main documentation for this class. *
*/ public boolean explicitlySpecified() { return _explicitlySpecified; } /** * One to many selectors describing the nature of theTask
requested by this TaskDef
.
*
*
* A Selector
can indicate a direct, such as command-line, request from the user or a "rerun" of previously run tests.
* In the latter case, the Selectors
would be taken from those passed in events of a previous run or runs.
*
fullyQualifiedName
attribute
* passed to the event.
*/
public final class TestSelector extends Selector implements Serializable {
private String _testName;
/**
* Constructs a new TestSelector
with passed testName
.
*
* @param testName the name of the test about which an event as fired.
*/
public TestSelector(String testName) {
if (testName == null) {
throw new NullPointerException("testName was null");
}
_testName = testName;
}
/**
* The name of a test about which an event was fired.
*
* @return the name of the test
*/
public String testName() {
return _testName;
}
@Override public boolean equals(Object o) {
boolean retVal = false;
if (o instanceof TestSelector) {
TestSelector ts = (TestSelector) o;
retVal = ts._testName == _testName;
}
return retVal;
}
@Override public int hashCode() {
return _testName.hashCode();
}
@Override public String toString() {
return "TestSelector(" + _testName + ")";
}
}
test-interface-1.0/src/main/java/sbt/testing/TestWildcardSelector.java 0000664 0000000 0000000 00000003626 12163402652 0026135 0 ustar 00root root 0000000 0000000 package sbt.testing;
import java.io.Serializable;
/**
* Information that identifies zero to many tests directly contained in a test class.
*
*
* The testWildcard
is a simple string, i.e., not a glob or regular expression.
* Any test whose name includes the testWildcard
string as a substring will be selected.
*
TestWildcardSelector
with passed testWildcard
.
*
*
* The testWildcard
is a simple string, i.e., not a glob or regular expression.
* Any test whose name includes the testWildcard
string as a substring will be selected.
*
* The testWildcard
is a simple string, i.e., not a glob or regular expression.
* Any test whose name includes the testWildcard
string as a substring will be selected.
*