README

March 21, 2012 ยท View on GitHub

Unit testing framework ('dunit')

Allows to define unittests simply as methods which names start with 'test'. The only thing necessary to create a unit test class, is to declare the mixin TestMixin inside the class. This will register the class and its test methods for the test runner.

License: Boost License 1.0. Authors: Juan Manuel Cabo Version: 0.6 Source: dunit.d Last update: 2012-03-21

     Copyright Juan Manuel Cabo 2012.

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

module ExampleTests; import std.stdio, std.string; import core.thread; import dunit;

//Minimal example: class ATestClass { mixin TestMixin;

void testExample() {
    assertEquals("bla", "b"~"la");
}

}

/**

  • Look!! no test base class needed!! */ class AbcTest { //This declaration here is the only thing needed to mark a class //as a unit test class: mixin TestMixin;

    //Variable members that start with 'test' are allowed. public int testN = 3; public int testM = 4;

    //Any method whose name starts with 'test' is run as a unit test: //(NOTE: this is bound at compile time, there is no overhead). public void test1() { assert(true); }

    public void test2() { //You can use D's assert() function: assert(1 == 2 / 2); //Or dunit convenience asserts (just edit dunit.d to add more): assertEquals(1, 2/2); //The expected and actual values will be shown in the output: assertEquals("my string looks dazzling", "my dtring looks sazzling"); }

    //Test methods with default arguments work, as long as they can //be called without arguments, ie: as testDefaultArguments() for instance: public void testDefaultArguments(int a=4, int b=3) { }

    //Even if the method is private to the unit test class, it is still run. private void test5(int a=4) { }

    //This test was disabled just by adding an underscore to the name: public void _testAnother() { assert(false, "fails"); }

    //Optional initialization and de-initialization. // setUp() and tearDown() are called around each individual test. // setUpClass() and tearDownClass() are called once around the whole unit test. public void setUp() { } public void tearDown() { } public void setUpClass() { } public void tearDownClass() { } }

class DerivedTest : AbcTest { mixin TestMixin;

//Base class tests will be run!!!!!!
//
//You can for instance override setUpClass() and change the target 
//implementation of a family of classes that you are testing.
//
//For instance: Run a set of tests against all derived classes of 
//the Stream class.  You do this by keeping all the tests in a parent
//test class, and creating a derived TestFixture for each one,
//that all it has to do is instantiate the instance under test in the
//overriden setUpClass().

}

/**

  • You can write asynchronous tests too!! Test those socket listeners of

  • yours, or your active thread objects, etc.!! */ class AsynchronousTestExample { mixin TestMixin; Thread theThread; bool threadDidItsThing;

    //Prepare the test: void setUp() { threadDidItsThing = false; theThread = new Thread(&threadFunction); }

    //Cleanup: void tearDown() { theThread.join(); theThread = null; }

    void threadFunction() { threadDidItsThing = true; }

    void testThreadActuallyRuns() { assertEquals(false, threadDidItsThing);

     //Start the thread
     theThread.start();
    
     //Assert that within a period of time (500ms by default), the variable 
     //threadDidItsThing gets toggled:
     assertWithTimeout({return threadDidItsThing;});
    

    } }

version = DUnit;

version(DUnit) {

//-All you need to run the tests, is to declare
//
//      mixin DUnitMain.
//
//-You can alternatively call 
//
//      dunit.runTests_Progress();      for java style results 
//                                      output (SHOWS COLORS IF IN UNIX !!!)
// or   
//      dunit.runTests_Tree();          for a more verbose output
//
//from your main function.

mixin DUnitMain;
//void main() {dunit.runTests_Tree();}

} else { int main (string[] args) { writeln("production"); } }

/*

  • Alternatively, you can run your DUnit tests when passing -unittest
  • to the compiler. This only needs to be declared once for the whole
  • application, and will run all the tests in all modules before the
  • application starts: */ unittest { dunit.runTests(); }

/*

Run this file with (works in Windows/Linux):

dmd exampleTests.d dunit.d
./exampleTests

The output will be (java style):

...F....F...
There were 2 failures:
1) test2(AbcTest)core.exception.AssertError@exampleTests.d(61): 
   Expected: 'my string looks dazzling', but was: 'my dtring looks sazzling'
2) test2(DerivedTest)core.exception.AssertError@exampleTests.d(61): 
   Expected: 'my string looks dazzling', but was: 'my dtring looks sazzling'

FAILURES!!!
Tests run: 10,  Failures: 2,  Errors: 0

If you use the more verbose method dunit.runTests_Tree(), then the output is:

Unit tests: 
    ATestClass
        OK:   0.01 ms  testExample()
    AbcTest
        OK:   0.00 ms  test1()
        FAILED: test2(): core.exception.AssertError@exampleTests.d(62): 
                Expected: 'my string looks dazzling', but was: 
                'my dtring looks sazzling'
        OK:   0.00 ms  testDefaultArguments()
        OK:   0.00 ms  test5()
    DerivedTest
        OK:   0.01 ms  test1()
        FAILED: test2(): core.exception.AssertError@exampleTests.d(62): 
                Expected: 'my string looks dazzling', but was: 
                'my dtring looks sazzling'
        OK:   0.00 ms  testDefaultArguments()
        OK:   0.00 ms  test5()
    AsynchronousTestExample
        OK:  11.00 ms  testThreadActuallyRuns()

HAVE FUN!

*/