Hack to name unit tests?

Christopher Wright dhasenan at gmail.com
Thu Nov 29 17:29:39 PST 2007


Robert Fraser wrote:
> Christopher Wright wrote:
>> 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");
>> }
> Heh; alright; that's what I was looking for! Thanks!

No worries. It's pretty much identical in principle to mocked methods in 
dmocks, except for using exceptions to pass the name around and abort 
the method.



More information about the Digitalmars-d mailing list