Hack to name unit tests?

Christopher Wright dhasenan at gmail.com
Thu Nov 29 13:03:11 PST 2007


Robert Fraser wrote:
> Christopher Wright wrote:
>> Robert Fraser wrote:
>>> I'm creating a Flectioned-based way to run unit tests individually 
>>> (it'll be hooked into a front-end, so you can run test suites, repeat 
>>> only failed tests after a code change, etc.)
>>>
>>> However, I have run into a problem: unit tests can't be named. Right 
>>> now I have a signature system, but I was wondering if there's any 
>>> hackish way to predictably insert a string into the generated object 
>>> file in a way that users can name unittests. That is to say, given a 
>>> function pointer, is there any way I can scan the code to see if a 
>>> name has been given to the unit test, and if so extract that name at 
>>> runtime?
>>>
>>> Ideally, it'd be as easy for the user as something like:
>>>
>>> unittest
>>> {
>>>    assert(":testName:");
>>>    // Rest of test goes here...
>>> }
>>>
>>> Right now, I have the associations being done in the front-end I'm 
>>> working on, that scans the code for comments in a particular format 
>>> and associates those with the unit tests. However, that ties the unit 
>>> test executor back-end to the code analysis front-end, so I was 
>>> hoping there's a better way.
>>>
>>> Thanks!
>>
>> class Unittest (string _name, alias _dg) : IUnittest {
>>    static string name = _name;
>>    static void delegate() test = _dg;
>> }
>>
>> Usage:
>> Unittest!("my test for wossname", {
>>    assert (false, "haven't gotten around to implementing this yet");
>> });
>>
>> Not guaranteed to work.
>>
>> Another tactic would be something like:
>>
>> class UnittestManager {
>>    static void registerCurrentTest (string name) {}
>>    static void endTest (bool success) {}
>>    static bool performTest () {}
>> }
>>
>> template Unittest (string _name, alias _dg) {
>>    unittest {
>>       UnittestManager.registerCurrentTest(_name);
>>
>>       // This lets us skip the test if we're just trying
>>       // to find out what tests there are currently.
>>       if (UnittestManager.performTest) {
>>          scope(success) UnittestManager.endTest(true);
>>          scope(failure) UnittestManager.endTest(false);
>>          _dg();
>>       }
>>    }
>> }
>>
>> mixin Unittest!("my test name", { assert (false, "not yet 
>> implemented"); });
> 
> Thanks! That's a good idea, but I want something compatible with current 
> unittest {} declarations.

You already have to modify the tests to insert the name, but you want 
something that works as a decorator inside the unittest. Can your 
unittest runner do a try/catch on a unittest? Then you could have 
something like:

void testName(string name) {
    if (collectingNames)
       throw new UnittestNameException(name);
}

struct NamedTest {
    Unittest test;
    string name;
}

...
void main () {
    NamedTest[] tests;
    collectingNames = true;
    foreach (test; getUnittests) {
        try {
            test();
        } catch (UnittestNameException e) {
            tests ~= NamedTest(test, e.name);
        }
    }
    collectingNames = false;
}

unittest {
    testName("blargh");
    assert (false, "still working on this");
}



More information about the Digitalmars-d mailing list