Documentation
Writing Tests
Tests are written as Scala class files. One class represents a 'set' or 'suite' of tests. We don't actually specify a name, as we don't want to force you to use them one way. Our original view was that for unit testing there could be one 'Tests' class for each production class (eg a production class com/vendor/product/Connection.scala
would have a 'Tests' class com/vendor/product/ConnectionTests.scala
)
The only special need is that the class name ends in "Tests", and that it inherits from Tests. When inheriting, you tell Rehersal what test category you are using. There's an extremely large list in the rehersal.TestCategories
object. Take a look at the source in rehersal/TestCategories.scala
.
An example skeleton of a test would be
package examples
import rehersal._
import rehersal.TestCategories._
class SkeletonTests extends Tests(UnitTesting)
{
}
. Note that a completely empty test is considered a failure by
Rehersal. Take a look at a real example in the source in
examples/EmptyTestsFailTests.scala
.
Tests are written quite differently in Rehersal to other frameworks, such as JUnit or TestNG. Instead of special method names or attributes, and limitations on test names, Rehersal lets you name tests anything you like - making 'tests as documentation' mantra much more realistic!
An example test is below:
test("Example of a test that will fail")( ()=>
{
fail()
})
A test can either pass or fail. A failure occurs when any exception is thrown. The
fail()
method above throws
ExpectationFailedException
. If no expectations are thrown, then the test is considered a pass.
It is also possible to make tests expect certain exceptions. The syntax is very similar:
test("Example of expected exceptions that will pass", classOf[IndexOutOfBoundsException])( ()=>
{
throw new IndexOutOfBoundsException()
})
Whilst this would be enough for testing, if not a little basic, Rehersal also comes with a novel twist to testing. Inspired by jMock, Rehersal uses Expectations rather than Assertions. A full set can be seen in the source at rehersal/expecations
. These use Scala's support for operators and case classes to make testing expectations very, very natural. The test case example/expecations/ExpectationTests.scala
shows the whole range in action. Please note that at this time the not operator, !, is not quite as we would like. It works, but it's a bit cumbersome.
Rehersal also supports the ability to run code before and after each test, and once before and once after each use of a 'Tests' class. The aforementioned examples show how to do this, but here's a code snippet anyway:-
onceBefore = () => { note("Run once before all tests in this object") }
onceAfter = () => { note("Run once after all tests in this object, unless onceBefore failed") }
before = () => { note("Run before each test unless the test is a duplicate") }
after = () => { note("Run after each test, unless before failed") }
Unlike other test frameworks, Rehersal does not redirect System.out
, Console println
or the like. This makes it easier to integrate into other libraries and applications which do. However, if you want to record information during the build, use the note()
method instead. This supports standard Java 'printf' string formatting using variable arguments for convenience.
Using the Command Line
To use Rehersal from the command line, use either java
or scala
. The jar file rehersal.jar
, in the binaries
folder, has a main class and class path defined. All you should need to do to use it with java
is to make that folder the current working directory and type
java -jar rehersal.jar $1 $2
where
$1
is the class path of your tests (or test jar) and
$2
is the category of your tests. This will evolve in future versions to be a much more natural class path
Using with Ant
At the beginning of your ant build file, or in the first target in the dependency chain, you'll need to include a taskdef
task. We recommend having an initialise
target that is the grandfather dependency of all targets in the build file. This keeps things neat: you can then put all your taskdef
s, typedef
s and the like in there.
Cut and paste this code in
<taskdef name="rehersal" classname="rehersal.ant.RehersalTask" classpathref="rehersal.classpath"/>
to have a standard
taskdef
. It uses a
classpathref
to
rehersal.classpath
. This is an Ant path definition. It needs to have a path to
rehersal.jar
and
scala-library.jar
. We also use
ant.jar
, but that should be present in the class path of the Ant ClassLoader that
taskdef
uses to load new Ant tasks.
To call rehersal, you just use rehersal
as the task name. The simplest example is
<
<rehersal classpath="tests" testcategory="Unit"/>
The classpath
is a standard Ant style class path, and it should be possible to specify it with a node of classpath, too. The class path is solely for the location of tests and any dependencies those tests need (eg drivers, third party libraries, etc). This might change in another release, so be warned (we may allow a secondary class path for libraries, to reduce the possibility of loading embedded tests in third party library code). This class path doesn't need to have rehersal.jar
, scala-library.jar
or ant.jar
.
The test category must match the category of your tests. Currently, only one category at a time can be tested. This argument is compulsory. There are also other arguments; see below.
Arguments
Argument | Required | Meaning |
classpath | Yes | Standard Ant classpath. Location of tests and tes depedencies |
classpathref | Yes | Standard Ant classpathref. Location of tests and tes depedencies; mutually incompatible with classpath. Last one set wins |
testcategory | Yes | Test category (see how to write tests). Typically 'Unit', 'Integration' or 'Acceptance' |
verbosity | Optional | Valid values are 'terse', 'regular' or 'detailed'. Default is 'regular'. |
failonerror | Optional | Boolean. Does test failure fail the build? Default is true. |
We use a new class loader for each invocation of rehersal
by ant and chain ourselves as a child of Ant's ClassLoader. We do not invoke any garbage collection currently after testing.
Using as a library
More to come! The API is currently in flux. When we add a GUI, that should hopefully iron out some of the trickier design pieces. However, the class to look at is rehersal.KnownTestSuites
, and its execute
method.