UnitTest a class for programmatic testing of classes


In order to make sure a method works correctly, a test can be implemented that assures the correct behavior.

It is a common practice to write tests to clarify how an object should respond, and it may avoid inconsistencies on the long run. A test is always a subclass of UnitTest, implementing at least one method starting with test_.


superclass: Object


see also: UnitTestScript (tests independent of classes).

Most tests are located in the CommonTest quark:


("open " ++ ("%/%".format(Quarks.local.path, "CommonTests").escapeChar($ ))).unixCmd;


Running tests


*gui 

For a graphical interface to all tests, run this line:


UnitTest.gui

*runTest(methiodName)


Run a single test in the name format "TestPolyPlayerPool:test_prepareChildrenToBundle"

UnitTest.reset; 

UnitTest.runTest("TestUnitTest:test_assert");


*runAll


runs all subclasses of UnitTest

UnitTest.reset; 

UnitTest.runAll;


run

All method names that start with test_ are invoked. 

TestUnitTest.new.run;


runTestMethod(method)


Run a single test method of this class

TestUnitTest.new.runTestMethod(TestUnitTest.findMethod(\test_assert));





Writing tests by subclassing UnitTest



YourClass.test


Runs the test class for YourClass, which is assumed to be named TestYourClass.

If no test class if found it politely declines.



UnitTests for Common library classes are kept in the CommonTests quark.

This enables you to easily install and uninstall these tests.



setUp / tearDown

Implement these methods in a subclass, to be called before and after a test.



assert(test, message, report, onFailure)

Make sure that the test returns true. Post the message if report is true. 

If onFailure is not nil, a failure stops the tests and evaluates this function.

UnitTest.new.assert(2 == 2, "Two does equal two.");

UnitTest.new.assert(2 == 2.00001, "Two does equal two.");



 

assertEquals(a, b, message, report, onFailure)

Make sure that a equals b.  Post the message if report is true. 

If onFailure is not nil, a failure stops the tests and evaluates this function.

UnitTest.new.assertEquals(2, 2, "Two does equal two.");

UnitTest.new.assertEquals(2, 2.00001, "Two does equal two.");


assertFloatEquals(a, b, message, within, report, onFailure)

Make sure that the two floats a and b equal within a given range (within). 

Post the message if report is true. 

If onFailure is not nil, a failure stops the tests and evaluates this function.

UnitTest.new.assertFloatEquals(2, 2.00001, "Two does equal two.", 0.00001);

UnitTest.new.assertFloatEquals(2, 2.001, "Two does equal two.", 0.0001);


assertArrayFloatEquals(a, b, message, within, report, onFailure)

Make sure that the two arrays of floats a and b equal within a given range (within). 

Post the message if report is true. 

If onFailure is not nil, a failure stops the tests and evaluates this function.

UnitTest.new.assertArrayFloatEquals([2, 3], [2, 3] + 0.00001, "Same Floats", 0.000001);


ifAsserts(boolean, message, ifPassedFunc, ifFailedFunc, report)

Make a further assertion only if it passed, or only if it failed.

(

a = UnitTest.new;

a.ifAsserts(2 == 3, "yes", { a.assert(2 == 4) }, { a.assert(1 == 1, "but this is correct") });

)

wait(condition, failureMessage, maxTime)

Wait for a condition, consider failed after maxTime. Only valid within a test (or a routine)

(

{

s.reboot;

UnitTest.new.wait(s.serverRunning, "server failed to boot in time", 2);

}.fork

)

bootServer(server)

Wait for server boot until continued. Only valid within a test (or a routine).

If already booted, then freeAll and create new allocators

(

{

UnitTest.new.bootServer(s);

}.fork

)


failed(method, message, report)

call failure directly.

UnitTest.new.failed(message: "this failed");


passed(method, message, report)

call failure directly.

UnitTest.new.passed(message: "this passed");




Example for a UnitTest class


TestYourClass : UnitTest {

setUp {

// this will be called before each test

}

tearDown {

// this will be called after each test

}

 

test_yourMethod {

 

  // every method named test_

  // will be run

 

  this.assert( 6 == 6, "6 should equal 6");

 

  this.assertEquals( 9, 9, "9 should equal 9");

 

  this.assertFloatEquals( 4.0 , 1.0 * 4.0 / 4.0 * 4.0, 

  "floating point math should be close to equal");

 

  // we are inside a Routine, you may wait

  1.0.wait;

 

  // this will wait until the server is booted

  this.bootServer;

 

  // if the server is already booted it will free all nodes

  // and create new allocators, giving you a clean slate

 

  p = { SinOsc.ar };

  p.play;

  p.register;

 

  // will wait until the condition is true

  // will be considered a failure after 10 seconds

  this.wait( { p.isPlaying }, "waiting for synth to play", 10);

 

}

}