Latest Releases
VersionDateRelease Notes
2006.11.16.2116th November 2006Details

Project Stuff
Home Page
Browse Subversion Repository
Sourceforge Home Page

Writing Tests
Using with the Command Line
Using with Ant

Scala Wiki
Scala Mailing List (Nabble)
Scala Mailing List (Snailmail)


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")( ()=>
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 $1is 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 taskdefs, typedefs 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.

classpathYesStandard Ant classpath. Location of tests and tes depedencies
classpathrefYesStandard Ant classpathref. Location of tests and tes depedencies; mutually incompatible with classpath. Last one set wins
testcategoryYesTest category (see how to write tests). Typically 'Unit', 'Integration' or 'Acceptance'
verbosityOptionalValid values are 'terse', 'regular' or 'detailed'. Default is 'regular'.
failonerrorOptionalBoolean. 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.