I've been thinking lately about unit tests in D. The built-in support is a bit lacking. There's been many threads with this topic, even an attempt to get unit-threaded (or parts of it) into druntime/Phobos.

I was thinking, instead of trying to come up with a unit test framework that will satisfy everyone's wishes, we could create a low level unit test library in druntime. There are many styles of unit test frameworks available that look very different, but (as far as I know) most of them have very similar functionality and behavior. Although, not all of them may have all of the functionality.

The unit test library would provide functionality for registering test, before and after hooks, indicating test failures, running the tests and so on. This low level library can then be used to build different kind of unit test frameworks on top of. Be it something simple as what we have now in D, JUnit style or something like RSpec. The library would not provide functionality for finding/collecting the unit tests, that part is very framework dependent.

If this is added do druntime, we would update the existing runner to use this new library and (at least as a start) configure it to have the exact same behavior as the existing runner

To give a better idea of what I'm talking about, at the bottom is an example of how the API of the library could look like. Please don't focus on any details in the API, it only acts like any illustration to give a better understanding of the above descriptions.

Thoughts? Is this something we would like to have in druntime?

class UnitTester
{
    bool parallel;
    bool stopOnFirstFaliure;
    Formatter formatter;

    void beginTestGroup(string title = null, string file = null,
        size_t line = 0);
    void endTestGroup();

    void registerTest(void delegate() test, string title = null,
        string file = null, size_t line = 0);

void registerTest(Context)(void delegate(Context) test, Context context,
        string title = null, string file = null, size_t line = 0);

    void registerBeforeSuiteCallback(void delegate() callback);
    void registerBeforeAllCallback(void delegate() callback);
    void registerBeforeEachCallback(void delegate() callback);

    void registerAfterSuiteCallback(void delegate() callback);
    void registerAfterAllCallback(void delegate() callback);
    void registerAfterEachCallback(void delegate() callback);

    void testFailed(Expected, Actual)(Expected expected, Actual actual);
    void testPassed();
    void testSkipped(string reason = null);
    void testPending(string reason = null);

    void runAll();
    void runSpecfic(string path, size_t line = 0);
    void runSpecfic(Regex regex, string path = null);
}

--
/Jacob Carlborg

Reply via email to